Introduction

In version two of the cloud provider 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 cloud provider API.

Prerequisites

action illustration for: Prerequisites

This article assumes a basic understanding of the cloud provider 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:

Understanding Action Objects

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://developer.mozilla.org/en-US/docs/Web/HTTP" 

				
			

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://developer.mozilla.org/en-US/docs/Web/HTTP;" 

				
			

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://developer.mozilla.org/en-US/docs/Web/HTTP"

				
			

Using Actions Objects in Practice

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 cloud provider 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

				
			

Putting It All Together

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.

Conclusion

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 the cloud provider developer's portal for more topics.