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__ |