| 1 | package WebService::Scaleway; |
| 2 | |
| 3 | use 5.014000; |
| 4 | use strict; |
| 5 | use warnings; |
| 6 | |
| 7 | our $VERSION = '0.001001'; |
| 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 { |
| 158 | my $content = encode_json { action => $_[2] }; |
| 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; |
| 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). |
| 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 | |
| 318 | These methods take the ID of a resource and return the resource as a |
| 319 | blessed hashref as described in the previous section. |
| 320 | |
| 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 | |
| 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 | |
| 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. |
| 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 |
| 472 | hashref format where a resource ID is expected, unless the method's |
| 473 | documentation says otherwise. |
| 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 |
| 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>. |
| 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 |