In version two of the DigitalOcean API, each event that occurs creates an “Action” object. These serve both as records of events that have occurred in the past and as a way to check the progress of an on-going event. From creating a new Droplet to transferring an image to a new region, an Action object will provide you with useful information about the event.
This article will explain Action objects and show how they can be used in practice via DropletKit, the official Ruby gem for the DigitalOcean API.
This article assumes a basic understanding of the DigitalOcean API. To learn more about the API including how to obtain an access token which will be needed to complete this tutorial, see the following resources:
When initiating an event with the API, an Action object will be returned in the response. This object will contain information about the event including its status, the timestamps for when it was started and completed, and the associated resource type and ID. For instance if we where to take a snapshot of the Droplet with the ID 3164450:
curl -X POST -H 'Content-Type: application/json' \
-H 'Authorization: Bearer '$TOKEN'' \
-d '{"type":"snapshot","name":"Nifty New Snapshot"}' \
"https://api.digitalocean.com/v2/droplets/3164450/actions"
we would receive this in response:
{
"action": {
"id": 36805022,
"status": "in-progress",
"type": "snapshot",
"started_at": "2014-11-14T16:34:39Z",
"completed_at": null,
"resource_id": 3164450,
"resource_type": "droplet",
"region": "nyc3"
}
}
Note that the resource_type
is droplet
and the resource_id
is the ID of the Droplet. The status
is in-progress
. This will change to completed
once the event is finished. In order to check on the status of an Action, you can query the API for that Action directly.
curl -X GET -H 'Content-Type: application/json' \
-H 'Authorization: Bearer '$TOKEN'' \
"https://api.digitalocean.com/v2/actions/36805022"
This will return the requested action object:
{
"action": {
"id": 36805022,
"status": "completed",
"type": "snapshot",
"started_at": "2014-11-14T16:34:39Z",
"completed_at": "2014-11-14T16:38:52Z",
"resource_id": 3164450,
"resource_type": "droplet",
"region": "nyc3"
}
}
Notice how now that the status
is completed
, there is a timestamp for completed_at
as well as started_at
.
You can also access a complete history of all Actions taken on your account at the /actions
endpoint.
curl -X GET -H 'Content-Type: application/json' \
-H 'Authorization: Bearer '$TOKEN'' \
"https://api.digitalocean.com/v2/actions"
While listing all Action objects may be interesting in order to audit your history, in practice you will mostly use this endpoint in order check on the status of a process. We’ll be using droplet_kit
, the official Ruby gem for the DigitalOcean API, for these examples. It can be installed with:
gem install droplet_kit
To get started, enter the Ruby shell by running the command irb
Then import the droplet_kit
gem and set up your client using your API token:
irb(main):> require 'droplet_kit'
=> true
irb(main):> client = DropletKit::Client.new(access_token: DO_TOKEN)
Some actions are dependent on others being taken first. For instance, attempting to take a snapshot of a Droplet which is still powered on will lead to an error. A Droplet must be powered off in order to take a snapshot.
irb(main):> client.droplet_actions.snapshot(droplet_id: 4143310, name: 'Snapshot Name')
=> "{\"id\":\"unprocessable_entity\",\"message\":\"Droplet is currently on. Please power it off to run this event.\"}"
Attempting to take a snapshot immediately after initiating a shutdown action will also lead to that same error as you must ensure that the shutdown Action has completed before the snapshot can be taken. Actions can not be queued.
irb(main):> client.droplet_actions.shutdown(droplet_id: 4143310)
=> <DropletKit::Action {:@id=>43918785, :@status=>"in-progress", :@type=>"shutdown", :@started_at=>"2015-02-16T21:22:35Z", :@completed_at=>nil, :@resource_id=>4143310, :@resource_type=>"droplet", :@region=>"nyc3"}>
irb(main):> client.droplet_actions.snapshot(droplet_id: 4143310, name: 'Snapshot Name')
=> "{\"id\":\"unprocessable_entity\",\"message\":\"Droplet is currently on. Please power it off to run this event.\"}"
Like the curl
examples above, droplet_kit
also returns the Action object in response to a successfully initiated event. It can be accessed as a normal Ruby object. Saving the response into a variable will allow you to access its attributes directly:
irb(main):> snapshot = client.droplet_actions.snapshot(droplet_id: 4143310, name: 'Snapshot Name')
=> "{\"id\":\"unprocessable_entity\",\"message\":\"Droplet is currently on. Please power it off to run this event.\"}"
irb(main):> shutdown = client.droplet_actions.shutdown(droplet_id: 4143310)
=> <DropletKit::Action {:@id=>43919195, :@status=>"in-progress", :@type=>"shutdown", :@started_at=>"2015-02-16T21:32:03Z", :@completed_at=>nil, :@resource_id=>4143310, :@resource_type=>"droplet", :@region=>"nyc3"}>
irb(main):> shutdown.status
=> "in-progress"
irb(main):> shutdown.id
=> 43919195
You can then check the status of the actions:
irb(main):> action = client.actions.find(id: shutdown.id)
=> <DropletKit::Action {:@id=>43919195, :@status=>"completed", :@type=>"shutdown", :@started_at=>"2015-02-16T21:32:03Z", :@completed_at=>"2015-02-16T21:32:07Z", :@resource_id=>4143310, :@resource_type=>"droplet", :@region=>"nyc3"}>
irb(main):> action.status
=> "completed"
We can use an until
loop in Ruby to check on the progress of an Action until it has completed:
res = client.droplet_actions.shutdown(droplet_id: id)
until res.status == "completed"
res = client.actions.find(id: res.id)
sleep(2)
end
This Ruby script bellow is an example of how to check on the status of an action in practice. It powers a droplet off and uses the while
loop from above to make sure that the action has completed before moving on. Once the shutdown action has completed, it will then take a snapshot of the droplet.
#!/usr/bin/env ruby
require 'droplet_kit'
require 'json'
token = ENV['DO_TOKEN']
client = DropletKit::Client.new(access_token: token)
droplet_id = ARGV[0]
snapshot_name = ARGV[1] || Time.now.strftime("%b. %d, %Y - %H:%M:%S %Z")
def power_off(client, id)
res = client.droplet_actions.shutdown(droplet_id: id)
until res.status == "completed"
res = client.actions.find(id: res.id)
sleep(2)
end
puts " * Action status: #{res.status}"
rescue NoMethodError
puts JSON.parse(res)['message']
end
def take_snapshot(client, id, name)
res = client.droplet_actions.snapshot(droplet_id: id, name: name)
puts " * Action status: #{res.status}"
rescue NameError
puts JSON.parse(res)['message']
end
unless droplet_id.nil?
puts "Powering off droplet..."
power_off(client, droplet_id)
sleep(2)
puts "Taking snapshot..."
take_snapshot(client, droplet_id, snapshot_name)
else
puts "Power off and snapshot a droplet. Requires a droplet ID and optionally a snapshot name."
puts "Usage: #{$0} droplet_id ['snapshot name']"
end
If you save this script as a file named snapshot.rb
(or download it from this GitHub Gist), you can run it from the command line like so:
DO_TOKEN=YOUR_DO_API_TOKEN ruby snapshot.rb 12345 "My Snapshot"
Note that in order to use the script, you must export your API token as a environmental variable with the name DO_TOKEN
. The script takes two arguments, the ID of the droplet and optionally a name of the snapshot. If you do not provide a name, it will is the date and time.
Action items are an important part of the DigtialOcean API. Using them to check the status of actions is an important best practice to implement when using the API. Now that you understand how to use them, you are ready to move on to more complex use-cases of the API like:
Check out the DigitalOcean developer’s portal for more topics.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!
Sign up for Infrastructure as a Newsletter.
Working on improving health and education, reducing inequality, and spurring economic growth? We'd like to help.
Get paid to write technical tutorials and select a tech-focused charity to receive a matching donation.