|
1 | 1 | defmodule Doex do |
2 | | - @moduledoc """ |
3 | | -
|
4 | | - An elixir implementation of the |
5 | | - [DigitalOcean API v2](https://developers.digitalocean.com/documentation/v2/). From |
6 | | - their documentation: |
7 | | -
|
8 | | - The DigitalOcean API allows you to manage Droplets and resources within |
9 | | - the DigitalOcean cloud in a simple, programmatic way using conventional |
10 | | - HTTP requests. The endpoints are intuitive and powerful, allowing you to |
11 | | - easily make calls to retrieve information or to execute actions. |
12 | | -
|
13 | | - All of the functionality that you are familiar with in the DigitalOcean |
14 | | - control panel is also available through the API, allowing you to script |
15 | | - the complex actions that your situation requires. |
16 | | -
|
17 | | - The API documentation will start with a general overview about the design |
18 | | - and technology that has been implemented, followed by reference information |
19 | | - about specific endpoints. |
20 | | -
|
21 | | - This Elixir DigitalOcean (DO) API gives you access to the API through three means: |
22 | | -
|
23 | | - * A command line escript tool called `doex` |
24 | | - * A set of mix tasks `mix doex.*`, or |
25 | | - * Directly from Elixir code using `Doex` module |
26 | | -
|
27 | | - Each one of the mechanism above allow you to automate your infrastructure needs, |
28 | | - it more comes down to preference and environment. |
29 | | -
|
30 | | - The library name is somewhat of an acryonym for Digital Ocean (do) and Elixir (ex). |
31 | | - It is pronounced "Doakes" after the excellent character in Dexter, |
32 | | - no other symbolism to the character, just liked it and it followed with the |
33 | | - Elixir convention of putting 'ex' somewhere in the library name. |
34 | | -
|
35 | | - ## Installation |
36 | | -
|
37 | | - ### Command Line (Latest Version) |
38 | | -
|
39 | | - To install the `doex` command line tool (whose only dependency is Erlang), then |
40 | | - you can [install it using escript](https://hexdocs.pm/mix/master/Mix.Tasks.Escript.Install.html). |
41 | | -
|
42 | | -
|
43 | | - ```bash |
44 | | - # Install from GitHub |
45 | | - mix escript.install github aforward/doex |
46 | | -
|
47 | | - # Install form HEX.pm |
48 | | - mix escript.install hex doex |
49 | | - ``` |
50 | | -
|
51 | | - If you see a warning like |
52 | | -
|
53 | | - ```bash |
54 | | - warning: you must append "~/.mix/escripts" to your PATH |
55 | | - if you want to invoke escripts by name |
56 | | - ``` |
57 | | -
|
58 | | - Then, make sure to update your PATH variable. Here's how on a Mac OS X, but each |
59 | | - [environment is slightly different](https://unix.stackexchange.com/questions/26047/how-to-correctly-add-a-path-to-path). |
60 | | -
|
61 | | - ```bash |
62 | | - vi ~/.bash_profile |
63 | | -
|
64 | | - # Add a line like the following |
65 | | - PATH="$HOME/.mix/escripts:$PATH" |
66 | | - export PATH |
67 | | - ``` |
68 | | -
|
69 | | - Start a new terminal session. You will know it's working when you can *find* it using *where* |
70 | | -
|
71 | | - ``` |
72 | | - where doex |
73 | | - ``` |
74 | | -
|
75 | | - ### Command Line (Other Versions) |
76 | | -
|
77 | | - To install a specific version, branch, tag or commit, adjust any one of the following |
78 | | -
|
79 | | - ```bash |
80 | | - # Install from a specific version |
81 | | - mix escript.install hex doex 0.11.0 |
82 | | -
|
83 | | - # Install from the latest of a specific branch |
84 | | - mix escript.install github aforward/doex branch git_branch |
85 | | -
|
86 | | - # Install from a specific tag |
87 | | - mix escript.install github aforward/doex tag git_tag |
88 | | -
|
89 | | - # Install from a specific commit |
90 | | - mix escript.install github aforward/doex ref git_ref |
91 | | - ``` |
92 | | -
|
93 | | - Again, checkout [mix escript.install](https://hexdocs.pm/mix/Mix.Tasks.Escript.Install.html) for |
94 | | - more information about installing global tasks. |
95 | | -
|
96 | | - ### Mix Tasks |
97 | | -
|
98 | | - If you have an Elixir project that you want to interact with the |
99 | | - DigitalOcean API, then you install the app by adding a dependency |
100 | | - to your `mix.exs` file. |
101 | | -
|
102 | | - ```elixir |
103 | | - @deps [ |
104 | | - {:doex, "~> 0.6.1"} |
105 | | - ] |
106 | | - ``` |
107 | | -
|
108 | | - This will give you access to `mix doex.*` tasks (instead of globally installing |
109 | | - the `doex` escript). You will also have programtic access from your `Doex` module |
110 | | - as well; so you could expose feature directly within your application as well. |
111 | | -
|
112 | | - ## Configure DO Token |
113 | | -
|
114 | | - Before you can use the DO API, you will need to configure access to your DigitalOcean |
115 | | - account. For this, you will need your [API TOKEN](https://www.digitalocean.com/community/tutorials/how-to-use-the-digitalocean-api-v2#how-to-generate-a-personal-access-token) |
116 | | -
|
117 | | - Let's say your token is ABC123, then configure it as follows: |
118 | | -
|
119 | | - # using escript |
120 | | - doex init |
121 | | - doex config token ABC123 |
122 | | -
|
123 | | - # using mix tasks |
124 | | - mix doex.init |
125 | | - mix doex.config token ABC123 |
126 | | -
|
127 | | - And to confirm it's set, run |
128 | | -
|
129 | | - doex config |
130 | | -
|
131 | | - And the output should look similar to: |
132 | | -
|
133 | | - ssh_keys: [] |
134 | | - token: "ABC123" |
135 | | - url: "https://api.digitalocean.com/v2" |
136 | | -
|
137 | | - Notice the empty `ssh_keys`. Please look at [DO documentation on SSH Keys](https://www.digitalocean.com/community/tutorials/how-to-use-ssh-keys-with-digitalocean-droplets) |
138 | | - and configure them right away. With the SSH Keys set, you will have secure |
139 | | - and passwordless access to your new droplet, enabling more convient scripting. To |
140 | | - retrieve your SSH Key IDs, run the following command |
141 | | -
|
142 | | - # using escript |
143 | | - doex get /account/keys |
144 | | -
|
145 | | - # using mix tasks |
146 | | - mix doex.get /account/keys |
147 | | -
|
148 | | - The output will be similar to the following, and it's the IDs you want. |
149 | | -
|
150 | | - {:ok, |
151 | | - %{"links" => %{}, "meta" => %{"total" => 2}, |
152 | | - "ssh_keys" => [%{"fingerprint" => "18:19:20:21:22:23:24:25:26:27:28:29:30:31:32:33", |
153 | | - "id" => 555213, "name" => "mbp", |
154 | | - "public_key" => "ssh-dss ABC123"}, |
155 | | - %{"fingerprint" => "19:20:21:22:23:24:25:26:27:28:29:30:31:32:33:34", |
156 | | - "id" => 555214, "name" => "andrew13mbp", |
157 | | - "public_key" => "ssh-rsa DEF456"}]}} |
158 | | -
|
159 | | - From the example above (please adjust for your output), the IDs are `555213`, and `555214`. |
160 | | - These can be set by running |
161 | | -
|
162 | | - mix doex.config ssh_keys 555213 555214 |
163 | | -
|
164 | | - Now, every droplet you create will, by default (and can be overwritten), be accessible |
165 | | - by all computers that have those public/private keys. |
166 | | -
|
167 | | - ## Available Commands / Tasks |
168 | | -
|
169 | | - To get help on the available commands, run |
170 | | -
|
171 | | - # using escript |
172 | | - doex |
173 | | -
|
174 | | - # using mix tasks |
175 | | - mix doex |
176 | | -
|
177 | | - The output will look similar to the following |
178 | | -
|
179 | | - doex v0.6.1 |
180 | | - doex is a API client for Digital Ocean's API v2. |
181 | | -
|
182 | | - Available tasks: |
183 | | -
|
184 | | - doex block # Block the command line until a condition is met |
185 | | - doex config # Reads, updates or deletes Doex config |
186 | | - doex delete # Execute a Digital Ocean API DELETE request |
187 | | - doex droplets.create # Create a droplet on Digital Ocean |
188 | | - doex droplets.id # Locate a droplet ID, by name or tag (--tag) |
189 | | - doex droplets.tag # Tag a droplet. |
190 | | - doex get # Execute a Digital Ocean API GET request |
191 | | - doex id # Locate a ID of a resource, by name or tag (--tag) |
192 | | - doex imagelets.create # Create a DitigalOcean snapshot based on available templates |
193 | | - doex init # Initialize your doex config |
194 | | - doex ip # Get the IP of a droplet |
195 | | - doex ls # List your resources. |
196 | | - doex post # Execute a Digital Ocean API POST request |
197 | | - doex put # Execute a Digital Ocean API PUT request |
198 | | - doex scp # Secure copy a file from <src> to your droplet's <target> |
199 | | - doex snapshots.create # Creates a snapshot of an existing Digital Ocean droplet |
200 | | - doex ssh # Execute a command on your droplet |
201 | | - doex ssh.hostkey # Add the droplet hostkey to the executing server |
202 | | -
|
203 | | - Further information can be found here: |
204 | | - -- https://hex.pm/packages/doex |
205 | | - -- https://github.com/aforward/doex |
206 | | -
|
207 | | - Please note that the mix tasks and doex scripts provide identical functionality, |
208 | | - they are just structured slightly differently. |
209 | | -
|
210 | | - In general, |
211 | | -
|
212 | | - * `mix doex.<sub command> <options> <args>` for mix tasks |
213 | | - * `doex <sub command> <options> <args>` for escript |
214 | | -
|
215 | | - Make sure that have installed doex correctly for mix tasks (if you want to use mix |
216 | | - tasks), or escript (if you want to use escript). |
217 | | -
|
218 | | - ## Elixir API |
219 | | -
|
220 | | - These features are also available from within Elixir through `Doex` modules, |
221 | | - this gives you better programatic access to return data (presented as a map), |
222 | | - but in most cases probably is not required to automate your infrastructure. |
223 | | -
|
224 | | - If we start an iEX session in your project that includes the doex dependency, |
225 | | - you can access the same information in Elixir. |
226 | | -
|
227 | | - iex> Doex.config |
228 | | - %{ssh_keys: [], token: "ABC123", url: "https://api.digitalocean.com/v2"} |
229 | | -
|
230 | | - The underlying API calls are made through |
231 | | -
|
232 | | - iex> h Doex.Api |
233 | | -
|
234 | | - The `source` is the DO API endpoint *after* the `url` provided above, so to |
235 | | - access your account information, you would run |
236 | | -
|
237 | | - iex> Doex.Api.get("/account") |
238 | | -
|
239 | | - OR, you can go through the more generic `call`, providing the arguments in a map. |
240 | | -
|
241 | | - iex> Doex.Api.call(:get, %{source: "/account"}) |
242 | | -
|
243 | | - If your configurations are messed up (or other errors occur), it will look |
244 | | - similar to |
245 | | -
|
246 | | - {:error, |
247 | | - "Expected a 200, received 401", |
248 | | - %{"id" => "unauthorized", "message" => "Unable to authenticate you."}} |
249 | | -
|
250 | | - If things are working as expected, a success message looks like |
251 | | -
|
252 | | - {:ok, |
253 | | - %{"account" => %{"droplet_limit" => 99, "email" => "me@example.com", |
254 | | - "email_verified" => true, "floating_ip_limit" => 5, "status" => "active", |
255 | | - "status_message" => "", |
256 | | - "uuid" => "abcdefghabcdefghabcdefghabcdefghabcdefgh"}}} |
257 | | -
|
258 | | - To send a POST command, for example creating a new droplet, you can run |
259 | | -
|
260 | | - iex> Doex.Api.post( |
261 | | - "/droplets", |
262 | | - %{name: "dplet001", |
263 | | - region: "tor1", |
264 | | - size: "s-1vcpu-1gb", |
265 | | - image: "ubuntu-18-04-x64", |
266 | | - ssh_keys: [12345], |
267 | | - backups: false, |
268 | | - ipv6: true, |
269 | | - user_data: nil, |
270 | | - private_networking: nil, |
271 | | - volumes: nil, |
272 | | - tags: ["dplet001"]}) |
273 | | -
|
274 | | - OR, you can go through the more generic `call` |
275 | | -
|
276 | | - iex> Doex.Api.call( |
277 | | - :post, |
278 | | - %{source: "/droplets", |
279 | | - body: %{name: "dplet001", |
280 | | - region: "tor1", |
281 | | - size: "s-1vcpu-1gb", |
282 | | - image: "ubuntu-18-04-x64", |
283 | | - ssh_keys: [12345], |
284 | | - backups: false, |
285 | | - ipv6: true, |
286 | | - user_data: nil, |
287 | | - private_networking: nil, |
288 | | - volumes: nil, |
289 | | - tags: ["dplet001"]}}) |
290 | | -
|
291 | | - The underlying configs are stored in `Doex.Worker` ([OTP GenServer](https://elixir-lang.org/getting-started/mix-otp/genserver.html)). |
292 | | - If you change your configurations and need them reloaded, then call |
293 | | - and can be reloaded using |
294 | | -
|
295 | | - iex> Doex.reload |
296 | | -
|
297 | | - At present, there are no client specific convenience methods, but when there are |
298 | | - they will be located in |
299 | | -
|
300 | | - iex> Doex.Client |
301 | | -
|
302 | | - """ |
| 2 | + @external_resource "README.md" |
| 3 | + @moduledoc "README.md" |
| 4 | + |> File.read!() |
| 5 | + |> String.split("<!-- MDOC !-->") |
| 6 | + |> Enum.fetch!(1) |
303 | 7 |
|
304 | 8 | def version(), do: unquote(Mix.Project.config()[:version]) |
305 | 9 | def elixir_version(), do: unquote(System.version()) |
|
0 commit comments