Easily Automate The DigitalOcean API From Windows And Mobile
DigitalOcean offers a set of APIs that we can access to manage their products from our application. You can create applications that act like DigitalOcean’s Droplets Control Panel. You can access DigitalOcean’s API documentation here https://developers.digitalocean.com/documentation/v2/. One reason to utilize the DigitalOcean API is to automate your cloud server management and deployment process. If you are building out separate machines for customers (using RAD Server for example) this would be a great way to automate that process. Or maybe you have a CI pipeline you’re setting up that involves automated deployment and testing of an installation process this would be a great way to automate the process through Delphi and the DigitalOcean API.
How do I set up a Windows app with DigitalOcean’s API?
This article is only an example of the initial steps in creating an automation application, so I only show how to set up the DigitalOcean’s Droplet.
In order to create a droplet (virtual private server) the /v2/droplets endpoint exists. It can be called to create a new server for you to use. Here are the two request headers needed which include authorization.
Content–Type: application/json Authorization: Bearer b7d03a6947b217efb6f3ec3bd3504582 |
Here are the list of request parameters that can be set when creating a droplet. The parameters are sent via JSON in the request body. You will see these parameters used in the Object Pascal code below.
Name | Type |
---|---|
name | String |
region | String |
size | String |
image | integer (if using an image ID), or String (if using a public image slug) |
ssh_keys | Array |
backups | Boolean |
ipv6 | Boolean |
private_networking | Boolean |
vpc_uuid | string |
user_data | String |
monitoring | Boolean |
volumes | Array |
tags | Array |
And here is some example JSON of a request body:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
{ “name”: “example.com”, “region”: “nyc3”, “size”: “s-1vcpu-1gb”, “image”: “ubuntu-16-04-x64”, “ssh_keys”: [ 107149 ], “backups”: false, “ipv6”: true, “user_data”: null, “private_networking”: null, “volumes”: null, “tags”: [ “web” ] } |
What Does the Delphi API code look like to access DigitalOcean?
We are going to use the TRESTClient TRESTRequest TRESTResponse pipeline that is built into the Delphi RTL to make it easy to handle the REST request. The library is available for all platforms that are supported by Object Pascal. The REST Library framework focuses on JSON as the representation format.
REST.Client.TRESTClient is the component that actually executes a request to a service. TRESTClient manages the HTTP connection to the service, deals with HTTP headers and proxy servers, and receives the response data. Authenticators (described later) can be attached to the client for a convenient way of adding authentication to a request.
The request (REST.Client.TRESTRequest) holds all parameters and settings that form the actual HTTP request to the service. When connected to a client-component, it can be executed (even at design time). One of the most important properties of the request is the ‘Resource’. This value forms the previously mentioned ‘second half’ of the full request-url and defines the actual action that is executed on the service. The request also defines the HTTP methods (‘get’, ‘post’, ‘put’, ‘delete’) that are used for its execution.
The response holds all the returned data from the service. The data includes the HTTP status code, error messages (if any exist), and of course the returned JSON data. A response object can be created on the fly by the client while executing a request, or the response object can be created beforehand and then connected to a client before executing a request.
We need to create 3 main methods:
First, the “CreateDroplet” API method
LRestRequest.Method := rmPOST;
LRestRequest.AddParameter(‘Authorization’, ‘Bearer ‘ + PersonalAccessToken, TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]);
LRestRequest.AddBody(LReqBody.ToJSON, TRESTContentType.ctAPPLICATION_JSON);
LRestRequest.Client := LRestClient;
LRestRequest.Execute;
LResp := (LRestRequest.Response.JSONValue as TJSONObject).GetValue(‘droplet’) as TJSONObject;
LItemLB := CreateListBoxItem(ListBox13.Count, LResp.GetValue(‘id’).Value, LResp.GetValue(‘name’).Value);
ListBox13.AddObject(LItemLB);
Result := LRestRequest.Response.JSONText;
finally
LRestRequest.Free;
LRestClient.Free;
LReqBody.Free;
end;
end;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
function CreateDroplet(): String; var LRestClient: TRESTClient; LRestRequest: TRESTRequest; LReqBody, LResp: TJSONObject; LItemLB: TListBoxItem; begin LRestClient := TRESTClient.Create(DO_DROPLET_BASE_PATH); LRestRequest:= TRESTRequest.Create(nil); LReqBody := TJSONObject.Create; try // creating new droplet req body LReqBody.AddPair(‘name’,‘DO.Delphi’+ListBox13.Count.ToString+‘.Droplet’); LReqBody.AddPair(‘region’,‘nyc3’); LReqBody.AddPair(‘size’,‘s-1vcpu-1gb’); LReqBody.AddPair(‘image’,‘ubuntu-16-04-x64’); LReqBody.AddPair(‘ssh_keys’, TJSONArray.Create); LReqBody.AddPair(‘backups’, TJSONBool.Create(false)); LReqBody.AddPair(‘ipv6’, TJSONBool.Create(True)); LReqBody.AddPair(‘user_data’, TJSONNull.Create); LReqBody.AddPair(‘private_networking’,TJSONNull.Create); LReqBody.AddPair(‘volumes’,TJSONNull.Create); LReqBody.AddPair(‘tags’,TJSONArray.Create);
LRestRequest.Method := rmPOST; LRestRequest.AddParameter(‘Authorization’, ‘Bearer ‘ + PersonalAccessToken, TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); LRestRequest.AddBody(LReqBody.ToJSON, TRESTContentType.ctAPPLICATION_JSON); LRestRequest.Client := LRestClient; LRestRequest.Execute; LResp := (LRestRequest.Response.JSONValue as TJSONObject).GetValue(‘droplet’) as TJSONObject; LItemLB := CreateListBoxItem(ListBox13.Count, LResp.GetValue(‘id’).Value, LResp.GetValue(‘name’).Value); ListBox13.AddObject(LItemLB); Result := LRestRequest.Response.JSONText; finally LRestRequest.Free; LRestClient.Free; LReqBody.Free; end; end; |
Now, the “DeleteDroplet” API method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
procedure DeleteDroplet(ADropletID: string; AItemIndex: integer); var LRestClient: TRESTClient; LRestRequest: TRESTRequest; begin LRestClient := TRESTClient.Create(DO_DROPLET_BASE_PATH + ‘/’ + ADropletID); LRestRequest:= TRESTRequest.Create(nil); try try LRestRequest.Method := rmDELETE; LRestRequest.AddParameter(‘Authorization’, ‘Bearer ‘ + PersonalAccessToken, TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); LRestRequest.Client := LRestClient; LRestRequest.Execute; ListBox13.Items.Delete(AItemIndex); except on E:Exception do ShowMessage(‘Delete droplet failed’); end; finally LRestRequest.Free; LRestClient.Free; end; end; |
Finally, code to access the “GetAllDroplets” method
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
function GetAllDroplet(APage: integer): TJSONObject; var LRestClient: TRESTClient; LRestRequest: TRESTRequest; LDroplets: TJSONArray; I: Integer; LLBDroplet: TListBoxItem; LLayout: TLayout; LBtnTrash: TButton; LDroplLabel: TLabel; begin LRestClient := TRESTClient.Create(DO_DROPLET_BASE_PATH); LRestRequest:= TRESTRequest.Create(nil); try LRestRequest.Method := rmGET; LRestRequest.AddParameter(‘Authorization’, ‘Bearer ‘ + edtPAT.Text, TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); LRestRequest.Client := LRestClient; LRestRequest.Execute; Result := LRestRequest.Response.JSONValue as TJSONObject; LDroplets := Result.GetValue(‘droplets’) as TJSONArray; I := 0; for I := 0 to LDroplets.Count – 1 do begin LLBDroplet := CreateListBoxItem(I, (LDroplets.Items[I] as TJSONObject).GetValue(‘id’).Value, (LDroplets.Items[I] as TJSONObject).GetValue(‘name’).Value); ListBox13.AddObject(LLBDroplet); end; PersonalAccessToken := edtPAT.Text; edtPAT.Visible := False; finally LRestRequest.Free; LRestClient.Free; end; end; |
What does the DigitalOcean sample Windows application look like?
Since we are using Delphi Firemonkey framework you can compile to other supported platforms also, like Android, iOS, macOS, Windows, and Linux.