Net::Async::DigitalOcean - Async client for DigitalOcean REST APIv2
use IO::Async::Loop; my $loop = IO::Async::Loop->new; # the god-like event loop use Net::Async::DigitalOcean; my $do = Net::Async::DigitalOcean->new( loop => $loop ); $do->start_actionables; # activate polling incomplete actions # create a domain, wait for it $do->create_domain( {name => "example.com"} ) ->get; # block here # create a droplet, wait for it my $dr = $do->create_droplet({ "name" => "www.example.com", "region" => "nyc3", "size" => "s-1vcpu-1gb", "image" => "openfaas-18-04", "ssh_keys" => [], "backups" => 'true', "ipv6" => 'true', "monitoring" => 'true', }) ->get; $dr = $dr->{droplet}; # skip type # reboot $do->reboot(id => $dr->{id})->get; # reboot all droplets tagged with 'prod:web' $do->reboot(tag => 'prod:web')->get;
DigitalOcean is a cloud provider which offers you to spin up servers (droplets) with a specified OS, predefined sizes in predefined regions. You can also procure storage volumes, attach those to the droplets, make snapshots of the volumes or the whole droplet. There are also interfaces to create and manage domains and domain record, ssh keys, various kinds of images or tags to tag the above things. On top of that you can build systems with load balancers, firewalls, distributable objects (Spaces, similar to Amazon's S3). Or, you can go along with the Docker pathway and/or create and run kubernetes structures.
See the DigitalOcean Platform for more.
DigitalOcean offers a web console to administrate all this, but also a RESTy interface (and Terraform for that matter)
This client library can be used by applications to talk to the various DigitalOcean REST endpoints. But in contrast to similar libraries, such as DigitalOcean or WebService::DigitalOcean, this library operates in asynchronous mode:
Firstly, all HTTP requests are launched asynchronously, without blocking until their respective responses come in.
But more importantly, long-lasting actions, such as creating a droplet, snapshoting volumes or rebooting a set of droplets are handled by the library itself; the application does not need to keep track of these open actions, or keep polling for their completion.
The way this works is that the application first has to create the event loop and - with it - create a handle to the DigitalOcean API server:
use IO::Async::Loop; my $loop = IO::Async::Loop->new; use Net::Async::DigitalOcean; my $do = Net::Async::DigitalOcean->new( loop => $loop ); $do->start_actionables;
You also should start a timer actionables. In regular intervals it will check with the server, whether open actions have been completed or not.
With that, every method (except a few) return a Future object, such when creating a droplet:
my $f = $do->create_droplet({ "name" => "example.com", "region" => "nyc3", "size" => "s-1vcpu-1gb", "image" => "openfaas-18-04", .... });
The application can either choose to wait synchronously:
my $d = $f->get; # wait, and receive the response as HASH
or, alternatively, can specify what should happen once the result comes in:
$f->on_done( sub { my $d = shift; warn "droplet $d->{droplet}->{name} ready (well, almost)"; } );
Futures can also be combined in various ways; one extremely useful is to wait for several actions to complete in one go:
Future->wait_all( map { $do->create_volume( ... ) } qw(one two another) )->get;
When futures succeed, the application will usually get a result in form of a Perl HASH (see below). If a future fails and has been configured to have a ->on_fail handler, then that will be invoked. Otherwise an exception will be raised. The library tries to figure out what the real message from the server was.
->on_fail
Another difference to other libraries in this arena is that it does not try to artifically objectify things into classes, such as for the droplet, image and other concepts.
Instead, the library truthfully transports Perl HASHes and LISTs via JSON to the server and back; even to the point to exactly reflect the API specification . That way you can always look up what to precisely expect as result.
But as the server chooses to type results, the application will have to cope with that
my $d = $do->create_droplet({ "name" => "example.com", .... })->get; $d = $d->{droplet}; # now I have the droplet itself
To avoid being swamped the DigitalOcean server enforces several measures to limit abuse:
Limit on the number of HTTP requests within a certain time window.
In the current version this client is rather aggressively trying to get things done. If you get too many TOO_MANY_REQUESTS errors, you may want to increase the poll time of actions (see actionables).
actionables
Future version will support policies to be set by the application.
Limit on the total number of droplets to be created
Such a case will result in an exception.
Limit on the number of droplets to be created in one go
Limit in the number of snapshots
In that case the client will wait for the indicated time. That may well be several minutes!
Limit in the size of volumes
Limit in the size of droplets
There is only one object class here, that of the DigitalOcean handle. All its methods - unless specifically mentioned - typically return one Future object.
DIGITALOCEAN_API (string)
Base HTTP endpoint for the DigitalOcean APIv2
Following fields are honored:
loop (required; IO::Async::Loop)
loop
Event loop to keep things going.
endpoint (optional; string)
endpoint
If this field is completely omitted, then the DigitalOcean endpoint is chosen as default.
If the field exists, but is kept undef, then the environment variable DIGITALOCEAN_API is consulted. If that is missing, then an exception is raised.
undef
DIGITALOCEAN_API
If the field exists, and the value is defined, it will be used.
bearer (optional; string)
bearer
To be authenticated to the official DigitalOcean endpoints the library will have to send an Authentication HTTP header with the bearer information to the server. Once you have an account, you can create such a bearer token.
Authentication
If this bearer field is missing or undef, then the environment variable DIGITALOCEAN_BEARER will be consulted. If there is no such token, and the endpoint is the official one, an exception will be raised. Otherwise, the missing bearer is tolerated (as you would if you test against a local server).
DIGITALOCEAN_BEARER
throtteling (optional; string)
throtteling
This is currently not implemented.
tracing (optional; any value)
tracing
If set to something non-zero, then a HTTP trace (sending and receiving, headers and body) is written to STDERR. This helps tremendously during debugging.
STDERR
rate_limit_frequency (optional; integer; in seconds; default 5)
rate_limit_frequency
This time interval is used to regularily poll the server for incomplete actions. Note, that for that to happen, you have to start/stop the timer explicitly:
$do->start_actionables; # from now on do something with DigitalOcean $do->stop_actionables; # dont need it anymore
start_actionables ([ $interval ])
start_actionables
$interval
This starts the timer. The optional interval integer overrides what the $do object would use as default.
$do
stop_actionables
Simply stops the timer. At any time it can be restarted.
If you work with the official DigitalOcean server, then this section can/should be ignored.
This subinterface allows to communicate with test servers to better control the test environent.
meta_reset
This deletes ALL resources on the server, providing a clean slate for a following test.
meta_ping
This pings the server which simply sends a pong response.
meta_account ($account_HASH)
meta_account
$account_HASH
Typically sets/resets operational limits, such as the number of volumes or droplets to be created. This will be more detailed later.
meta_statistics
Returns eventually a rough statistics on what happened on the server.
meta_capabilities
Lists which sections (chapters) of the API specification are implemented on the server. Returns a HASH, to be detailed later.
account
Returns account information for the current user (as identified by the bearer token) as a HASH.
volumes
List all volumes.
volumes (name => $name)
$name
List all volumes with a certain name.
create_volume ($volume_HASH)
create_volume
$volume_HASH
Instigate to create a volume with your spec.
volume (id => $volume_id)
volume
$volume_id
volume (name => $name, $region)
$region
Returns volume information, the volume either identified by its id, or the name/region combination.
snapshots (volume => $volume_id)
snapshots
List volume snapshots.
create_snapshot ($volume_id, $HASH)
create_snapshot
$HASH
Creates a new volume snapshot with name and tags provided in the HASH.
name
tags
delete_volume (id => $volume_id)
delete_volume
delete_volume (name => $name, $region)
Delete a volume, either identified by its id, or the name/region combination.
delete_snapshot ($snapshot_id)
delete_snapshot
$snapshot_id
Delete volume snapshot with a given id.
volume_attach ($volume_id, $attach_HASH)
volume_attach
$attach_HASH
Attaches a given volume to a droplet specified in the HASH.
Attaching by name is NOT IMPLEMENTED.
Note that the region of the droplet and that of the volume must agree to make that work.
volume_detach ($volume_id, $attach_HASH)
volume_detach
Detach the specified volume from the droplet named in the HASH.
Detaching by name is NOT IMPLEMENTED.
volume_resize ($volume_id, $resize_HASH)
volume_resize
$resize_HASH
Resizes the volume.
domains
Lists all domains.
create_domain ($domain_HASH)
create_domain
$domain_HASH
Creates a domain entry with the given specification.
Note that you can enter here anything, as the DigitialOcean DNS servers are not necessarily authoritative for such a domain.
domain ($name)
domain
Retrieves information of a named domain.
delete_domain ($name)
delete_domain
Deletes the named domain.
domain_records
domain_records ($name, type => $record_type)
$record_type
domain_records ($name, name => $record_name)
$record_name
List domain records of the named domain; either all of them or filtered according to type or to name.
create_record ($name, $record_HASH)
create_record
$record_HASH
Create new domain record within the named domain.
domain_record ($name, $record_id)
domain_record
$record_id
Retrieves the record for a given id from the named domain.
update_record ($name, $record_id, $record_HASH)
update_record
Selectively updates information in the record hash into the domain record with that id, all for the named domain.
delete_record ($name, $record_id)
delete_record
Deletes the record with the given id from the named domain.
create_droplet ($droplet_HASH)
create_droplet
$droplet_HASH
Instigate to create new droplet(s) specified by the HASH.
If you specify not a name field, but a names field with an ARRAY of names, then multiple droplets will be created. (There is a user-specific limit on how many can be created in one go.)
names
Note that resulting droplets may have the networking information incomplete (as that seems to be determined rather late). To get this right, you will have to retrieve that droplet information a bit later.
droplet (id => $droplet_id)
droplet
$droplet_id
droplet (name => $droplet_name, $region)
$droplet_name
Retrieve droplet information based on its id, or alternatively by name and region.
droplets
List all droplets.
Listing of droplets based on name is NOT IMPLEMENTED.
droplets_all
This convenience method will return a future which - when done - will return the complete list of droplets, not just the first page.
droplets_kernels
NOT IMPLEMENTED
snapshots (droplet => $droplet_id)
List all droplet snapshots for that very droplet.
backups ($droplet_id)
backups
List backups of droplet specified by id.
droplet_actions (id => $droplet_id)
droplet_actions
droplet_actions (tag => $tag)
$tag
List all actions (also completed ones) of a specific droplet.
delete_droplet (id => $droplet_id)
delete_droplet
delete_droplet (tag => $tag)
Delete a specific droplet by id, or alternatively, a set specified by a tag.
list_neighbors
associated_resources (id => $droplet_id)
associated_resources
List volumes attached, snapshots thereof, and snapshots of the droplet itself.
delete_selective_associated_resources
delete_with_associated_resources (id => $droplet_id)
delete_with_associated_resources
Deletes the droplet and all its associated resources.
associated_resources (check_status => $droplet_id)
Check which resources are already deleted.
delete_with_associated_resources_retry
enable_backups (id => $droplet_id)
enable_backups
enable_backups (tag => $tag)
Enable regular backups (done by DigitalOcean).
disable_backups (id => $droplet_id)
disable_backups
disable_backups (tag => $tag)
Disable regular backups.
reboot (id => $droplet_id)
reboot
reboot (tag => $tag)
Reboots the specified droplet(s), either one via the id, or several via a tag.
power_cycle (id => $droplet_id)
power_cycle
power_cycle (tag => $tag)
Power-cycles the specified droplet(s), either one via the id, or several via a tag.
shutdown (id => $droplet_id)
shutdown
shutdown (tag => $tag)
Shuts down the specified droplet(s), either one via the id, or several via a tag.
power_off (id => $droplet_id)
power_off
power_off (tag => $tag)
Powers down the specified droplet(s), either one via the id, or several via a tag.
power_on (id => $droplet_id)
power_on
power_on (tag => $tag)
Powers on the specified droplet(s), either one via the id, or several via a tag.
restore (id => $droplet_id, $image)
restore
$image
restore (tag => $tag, $image)
Restores the specified droplet(s) with the image given.
password_reset (id => $droplet_id)
password_reset
password_reset (tag => $tag)
Resets password on the specified droplet(s), either one via the id, or several via a tag.
resize (id => $droplet_id, $new_size, $diskresize_yes)
resize
$new_size
$diskresize_yes
resize (tag => $tag, $new_size, $diskresize_yes)
Resizes the specified droplet(s).
rebuild (id => $droplet_id, $image)
rebuild
rebuild (tag => $tag, $image)
Rebuilds the specified droplet(s) with the image given.
NOTE: I do not understand the difference to restore.
rename (id => $droplet_id, $name)
rename
Renames the specified droplet to a new name.
enable_ipv6 (id => $droplet_id)
enable_ipv6
enable_ipv6 (tag => $tag)
Turn on IPv6 on specified droplet(s).
Note, that it takes a while on the server to get this configured.
Note, that there does not seem a way to disable IPv6 for a droplet.
enable_private_networking (id => $droplet_id)
enable_private_networking
enable_private_networking (tag => $tag)
Enables ... well.
create_droplet_snapshot (id => $droplet_id)
create_droplet_snapshot
create_droplet_snapshot (tag => $tag)
Creates a new snapshot of the specified droplet(s).
droplet_action
images
List all images.
images (type => 'distribution')
List all distribution images.
images (type => 'application')
List all application images.
images (private => 'true')
List all user images.
images (tag_name => $tag)
List all images tagged with the tag.
images_all
This convenience method returns a future, which - when done - will return complete list of images. For that it will iterate over all pages, if any, and collects all results into a list.
create_custom_image
image
update_image
image_actions
delete_image
regions
List all available regions.
sizes
List all sizes.
keys
List all keys.
create_key ($key_HASH)
create_key
$key_HASH
Create a new key with a provided HASH.
key ($key_id)
key
$key_id
Retrieve existing key given by the id.
update_key ($key_id, $key_HASH)
update_key
Selectively update fields for a given key.
delete_key ($key_id)
delete_key
Delete a specific key.
INSTALLATION file in this distribution
examples/*.pl in this distribution
t/*.t test suites in this distribution
Github
Topic Map knowledge in ontologies/digitalocean-clients.atm in this distribution
DigitalOcean API
Other Perl packages which talk to DigitalOcean are DigitalOcean and WebService::DigitalOcean
Robert Barta, <rho at devc.at>
<rho at devc.at>
Copyright 2021 Robert Barta.
This program is free software; you can redistribute it and/or modify it under the terms of the the Artistic License (2.0). You may obtain a copy of the full license at:
http://www.perlfoundation.org/artistic_license_2_0
Any use, modification, and distribution of the Standard or Modified Versions is governed by this Artistic License. By using, modifying or distributing the Package, you accept this license. Do not use, modify, or distribute the Package, if you do not accept this license.
If your Modified Version has been derived from a Modified Version made by someone other than you, you are nevertheless required to ensure that your Modified Version complies with the requirements of this license.
This license does not grant you the right to use any trademark, service mark, tradename, or logo of the Copyright Holder.
This license includes the non-exclusive, worldwide, free-of-charge patent license to make, have made, use, offer to sell, sell, import and otherwise transfer the Package with respect to any patent claims licensable by the Copyright Holder that are necessarily infringed by the Package. If you institute patent litigation (including a cross-claim or counterclaim) against any party alleging that the Package constitutes direct or contributory patent infringement, then this Artistic License to you shall terminate on the date that such litigation is filed.
Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES. THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
To install Net::Async::DigitalOcean, copy and paste the appropriate command in to your terminal.
cpanm
cpanm Net::Async::DigitalOcean
CPAN shell
perl -MCPAN -e shell install Net::Async::DigitalOcean
For more information on module installation, please visit the detailed CPAN module installation guide.