Home

Awesome

DigOc

An Elixir client for the Digital Ocean API. If you find errors, please don't hesitate to file a GitHub issue.

DigOc API Documentation is available at http://hexdocs.pm/digoc

The Digital Ocean API documenation will prove helpful.

[Please note: the "examples" documentation effort here is ongoing but I believe the API is fully documented. If something there is confusing or missing or just plain wrong it's a bug; please file a GitHub issue.]

Porcelain vs. Plumbing

I'm working on a separate library that wraps this library with more developer friendly functions. That is a work in progress and in no way deprecates this code (quite the opposite: it relies on it). If you're doing anything more than a quick 'n' dirty script, it might be worth taking a look.

Authentication

Generate a Digital Ocean from the Applications & API page. Set the environment variable DIGOC_API2_TOKEN to the value of the token.

This value is available programmatically:

iex> DigOc.api_token
"12345...7890"

Results

All of the commands have two varients, e.g., DigOc.account/0 and DigOc.account!/0. The first returns a three-tuple:

iex> DigOc.account
{:ok,
 %{account: %{droplet_limit: 25, email: "quux@example.com",
     email_verified: true, uuid: "12345"}},
 %{"CF-RAY" => "1a6a3abe45cf115f-DFW",
   "Content-Type" => "application/json; charset=utf-8",
   "RateLimit-Limit" => "1200",
   "RateLimit-Remaining" => "1199",
   "RateLimit-Reset" => "1420910715",
   "Server" => "cloudflare-nginx",
   "Status" => "200 OK"}}`

The latter just the response body:

iex> DigOc.account!
%{account: %{droplet_limit: 25, email: "quux@example.com",
email_verified: true, uuid: "12345"}}

The response body is the original JSON decoded by Poison. I've given some thought to making these actual records but don't see that there's a real benefit to that (in fact, that just opens the door to more maintenance when the API changes). If you think otherwise, please let me know.

Examples

NB: The results shown have been edited and often truncated. For documentation on the datastructures that are being returned, please consult the D.O. API v2 documentation.

Account

iex(8)> DigOc.account!
%{account: %{droplet_limit: 25, email: "quuxor@example.com",
    email_verified: true, uuid: "12345"}}

Actions and Pagination

iex(10)> res = DigOc.actions!(3)
%{actions: [%{completed_at: "2015-01-10T16:07:39Z", id: 40940233,
     region: "nyc3", resource_id: 3723327, resource_type: "droplet",
     started_at: "2015-01-10T16:07:36Z", status: "completed",
     type: "destroy"},
   %{completed_at: "2015-01-09T20:31:21Z", id: 40885160, region: "nyc3",
     resource_id: 3723351, resource_type: "droplet",
     started_at: "2015-01-09T20:31:16Z", status: "completed",
     type: "destroy"},
   %{completed_at: "2015-01-09T20:31:15Z", id: 40885158, region: "nyc3",
     resource_id: 3723351, resource_type: "droplet",
     started_at: "2015-01-09T20:31:15Z", status: "completed",
     type: "rename"}],
 links: %{pages:
     %{last: "https://api.digitalocean.com/v2/actions?page=382&per_page=3",
       next: "https://api.digitalocean.com/v2/actions?page=2&per_page=3"}},
 meta: %{total: 1144}}
       
iex(12)> DigOc.Page.next?(res)
true
iex(13)> DigOc.Page.last?(res)
true
iex(14)> DigOc.Page.prev?(res)
false

iex(16)> last_res = DigOc.Page.last!(res)
%{actions: [%{completed_at: "2012-09-20T17:59:05Z", id: 137720,
              region: "nyc1", resource_id: 25817, resource_type: "droplet",
              started_at: "2012-09-20T17:58:05Z", status: "completed",
              type: "create"}],
  links: %{pages:
   %{first: "https://api.digitalocean.com/v2/actions?page=1&per_page=3",
     prev: "https://api.digitalocean.com/v2/actions?page=381&per_page=3"}},
  meta: %{total: 1144}}

iex(18)> DigOc.Page.next!(last_res)
** (RuntimeError) No bookmark for next page.
    (digoc) lib/digoc/page.ex:24: DigOc.Page.get_page/2
    (digoc) lib/digoc/page.ex:13: DigOc.Page.next!/1


iex(18)> DigOc.action!(40940233)
%{action: %{completed_at: "2015-01-10T16:07:39Z", id: 40940233,
    region: "nyc3", resource_id: 3723327, resource_type: "droplet",
    started_at: "2015-01-10T16:07:36Z", status: "completed",
    type: "destroy"}}

Domains

iex(26)>  DigOc.Domain.new!("bapi.us", "10.0.0.1")
%{domain: %{name: "bapi.us", ttl: 1800, zone_file: nil}}

iex(29)>  DigOc.Domain.new!("another.bapi.us", "10.0.0.1")
%{domain: %{name: "another.bapi.us", ttl: 1800, zone_file: nil}}

iex(30)> DigOc.domains!
%{domains: [%{name: "bapi.us", ttl: 1800,
     zone_file: "$ORIGIN bapi.us.\n..."},
   %{name: "another.bapi.us", ttl: 1800,
     zone_file: "$ORIGIN another.bapi.us.\n..."}],
  links: %{}, meta: %{total: 2}}

iex(32)> DigOc.domain!("another.bapi.us")
%{domain: %{name: "another.bapi.us", ttl: 1800,
    zone_file: "$ORIGIN another.bapi.us.\n..."}}

ex(2)> DigOc.Domain.delete("another.bapi.us")
{:ok, "", %{"Status" => "204 No Content"}}

Domain Records

iex(3)>  DigOc.Domain.Record.new!("bapi.us", %{ type: "A",
                                                name: "test.bapi.us",
                                                data: "10.0.0.2" })
%{domain_record: %{data: "10.0.0.2", id: 3833327, name: "test.bapi.us",
port: nil, priority: nil, type: "A", weight: nil}}

iex(4)> DigOc.Domain.records!("bapi.us")
%{domain_records: [%{data: "ns1.digitalocean.com", id: 3833164, name: "@",
     port: nil, priority: nil, type: "NS", weight: nil},
   %{data: "ns2.digitalocean.com", id: 3833165, name: "@", port: nil,
     priority: nil, type: "NS", weight: nil},
   %{data: "ns3.digitalocean.com", id: 3833166, name: "@", port: nil,
     priority: nil, type: "NS", weight: nil},
   %{data: "10.0.0.1", id: 3833167, name: "@", port: nil, priority: nil,
     type: "A", weight: nil},
   %{data: "10.0.0.2", id: 3833326, name: "test.bapi.us", port: nil,
     priority: nil, type: "A", weight: nil},
   %{data: "10.0.0.2", id: 3833327, name: "test.bapi.us", port: nil,
     priority: nil, type: "A", weight: nil}], links: %{}, meta: %{total: 6}}

iex(9)> DigOc.Domain.record!("bapi.us", 3833327)
%{domain_record: %{data: "10.0.0.2", id: 3833327, name: "test.bapi.us",
port: nil, priority: nil, type: "A", weight: nil}}

iex(2)> DigOc.Domain.Record.update!("bapi.us", 3833327, "prod.bapi.us")
%{domain_record: %{data: "10.0.0.2", id: 3833327, name: "prod.bapi.us",
    port: nil, priority: nil, type: "A", weight: nil}}

iex(3)> DigOc.Domain.Record.delete("bapi.us", 3833327)
{:ok, "", %{"Status" => "204 No Content"}}

Copyright

This library is (c) 2015 BAPI Consulting and released under the MIT License.