DigitalOcean API implementation
Recently DigitalOcean introduced new plans for droplets, but as existing droplets stayed on the old plans I decided to use API to resize them automatically. After reading tutorial, I wrote partial client for DigitalOcean API, which I would like to share today.
API
The core part of the API which controls requests consists of three methods:
- Get access key
- Generate request template
- Send request and convert results
Here's how it looks:
/// Get Access Key
/// https://www.digitalocean.com/community/tutorials/how-to-use-the-digitalocean-api-v2
ClassMethod GetKey() As %Net.HttpRequest [ CodeMode = expression ]
{
$Get(^DigitalOcean)
}
/// Get basic request.
ClassMethod GetRequest() As %Net.HttpRequest
{
#Dim Request As %Net.HttpRequest = ##class(%Net.HttpRequest).%New()
Set Request.Https = $$$YES
Set Request.SSLConfiguration = ..#SSLConfiguration
Set Request.Server = ..#Server
Set Request.ContentType = ##class(%CSP.REST).#CONTENTTYPEJSON
Do Request.SetHeader("Authorization", "Bearer " _ ..GetKey())
Quit Request
}
/// Ececute request against DigitalOcean API.
ClassMethod ExecuteRequest(Method As %String(VALUELIST="GET,POST,PUT,DELETE"), Location As %String, Output Result As %DynamicObject, Request As %Net.HttpRequest = {..GetRequest()}, SuccessCode As %Integer = {$Case(Method, "POST":201,:200)}, Test As %Integer(MINVAL=0,MAXVAL=2) = 0) As %Status
{
Kill Result
#Dim Status As %Status = $$$OK
Set Status = Request.Send(Method, Location, Test)
If (Test '= 1) {
If (Request.HttpResponse.StatusCode '= SuccessCode) {
Set Status = $$$ERROR($$$GeneralError, $$$FormatText("Received %1 expected %2. Responce body: %3", Request.HttpResponse.StatusCode, SuccessCode, Request.HttpResponse.Data.Read($$$MaxStringLength)))
}
Set Result = {}.%FromJSON(Request.HttpResponse.Data)
}
Quit Status
}All other methods just:
- specify endpoint (required)
- specify parameters
- specify body
- call ExecuteRequest (required)
- process response
Example
Most calls to API are asynchronous, so in response the client gets ActionId which holds the current status of the original call:
/// Get information about action.
/// https://developers.digitalocean.com/documentation/v2/#retrieve-an-existing-action
/// Do ##class(Utils.DigitalOcean).GetStatus()
ClassMethod GetAction(ActionId As %Integer, Output Progress As %String(VALUELIST="in-progress,completed,errored,"), Test As %Integer(MINVAL=0,MAXVAL=2) = 0) As %Status
{
Kill Progress
#Dim Status As %Status = $$$OK
Set Location = "/v2/actions/" _ ActionId
Set Status = ..ExecuteRequest("GET", Location, .Result, , , Test)
Quit:$$$ISERR(Status) Status
Set Progress = Result.action.status
Quit Status
}This way we can minimize the amount of code for an API client since the task of technical response processing is done once (in ExecuteRequest) and API methods hold just the business logic.
Usage
To use this project:
- Import API class
- Create SSLConfiguration DefaultSSL or change SSLConfiguration parameter of Utils.DigitalOcean class to a name of a valid configuration
- Set ^DigitalOcean global to your access key value
After that, call existing API methods or add the new ones.
Conclusion
DigitalOcean API is easy to use. Structuring your API client can improve readability and lessen the amount of code you need to write.
Links