Commit | Line | Data |
---|---|---|
362a19d8 MG |
1 | package WebService::Scaleway; |
2 | ||
3 | use 5.014000; | |
4 | use strict; | |
5 | use warnings; | |
6 | ||
30c0c3c5 | 7 | our $VERSION = '0.001001'; |
362a19d8 MG |
8 | |
9 | use Carp qw/croak/; | |
10 | use HTTP::Tiny; | |
11 | use JSON::MaybeXS; | |
12 | use Scalar::Util qw/blessed/; | |
13 | ||
14 | my $ht = HTTP::Tiny->new( | |
15 | agent => "WebService-Scaleway/$VERSION ", | |
16 | verify_SSL => 1, | |
17 | ); | |
18 | ||
19 | # Instance of WebService::Scaleway with no API key | |
20 | # Used to create tokens from email/password | |
21 | my $dummy = ''; | |
22 | $dummy = bless \$dummy, __PACKAGE__; | |
23 | ||
24 | sub _account ($) { "https://account.scaleway.com$_[0]"} | |
25 | sub _api ($) { "https://api.scaleway.com$_[0]" } | |
26 | ||
27 | sub _request { | |
28 | my ($self, $method, $url, $opts) = @_; | |
29 | $opts->{headers} //= {}; | |
30 | $opts->{headers}{'X-Auth-Token'} = $$self if $$self; | |
31 | $opts->{headers}{'Content-Type'} = 'application/json'; | |
32 | my $ret = $ht->request($method, $url, $opts); | |
33 | die 'Request to Scaleway API server was unsuccessful: ' . $ret->{status} . ' ' . $ret->{reason} . '; ' . $ret->{content} unless $ret->{success}; | |
34 | ||
35 | decode_json $ret->{content} if $ret->{status} != 204; | |
36 | } | |
37 | ||
38 | sub _get { shift->_request(GET => @_) } | |
39 | sub _post { shift->_request(POST => @_) } | |
40 | sub _patch { shift->_request(PATCH => @_) } | |
41 | sub _put { shift->_request(PUT => @_) } | |
42 | sub _delete { shift->_request(DELETE => @_) } | |
43 | ||
44 | sub _tores { | |
45 | my @ret = map { bless $_, 'WebService::Scaleway::Resource' } @_; | |
46 | wantarray ? @ret : $ret[0] | |
47 | } | |
48 | ||
49 | sub new { | |
50 | my ($class, $token) = @_; | |
51 | $token = $dummy->create_token(@_[1..$#_])->id if @_ > 2; | |
52 | ||
53 | bless \$token, $class | |
54 | } | |
55 | ||
56 | BEGIN { | |
57 | my @account_res = qw/token organization user/; | |
58 | my @api_res = qw/server volume snapshot image ip security_group/; | |
59 | ||
60 | my %res = ( | |
61 | map ({ $_ => _account "/${_}s" } @account_res), | |
62 | map { $_ => _api "/${_}s" } @api_res); | |
63 | ||
64 | my %create_parms = ( | |
65 | token => [qw/email password expires/], | |
66 | server => [qw/name organization image volumes tags/], | |
67 | volume => [qw/name organization volume_type size/], | |
68 | snapshot => [qw/name organization volume_id/], | |
69 | image => [qw/name organization root_volume arch/], | |
70 | ip => [qw/ organization/], | |
71 | security_group => [qw/name organization description/], | |
72 | ); | |
73 | ||
74 | sub dynsub { | |
75 | no strict 'refs'; | |
76 | my $sub = pop; | |
77 | *$_ = $sub for @_ | |
78 | } | |
79 | ||
80 | for my $res (keys %res) { | |
81 | dynsub $res, "get_$res", sub { | |
82 | local *__ANON__ = $res; | |
83 | _tores shift->_get("$res{$res}/$_[0]")->{$res} | |
84 | }; | |
85 | ||
86 | dynsub $res.'s', "list_$res".'s', sub { | |
87 | local *__ANON__ = $res.'s'; | |
88 | my @ret = _tores @{shift->_get($res{$res})->{$res.'s'}}; | |
89 | wantarray ? @ret : $ret[0] | |
90 | }; | |
91 | ||
92 | dynsub "delete_$res", sub { | |
93 | local *__ANON__ = "delete_$res"; | |
94 | shift->_delete("$res{$res}/$_[0]") | |
95 | }; | |
96 | ||
97 | dynsub "create_$res", sub { | |
98 | local *__ANON__ = "create_$res"; | |
99 | my $self = shift; | |
100 | my $content = $_[0]; | |
101 | if (blessed $content || ref $content ne 'HASH') { | |
102 | croak "create_$res does not understand positional parameters, pass a hashref instead\n" unless $create_parms{$res}; | |
103 | my @parms = @{$create_parms{$res}}; | |
104 | $content = { map { | |
105 | $parms[$_] => (blessed $_[$_] ? $_[$_]->id : $_[$_]) } 0 .. $#_ }; | |
106 | } | |
107 | _tores $self->_post($res{$res}, { content => encode_json $content })->{$res} | |
108 | }; | |
109 | ||
110 | dynsub "update_$res", sub { | |
111 | local *__ANON__ = "update_$res"; | |
112 | my $data = blessed $_[1] ? {%{$_[1]}} : $_[1]; | |
113 | shift->_put("$res{$res}/".$data->{id}, { content => encode_json $data }) | |
114 | }; | |
115 | } | |
116 | } | |
117 | ||
118 | sub security_group_rule { | |
119 | _tores shift->_get(_api "/security_groups/$_[0]/rules/$_[1]")->{rule} | |
120 | } | |
121 | ||
122 | sub security_group_rules { | |
123 | _tores @{shift->_get(_api "/security_groups/$_[0]/rules")->{rules}} | |
124 | } | |
125 | ||
126 | BEGIN { | |
127 | *get_security_group_rule = \&security_group_rule; | |
128 | *list_security_group_rule = \&security_group_rules; | |
129 | } | |
130 | ||
131 | sub delete_security_group_rule { | |
132 | shift->_delete(_api "/security_groups/$_[0]/rules/$_[1]") | |
133 | } | |
134 | ||
135 | sub create_security_group_rule { | |
136 | my $self = shift; | |
137 | my $grp = shift; | |
138 | my $content = $_[0]; | |
139 | unless (ref $content eq 'HASH') { | |
140 | my @parms = qw/organization action direction ip_range protocol dest_port_from/; | |
141 | $content = { map { $parms[$_] => $_[$_] } 0 .. $#_ }; | |
142 | } | |
143 | $self->_post(_api "/security_groups/$grp/rules", { content => encode_json $content }) | |
144 | } | |
145 | ||
146 | sub update_security_group_rule { | |
147 | my $data = blessed $_[2] ? {%{$_[2]}} : $_[2]; | |
148 | shift->_put (_api "/security_groups/$_[0]/rules/".$data->{id}, { content => encode_json $data }) | |
149 | } | |
150 | ||
151 | sub server_actions { | |
152 | @{shift->_get(_api "/servers/$_[0]/action")->{actions}} | |
153 | } | |
154 | ||
155 | BEGIN { *list_server_actions = \&server_actions } | |
156 | ||
157 | sub perform_server_action { | |
b292204e | 158 | my $content = encode_json { action => $_[2] }; |
362a19d8 MG |
159 | _tores shift->_post(_api "/servers/$_[0]/action", { content => $content })->{task}; |
160 | } | |
161 | ||
162 | sub refresh_token { | |
163 | _tores shift->_patch(_account "/tokens/$_[0]")->{token} | |
164 | } | |
165 | ||
166 | sub server_metadata { | |
167 | _tores $dummy->_get('http://169.254.42.42/conf?format=json') | |
168 | } | |
169 | ||
170 | package # hide from PAUSE | |
171 | WebService::Scaleway::Resource; | |
172 | ||
173 | use overload '""' => sub { shift->id }; | |
174 | ||
175 | our $AUTOLOAD; | |
176 | sub AUTOLOAD { | |
177 | my ($self) = @_; | |
178 | my ($attr) = $AUTOLOAD =~ m/::([^:]*)$/s; | |
179 | die "No such attribute: $attr" unless exists $self->{$attr}; | |
180 | $self->{$attr} | |
181 | } | |
182 | ||
183 | sub can { | |
184 | my ($self, $sub) = @_; | |
185 | exists $self->{$sub} ? sub { shift->{$sub} } : undef | |
186 | } | |
187 | ||
188 | sub DESTROY {} # Don't call AUTOLOAD on destruction | |
189 | ||
190 | 1; | |
191 | __END__ | |
192 | ||
193 | =encoding utf-8 | |
194 | ||
195 | =head1 NAME | |
196 | ||
197 | WebService::Scaleway - Perl interface to Scaleway cloud server provider API | |
198 | ||
199 | =head1 SYNOPSIS | |
200 | ||
201 | use WebService::Scaleway; | |
202 | my $token = ...; # API token here | |
203 | my $sw = WebService::Scaleway->new($token); | |
204 | my $org = $sw->organizations; | |
205 | ||
206 | # Create an IP, a volume, and use them for a new Debian Jessie server | |
207 | my $ip = $sw->create_ip($org); | |
208 | my $vol = $sw->create_volume('testvol', $org, 'l_ssd', 50_000_000_000); | |
209 | my ($debian) = grep { $_->name =~ /debian jessie/i } $sw->images; | |
d06a69ab MG |
210 | my $srv = $sw->create_server('testsrv', $org, $debian, {1 => $vol->id}); |
211 | ||
212 | # Now we have a server, an IP, and two volumes (the root volume with | |
213 | # Debian Jessie, and the extra volume we just created). | |
362a19d8 MG |
214 | |
215 | # Change the server name | |
216 | $srv->{name} = 'Debian'; | |
217 | $sw->update_server($srv); | |
218 | ||
219 | # Boot the server | |
220 | $sw->perform_server_action($srv, 'poweron'); | |
221 | say "The server is now booting. To access it, do ssh root@", $ip->address; | |
222 | ||
223 | =head1 DESCRIPTION | |
224 | ||
225 | Scaleway is an IaaS provider that offers bare metal ARM cloud servers. | |
226 | WebService::Scaleway is a Perl interface to the Scaleway API. | |
227 | ||
228 | =head2 Constructors | |
229 | ||
230 | WebService::Scaleway objects are defined by their authentication | |
231 | token. There are two consructors: | |
232 | ||
233 | =over | |
234 | ||
235 | =item WebService::Scaleway->B<new>(I<$auth_token>) | |
236 | ||
237 | Construct a WebService::Scaleway object from a given authentication | |
238 | token. | |
239 | ||
240 | =item WebService::Scaleway->B<new>(I<$email>, I<$password>) | |
241 | ||
242 | Construct a WebService::Scaleway object from an authentication token | |
243 | obtained by logging in with the given credentials. | |
244 | ||
245 | =back | |
246 | ||
247 | =head2 Listing resources | |
248 | ||
249 | These methods return a list of all resources of a given type | |
250 | associated to your account. Each resource is a blessed hashref with | |
251 | C<AUTOLOAD>ed accessors (for example C<< $resource->{name} >> can be | |
252 | written as C<< $resource->name >>) and that stringifies to the ID of | |
253 | the resource: C<< $resource->id >>. | |
254 | ||
255 | There is no difference between B<resources>() and | |
256 | B<list_resources>(). | |
257 | ||
258 | =over | |
259 | ||
260 | =item $self->B<tokens> | |
261 | ||
262 | =item $self->B<list_tokens> | |
263 | ||
264 | Official documentation: L<https://developer.scaleway.com/#tokens-tokens-get>. | |
265 | ||
266 | =item $self->B<organizations> | |
267 | ||
268 | =item $self->B<list_organizations> | |
269 | ||
270 | Official documentation: L<https://developer.scaleway.com/#organizations-organizations>. | |
271 | ||
272 | =item $self->B<servers> | |
273 | ||
274 | =item $self->B<list_servers> | |
275 | ||
276 | Official documentation: L<https://developer.scaleway.com/#servers-servers-get>. | |
277 | ||
278 | =item $self->B<volumes> | |
279 | ||
280 | =item $self->B<list_volumes> | |
281 | ||
282 | Official documentation: L<https://developer.scaleway.com/#volumes-volumes-get>. | |
283 | ||
284 | =item $self->B<snapshots> | |
285 | ||
286 | =item $self->B<list_snapshots> | |
287 | ||
288 | Official documentation: L<https://developer.scaleway.com/#snapshots-snapshots-get>. | |
289 | ||
290 | =item $self->B<images> | |
291 | ||
292 | =item $self->B<list_images> | |
293 | ||
294 | Official documentation: L<https://developer.scaleway.com/#images-images-get>. | |
295 | ||
296 | =item $self->B<ips> | |
297 | ||
298 | =item $self->B<list_ips> | |
299 | ||
300 | Official documentation: L<https://developer.scaleway.com/#ips-ips-get>. | |
301 | ||
302 | =item $self->B<security_groups> | |
303 | ||
304 | =item $self->B<list_security_groups> | |
305 | ||
306 | Official documentation: L<https://developer.scaleway.com/#security-groups-security-groups-get>. | |
307 | ||
308 | =item $self->B<security_group_rules>(I<$group_id>) | |
309 | ||
310 | =item $self->B<list_security_group_rules>(I<$group_id>) | |
311 | ||
312 | Official documentation: L<https://developer.scaleway.com/#security-groups-manage-rules-get>. | |
313 | ||
314 | =back | |
315 | ||
316 | =head2 Retrieving resources | |
317 | ||
d06a69ab | 318 | These methods take the ID of a resource and return the resource as a |
362a19d8 MG |
319 | blessed hashref as described in the previous section. |
320 | ||
d06a69ab MG |
321 | You can pass a blessed hashref instead of a resource ID, and you'll |
322 | get a fresh version of the object passed. Useful if something updated | |
323 | the object in the meantime. | |
324 | ||
362a19d8 MG |
325 | There is no difference between B<resource>(I<$id>) and |
326 | B<get_resource>(I<$id>). | |
327 | ||
328 | =over | |
329 | ||
330 | =item $self->B<token>(I<$id>) | |
331 | ||
332 | =item $self->B<get_token>(I<$id>) | |
333 | ||
334 | Official documentation: L<https://developer.scaleway.com/#tokens-token-get>. | |
335 | ||
336 | =item $self->B<user>(I<$id>) | |
337 | ||
338 | =item $self->B<get_user>(I<$id>) | |
339 | ||
340 | Official documentation: L<https://developer.scaleway.com/#users-user>. | |
341 | ||
342 | =item $self->B<server>(I<$id>) | |
343 | ||
344 | =item $self->B<get_server>(I<$id>) | |
345 | ||
346 | Official documentation: L<https://developer.scaleway.com/#servers-server-get>. | |
347 | ||
348 | =item $self->B<volume>(I<$id>) | |
349 | ||
350 | =item $self->B<get_volume>(I<$id>) | |
351 | ||
352 | Official documentation: L<https://developer.scaleway.com/#volumes-volume-get>. | |
353 | ||
354 | =item $self->B<snapshot>(I<$id>) | |
355 | ||
356 | =item $self->B<get_snapshot>(I<$id>) | |
357 | ||
358 | Official documentation: L<https://developer.scaleway.com/#snapshots-snapshot-get>. | |
359 | ||
360 | =item $self->B<image>(I<$id>) | |
361 | ||
362 | =item $self->B<get_image>(I<$id>) | |
363 | ||
364 | Official documentation: L<https://developer.scaleway.com/#images-operation-on-a-single-image-get>. | |
365 | ||
366 | =item $self->B<ip>(I<$id>) | |
367 | ||
368 | =item $self->B<get_ip>(I<$id>) | |
369 | ||
370 | Official documentation: L<https://developer.scaleway.com/#ips-ip-get>. | |
371 | ||
372 | =item $self->B<security_group>(I<$id>) | |
373 | ||
374 | =item $self->B<get_security_group>(I<$id>) | |
375 | ||
376 | Official documentation: L<https://developer.scaleway.com/#security-groups-operation-on-a-security-groups-get>. | |
377 | ||
378 | =item $self->B<security_group_rule>(I<$group_id>, I<$rule_id>) | |
379 | ||
380 | =item $self->B<get_security_group_rule>(I<$group_id>, I<$rule_id>) | |
381 | ||
382 | Official documentation: L<https://developer.scaleway.com/#security-groups-operation-on-a-security-rule-get>. | |
383 | ||
384 | =back | |
385 | ||
386 | =head2 Deleting resources | |
387 | ||
d06a69ab MG |
388 | These methods take the ID of a resource and delete it. They do not |
389 | return anything. You can pass a blessed hashref instead of a resource | |
390 | ID. | |
362a19d8 MG |
391 | |
392 | =over | |
393 | ||
394 | =item $self->B<delete_token>(I<$id>) | |
395 | ||
396 | Official documentation: L<https://developer.scaleway.com/#tokens-token-delete>. | |
397 | ||
398 | =item $self->B<delete_server>(I<$id>) | |
399 | ||
400 | Official documentation: L<https://developer.scaleway.com/#servers-server-delete>. | |
401 | ||
402 | =item $self->B<delete_volume>(I<$id>) | |
403 | ||
404 | Official documentation: L<https://developer.scaleway.com/#volumes-volume-delete>. | |
405 | ||
406 | =item $self->B<delete_snapshot>(I<$id>) | |
407 | ||
408 | Official documentation: L<https://developer.scaleway.com/#snapshots-snapshot-delete>. | |
409 | ||
410 | =item $self->B<delete_image>(I<$id>) | |
411 | ||
412 | Official documentation: L<https://developer.scaleway.com/#images-operation-on-a-single-image-delete>. | |
413 | ||
414 | =item $self->B<delete_ip>(I<$id>) | |
415 | ||
416 | Official documentation: L<https://developer.scaleway.com/#ips-ip-delete>. | |
417 | ||
418 | =item $self->B<delete_security_group>(I<$id>) | |
419 | ||
420 | Official documentation: L<https://developer.scaleway.com/#security-groups-operation-on-a-security-groups-delete>. | |
421 | ||
422 | =item $self->B<delete_security_group_rule>(I<$group_id>, I<$rule_id>) | |
423 | ||
424 | Official documentation: L<https://developer.scaleway.com/#security-groups-operation-on-a-security-rule-delete>. | |
425 | ||
426 | =back | |
427 | ||
428 | =head2 Modifying resources | |
429 | ||
430 | These methods take a hashref representing a resource that already | |
431 | exists and update it. The value of C<< $resource->{id} >> is used for | |
432 | identifying this resource on the remote end. Both blessed and | |
433 | unblessed hashrefs are accepted. The updated resource is returned as a | |
434 | blessed hashref as described in L</"Listing resources">. | |
435 | ||
436 | =over | |
437 | ||
438 | =item $self->B<update_server>(I<$resource>) | |
439 | ||
440 | Official documentation: L<https://developer.scaleway.com/#servers-server-put>. | |
441 | ||
442 | =item $self->B<update_snapshot>(I<$resource>) | |
443 | ||
444 | Official documentation: L<https://developer.scaleway.com/#snapshots-snapshot-put>. | |
445 | ||
446 | =item $self->B<update_image>(I<$resource>) | |
447 | ||
448 | Official documentation: L<https://developer.scaleway.com/#images-operation-on-a-single-image-put>. | |
449 | ||
450 | =item $self->B<update_ip>(I<$resource>) | |
451 | ||
452 | Official documentation: L<https://developer.scaleway.com/#ips-ip-put>. | |
453 | ||
454 | =item $self->B<update_security_group>(I<$resource>) | |
455 | ||
456 | Official documentation: L<https://developer.scaleway.com/#security-groups-operation-on-a-security-groups-put>. | |
457 | ||
458 | =item $self->B<update_security_group_rule>(I<$group_id>, I<$resource>) | |
459 | ||
460 | Official documentation: L<https://developer.scaleway.com/#security-groups-operation-on-a-security-rule-put>. | |
461 | ||
462 | =back | |
463 | ||
464 | =head2 Creating resources | |
465 | ||
466 | These methods take either a hash that is passed directly to the API or | |
467 | a method-specific list of positional parameters. They create a new | |
468 | resource and return it as a blessed hashref as described in | |
469 | L</"Listing resources">. | |
470 | ||
471 | When using positional parameters, you can pass a resource in blessed | |
d06a69ab MG |
472 | hashref format where a resource ID is expected, unless the method's |
473 | documentation says otherwise. | |
362a19d8 MG |
474 | |
475 | Most of these methods require an organization ID. You can obtain it | |
476 | with the B<organizations> method described above. | |
477 | ||
478 | =over | |
479 | ||
480 | =item $self->B<create_token>(I<\%data>) | |
481 | ||
482 | =item $self->B<create_token>(I<$email>, I<$password>, [I<$expires>]) | |
483 | ||
484 | Authenticates a user against their username and password and returns | |
485 | an authentication token. If I<$expires> (default: false) is true, the | |
486 | token will expire. | |
487 | ||
488 | This method is called internally by the two-argument constructor. | |
489 | ||
490 | Official documentation: L<https://developer.scaleway.com/#tokens-tokens-get>. | |
491 | ||
492 | =item $self->B<create_server>(I<\%data>) | |
493 | ||
494 | =item $self->B<create_server>(I<$name>, I<$organization>, I<$image>, I<$volumes>, [I<$tags>]) | |
495 | ||
496 | Creates and returns a new server. | |
497 | ||
498 | I<$name> is the server name. I<$organization> is the organization ID. | |
499 | I<$image> is the image ID. I<$volumes> is a "sparse array" (hashref | |
d06a69ab MG |
500 | from indexes to volume IDs, indexed from 1) of B<extra> volumes (that |
501 | is, volumes other than the root volume). I<$tags> is an optional | |
502 | arrayref of tags. | |
503 | ||
504 | For the I<$volumes> parameter you can pass hashrefs that describe | |
505 | volumes instead of volume IDs. This will create new volumes. The | |
506 | hashrefs are (presumably) passed to B<create_volume>. An example | |
507 | inspired by the official documentation: | |
508 | ||
509 | $volumes = { 1 => { | |
510 | name => "vol_demo", | |
511 | organization => "ecc1c86a-eabb-43a7-9c0a-77e371753c0a", | |
512 | size => 10_000_000_000, | |
513 | volume_type => "l_sdd", | |
514 | }}; | |
515 | ||
516 | Note that there B<may not> be any blessed hashrefs inside I<$volumes>. | |
362a19d8 MG |
517 | |
518 | Official documentation: L<https://developer.scaleway.com/#servers-servers-get>. | |
519 | ||
520 | =item $self->B<create_volume>(I<\%data>) | |
521 | ||
522 | =item $self->B<create_volume>(I<$name>, I<$organization>, I<$volume_type>, I<$size>) | |
523 | ||
524 | Creates and returns a new volume. I<$volume_type> currently must be | |
525 | C<l_ssd>. I<$size> is the size in bytes. | |
526 | ||
527 | Official documentation: L<https://developer.scaleway.com/#volumes-volumes-get>. | |
528 | ||
529 | =item $self->B<create_snapshot>(I<\%data>) | |
530 | ||
531 | =item $self->B<create_snapshot>(I<$name>, I<$organization>, I<$volume_id>) | |
532 | ||
533 | Creates and returns a snapshot of the volume I<$volume_id>. | |
534 | ||
535 | Official documentation: L<https://developer.scaleway.com/#snapshots-snapshots-get>. | |
536 | ||
537 | =item $self->B<create_image>(I<\%data>) | |
538 | ||
539 | =item $self->B<create_image>(I<$name>, I<$organization>, I<$root_volume>, I<$arch>) | |
540 | ||
541 | Creates and returns an image from the volume I<$root_volume>. I<$arch> | |
542 | is the architecture of the image (currently must be C<"arm">). | |
543 | ||
544 | Official documentation: L<https://developer.scaleway.com/#images-images-get>. | |
545 | ||
546 | =item $self->B<create_ip>(I<\%data>) | |
547 | ||
548 | =item $self->B<create_ip>(I<$organization>) | |
549 | ||
550 | Official documentation: L<https://developer.scaleway.com/#ips-ips-get>. | |
551 | ||
552 | =item $self->B<create_security_group>(I<\%data>) | |
553 | ||
554 | =item $self->B<create_security_group>(I<$name>, I<$organization>, I<$description>) | |
555 | ||
556 | Official documentation: L<https://developer.scaleway.com/#security-groups-security-groups-get>. | |
557 | ||
558 | =item $self->B<create_security_group_rule>(I<$group_id>) | |
559 | ||
560 | =item $self->B<create_security_group_rule>(I<$group_id>, I<$organization>, I<$action>, I<$direction>, I<$ip_range>, I<$protocol>, [<$dest_port_from>]) | |
561 | ||
562 | ||
563 | Official documentation: L<https://developer.scaleway.com/#security-groups-manage-rules-get>. | |
564 | ||
565 | =back | |
566 | ||
567 | =head2 Miscellaneous methods | |
568 | ||
569 | These are methods that don't fit any previous category. Any use of | |
570 | "blessed hashref" refers to the concept described in L</"Listing | |
571 | resources">. Wherever a resource ID is expected, you can instead pass | |
572 | a resource as a blessed hashref and the method will call C<< ->id >> | |
573 | on it for you. | |
574 | ||
575 | =over | |
576 | ||
577 | =item $self->B<server_actions>(I<$server_id>) | |
578 | ||
579 | =item $self->B<list_server_actions>(I<$server_id>) | |
580 | ||
581 | Returns a list of strings representing possible actions you can | |
582 | perform on the given server. Example actions are powering on/off a | |
583 | server or rebooting it. | |
584 | ||
585 | Official documentation: L<https://developer.scaleway.com/#servers-actions-get> | |
586 | ||
587 | =item $self->B<perform_server_action>(I<$server_id>, I<$action>) | |
588 | ||
589 | Performs an action on a server. I<$action> is one of the strings | |
590 | returned by B<server_actions>. The function returns a blessed hashref | |
591 | with information about the task. | |
592 | ||
593 | This is not very useful, as this module does not currently offer any | |
594 | function for tracking tasks. | |
595 | ||
596 | Official documentation: L<https://developer.scaleway.com/#servers-actions-post> | |
597 | ||
598 | =item $self->B<refresh_token>(I<$token_id>) | |
599 | ||
600 | This method takes the ID of an expirable token, extends its expiration | |
601 | date by 30 minutes, and returns the new token as a blessed hashref. | |
602 | ||
603 | Official documentation: L<https://developer.scaleway.com/#tokens-token-patch> | |
604 | ||
605 | =item $self->B<server_metadata> | |
606 | ||
607 | This method can only be called from a Scaleway server. It returns | |
608 | information about the server as a blessed hashref. | |
609 | ||
610 | Official documentation: L<https://developer.scaleway.com/#metadata-c1-server-metadata> | |
611 | ||
612 | =back | |
613 | ||
614 | =head1 SEE ALSO | |
615 | ||
616 | L<https://developer.scaleway.com/> | |
617 | ||
618 | =head1 AUTHOR | |
619 | ||
620 | Marius Gavrilescu, E<lt>marius@ieval.roE<gt> | |
621 | ||
622 | =head1 COPYRIGHT AND LICENSE | |
623 | ||
624 | Copyright (C) 2015 by Marius Gavrilescu | |
625 | ||
626 | This library is free software; you can redistribute it and/or modify | |
627 | it under the same terms as Perl itself, either Perl version 5.20.2 or, | |
628 | at your option, any later version of Perl 5 you may have available. | |
629 | ||
630 | ||
631 | =cut |