| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package OvhApi; |
|
2
|
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
419
|
use strict; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
25
|
|
|
4
|
1
|
|
|
1
|
|
3
|
use warnings; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
31
|
|
|
5
|
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = 0.2; |
|
7
|
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
|
|
9
|
1
|
|
|
1
|
|
285
|
use OvhApi::Answer; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
21
|
|
|
10
|
|
|
|
|
|
|
|
|
11
|
1
|
|
|
1
|
|
4
|
use Carp qw{ carp croak }; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
33
|
|
|
12
|
1
|
|
|
1
|
|
3
|
use List::Util 'first'; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
57
|
|
|
13
|
1
|
|
|
1
|
|
520
|
use LWP::UserAgent (); |
|
|
1
|
|
|
|
|
28530
|
|
|
|
1
|
|
|
|
|
19
|
|
|
14
|
1
|
|
|
1
|
|
7
|
use JSON (); |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
14
|
|
|
15
|
1
|
|
|
1
|
|
494
|
use Digest::SHA1 'sha1_hex'; |
|
|
1
|
|
|
|
|
513
|
|
|
|
1
|
|
|
|
|
61
|
|
|
16
|
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
|
20
|
|
|
|
|
|
|
# Class constants |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
use constant { |
|
23
|
1
|
|
|
|
|
619
|
OVH_API_EU => 'https://eu.api.ovh.com/1.0', |
|
24
|
|
|
|
|
|
|
OVH_API_CA => 'https://ca.api.ovh.com/1.0', |
|
25
|
1
|
|
|
1
|
|
5
|
}; |
|
|
1
|
|
|
|
|
1
|
|
|
26
|
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# End - Class constants |
|
28
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
|
29
|
|
|
|
|
|
|
|
|
30
|
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
|
33
|
|
|
|
|
|
|
# Class variables |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
my $UserAgent = LWP::UserAgent->new(timeout => 10); |
|
36
|
|
|
|
|
|
|
my $Json = JSON->new->allow_nonref; |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
my @accessRuleMethods = qw{ GET POST PUT DELETE }; |
|
39
|
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
# End - Class variables |
|
41
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
|
42
|
|
|
|
|
|
|
|
|
43
|
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
|
|
45
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
|
46
|
|
|
|
|
|
|
# Class methods |
|
47
|
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
sub new |
|
49
|
|
|
|
|
|
|
{ |
|
50
|
0
|
|
|
0
|
0
|
|
my @keys = qw{ applicationKey applicationSecret consumerKey }; |
|
51
|
|
|
|
|
|
|
|
|
52
|
0
|
|
|
|
|
|
my ($class, %params) = @_; |
|
53
|
|
|
|
|
|
|
|
|
54
|
0
|
0
|
|
|
|
|
if (my @missingParameters = grep { not $params{$_} } qw{ applicationKey applicationSecret }) |
|
|
0
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
{ |
|
56
|
0
|
|
|
|
|
|
local $" = ', '; |
|
57
|
0
|
|
|
|
|
|
croak "Missing parameter: @missingParameters"; |
|
58
|
|
|
|
|
|
|
} |
|
59
|
|
|
|
|
|
|
|
|
60
|
0
|
0
|
0
|
|
|
|
unless ($params{'type'} and grep { $params{'type'} eq $_ } (OVH_API_EU, OVH_API_CA)) |
|
|
0
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
{ |
|
62
|
0
|
|
|
|
|
|
carp 'Missing or invalid type parameter: defaulting to OVH_API_EU'; |
|
63
|
|
|
|
|
|
|
} |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
my $self = { |
|
66
|
0
|
|
0
|
|
|
|
_type => ($params{'type'} or OVH_API_EU), |
|
67
|
|
|
|
|
|
|
}; |
|
68
|
|
|
|
|
|
|
|
|
69
|
0
|
|
|
|
|
|
@$self{@keys} = @params{@keys}; |
|
70
|
|
|
|
|
|
|
|
|
71
|
0
|
|
|
|
|
|
bless $self, $class; |
|
72
|
|
|
|
|
|
|
} |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub setRequestTimeout |
|
75
|
|
|
|
|
|
|
{ |
|
76
|
0
|
|
|
0
|
1
|
|
my ($class, %params) = @_; |
|
77
|
|
|
|
|
|
|
|
|
78
|
0
|
0
|
|
|
|
|
if ($params{'timeout'} =~ /^\d+$/) |
|
|
|
0
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
{ |
|
80
|
0
|
|
|
|
|
|
$UserAgent->timeout($params{'timeout'}); |
|
81
|
|
|
|
|
|
|
} |
|
82
|
|
|
|
|
|
|
elsif (exists $params{'timeout'}) |
|
83
|
|
|
|
|
|
|
{ |
|
84
|
0
|
|
|
|
|
|
carp "Invalid timeout: $params{'timeout'}"; |
|
85
|
|
|
|
|
|
|
} |
|
86
|
|
|
|
|
|
|
else |
|
87
|
|
|
|
|
|
|
{ |
|
88
|
0
|
|
|
|
|
|
carp 'Missing parameter: timeout'; |
|
89
|
|
|
|
|
|
|
} |
|
90
|
|
|
|
|
|
|
} |
|
91
|
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
# End - Class methods |
|
93
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
|
94
|
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
|
98
|
|
|
|
|
|
|
# Instance methods |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
sub rawCall |
|
101
|
|
|
|
|
|
|
{ |
|
102
|
0
|
|
|
0
|
1
|
|
my ($self, %params) = @_; |
|
103
|
|
|
|
|
|
|
|
|
104
|
0
|
|
|
|
|
|
my $method = lc $params{'method'}; |
|
105
|
0
|
0
|
|
|
|
|
my $url = $self->{'_type'} . (substr($params{'path'}, 0, 1) eq '/' ? '' : '/') . $params{'path'}; |
|
106
|
|
|
|
|
|
|
|
|
107
|
0
|
|
|
|
|
|
my %httpHeaders; |
|
108
|
|
|
|
|
|
|
|
|
109
|
0
|
|
|
|
|
|
my $body = ''; |
|
110
|
0
|
|
|
|
|
|
my %content; |
|
111
|
|
|
|
|
|
|
|
|
112
|
0
|
0
|
0
|
|
|
|
if ($method ne 'get' and $method ne 'delete') |
|
113
|
|
|
|
|
|
|
{ |
|
114
|
0
|
|
|
|
|
|
$body = $Json->encode($params{'body'}); |
|
115
|
|
|
|
|
|
|
|
|
116
|
0
|
|
|
|
|
|
$httpHeaders{'Content-type'} = 'application/json'; |
|
117
|
0
|
|
|
|
|
|
$content{'Content'} = $body; |
|
118
|
|
|
|
|
|
|
} |
|
119
|
|
|
|
|
|
|
|
|
120
|
0
|
0
|
|
|
|
|
unless ($params{'noSignature'}) |
|
121
|
|
|
|
|
|
|
{ |
|
122
|
0
|
|
|
|
|
|
my $now = $self->_timeDelta + time; |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
$httpHeaders{'X-Ovh-Consumer'} = $self->{'consumerKey'}, |
|
125
|
|
|
|
|
|
|
$httpHeaders{'X-Ovh-Timestamp'} = $now, |
|
126
|
|
|
|
|
|
|
$httpHeaders{'X-Ovh-Signature'} = '$1$' . sha1_hex(join('+', ( |
|
127
|
|
|
|
|
|
|
# Full signature is '$1$' followed by the hex digest of the SHA1 of all these data joined by a + sign |
|
128
|
|
|
|
|
|
|
$self->{'applicationSecret'}, # Application secret |
|
129
|
0
|
|
|
|
|
|
$self->{'consumerKey'}, # Consumer key |
|
130
|
|
|
|
|
|
|
uc $method, # HTTP method (uppercased) |
|
131
|
|
|
|
|
|
|
$url, # Full URL |
|
132
|
|
|
|
|
|
|
$body, # Full body |
|
133
|
|
|
|
|
|
|
$now, # Curent OVH server time |
|
134
|
|
|
|
|
|
|
))); |
|
135
|
|
|
|
|
|
|
} |
|
136
|
|
|
|
|
|
|
|
|
137
|
0
|
|
|
|
|
|
$httpHeaders{'X-Ovh-Application'} = $self->{'applicationKey'}, |
|
138
|
|
|
|
|
|
|
|
|
139
|
|
|
|
|
|
|
return OvhApi::Answer->new(response => $UserAgent->$method($url, %httpHeaders, %content)); |
|
140
|
|
|
|
|
|
|
} |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
sub requestCredentials |
|
143
|
|
|
|
|
|
|
{ |
|
144
|
0
|
|
|
0
|
1
|
|
my ($self, %params) = @_; |
|
145
|
|
|
|
|
|
|
|
|
146
|
0
|
0
|
|
|
|
|
croak 'Missing parameter: accessRules' unless $params{'accessRules'}; |
|
147
|
0
|
0
|
|
|
|
|
croak 'Invalid parameter: accessRules' if ref $params{'accessRules'} ne 'ARRAY'; |
|
148
|
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
my @rules = map { |
|
150
|
0
|
0
|
|
|
|
|
croak 'Invalid access rule: must be HASH ref' if ref ne 'HASH'; |
|
151
|
|
|
|
|
|
|
|
|
152
|
0
|
|
|
|
|
|
my %rule = %$_; |
|
153
|
|
|
|
|
|
|
|
|
154
|
0
|
|
|
|
|
|
$rule{'method'} = uc $rule{'method'}; |
|
155
|
|
|
|
|
|
|
|
|
156
|
0
|
0
|
0
|
|
|
|
croak 'Access rule must have method and path keys' unless $rule{'method'} and $rule{'path'}; |
|
157
|
0
|
0
|
|
0
|
|
|
croak 'Invalid access rule method' unless first { $_ eq $rule{'method'} } (@accessRuleMethods, 'ALL'); |
|
|
0
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
|
|
159
|
0
|
0
|
|
|
|
|
if ($rule{'method'} eq 'ALL') |
|
160
|
|
|
|
|
|
|
{ |
|
161
|
0
|
|
|
|
|
|
map { path => $rule{'path'}, method => $_ }, @accessRuleMethods; |
|
162
|
|
|
|
|
|
|
} |
|
163
|
|
|
|
|
|
|
else |
|
164
|
|
|
|
|
|
|
{ |
|
165
|
0
|
|
|
|
|
|
\%rule |
|
166
|
|
|
|
|
|
|
} |
|
167
|
0
|
|
|
|
|
|
} @{ $params{'accessRules'} }; |
|
|
0
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
|
|
169
|
0
|
|
|
|
|
|
return $self->post(path => '/auth/credential/', noSignature => 1, body => { accessRules => \@rules }); |
|
170
|
|
|
|
|
|
|
} |
|
171
|
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
# Generation of helper subs: simple wrappers to rawCall |
|
173
|
|
|
|
|
|
|
# Generate: get(), post(), put(), delete() |
|
174
|
|
|
|
|
|
|
{ |
|
175
|
1
|
|
|
1
|
|
4
|
no strict 'refs'; |
|
|
1
|
|
|
|
|
1
|
|
|
|
1
|
|
|
|
|
124
|
|
|
176
|
|
|
|
|
|
|
|
|
177
|
|
|
|
|
|
|
for my $method (qw{ get post put delete }) |
|
178
|
|
|
|
|
|
|
{ |
|
179
|
0
|
|
|
0
|
|
|
*$method = sub { rawCall(@_, 'method', $method ) }; |
|
180
|
|
|
|
|
|
|
} |
|
181
|
|
|
|
|
|
|
} |
|
182
|
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
|
184
|
|
|
|
|
|
|
# Private part |
|
185
|
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
sub _timeDelta |
|
187
|
|
|
|
|
|
|
{ |
|
188
|
0
|
|
|
0
|
|
|
my ($self, %params) = @_; |
|
189
|
|
|
|
|
|
|
|
|
190
|
0
|
0
|
|
|
|
|
unless (defined $self->{'_timeDelta'}) |
|
191
|
|
|
|
|
|
|
{ |
|
192
|
0
|
0
|
|
|
|
|
if (my $ServerTimeResponse = $self->get(path => 'auth/time', noSignature => 1)) |
|
193
|
|
|
|
|
|
|
{ |
|
194
|
0
|
|
|
|
|
|
$self->{'_timeDelta'} = ($ServerTimeResponse->content - time); |
|
195
|
|
|
|
|
|
|
} |
|
196
|
|
|
|
|
|
|
else |
|
197
|
|
|
|
|
|
|
{ |
|
198
|
0
|
|
|
|
|
|
return 0; |
|
199
|
|
|
|
|
|
|
} |
|
200
|
|
|
|
|
|
|
} |
|
201
|
|
|
|
|
|
|
|
|
202
|
0
|
|
|
|
|
|
return $self->{'_timeDelta'}; |
|
203
|
|
|
|
|
|
|
} |
|
204
|
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
# End - Instance methods |
|
206
|
|
|
|
|
|
|
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # |
|
207
|
|
|
|
|
|
|
|
|
208
|
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
return 42; |
|
210
|
|
|
|
|
|
|
|
|
211
|
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
__END__ |