nodejs-wrapper-digitalocean-v2-api
Version:
Node.js Wrapper for the DigitalOcean v2 API
374 lines (335 loc) • 13.2 kB
JavaScript
// Require module dependencies
var fs = require('fs');
path = require('path');
https = require('https');
extend = require('node.extend');
querystring = require('querystring');
// Provider config
var API_URL = 'api.digitalocean.com';
API_PATH = '/v2';
// Request config
var HTTP_GET = 'GET';
HTTP_POST = 'POST';
HTTP_PUT = 'PUT';
HTTP_DELETE = 'DELETE';
/**
* Digitalocean api client
*
* @param {string} apiKey Required, OAuth token for authenticating requests
* @constructor
*/
var Digitalocean = function(apiKey) {
this.options = {
hostname: API_URL,
port: 443,
path: API_PATH,
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer '+apiKey
}
};
};
/**
* OAuth Request handler
*
* @param {string} endpoint Required, endpoint path
* @param {string} method Required, request method (GET, POST, PUT, DELETE)
* @param {Object} params Request parameters
* @param {Function} callback Complete
* @method _request
* @memberOf Digitalocean
*/
Digitalocean.prototype._request = function(endpoint, method, params, callback) {
// Modify default request path and method
this.options.path = this.options.path+'/'+endpoint;
this.options.method = method;
// Handle parsing request params
var postDataExists = false;
if (Object.keys(params).length > 0) {
params = querystring.stringify(params);
// Modify headers and path as it applies to the request method
switch (this.options.method) {
case HTTP_GET:
this.options.path = this.options.path+params;
break;
case HTTP_POST:
var contentLength = {'Content-Length': parmas.length};
this.options.headers = extend(this.options.headers, contentLength);
// We can tell whether or not to write to the request body by setting this to true
postDataExists = true;
break;
}
}
// Main http request
var req = https.request(this.options, function(res) {
// Prep response body
var resBody = '';
res.setEncoding('utf8');
res.on('data', function(chunk) {
// Cache each chunk of data as it arrives
resBody += chunk;
});
res.on('end', function() {
// Done streaming, safely parse the response body
resBody = JSON.parse(resBody);
err = (!resBody) ? {'message': 'Invalid JSON detected in response body'} : null;
callback(err, resBody);
});
});
// Write post params if applicable
if (this.options.method == HTTP_POST && postDataExists)
req.write(params);
// Reset path variable as to avoid concatenation
this.options.path = API_PATH;
req.end();
req.on('error', function(err) {
callback(err);
});
};
/**
* Helper method that gets basic user account information
*
* @param {Function} callback Complete
* @method _getUserInfo
* @memberOf Digitalocean
*/
Digitalocean.prototype._getUserInfo = function(callback) {
this._request('account', HTTP_GET, {}, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Helper method that creates or updates a record for a domain
*
* @param {string} method Required, request method, varies depending on action (POST, PUT)
* @param {string} domainName Required, name of an account registered domain
* @param {integer} recordId Unique numeric record ID
* @param {string} type Required, record type (A, MX, CNAME, etc)
* @param {string} name Host name, alias, or service (A, AAAA, CNAME, TXT, SRV)
* @param {string} data Varies depending on record type (A, AAAA, CNAME, MX, TXT, SRV, NS)
* @param {integer} priority Priority of the host (SRV and MX records, null otherwise)
* @param {integer} port Port the service is accessible on (SRV records, null otherwise)
* @param {integer} weight Weight of records with same priority (SRV records, null otherwise)
* @param {Function} callback Complete
* @method _setDomainRecord
* @memberOf Digitalocean
*/
Digitalocean.prototype._setDomainRecord = function(method, domainName, recordId, type, name, data, priority, port, weight, callback) {
var params = {type: type};
if (name) params.name = name;
if (data) params.data = data;
if (priority) params.priority = priority;
if (port) params.port = port;
if (weight) params.weight = weight;
this._request('domains/'+domainName+'/records'+(method == HTTP_PUT && recordId) ? '/'+recordId : '', method, params, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
// Define our global api client variable
var api;
/**
* Instantiates a new Digitalocean api client object
* Needs to be called first with a valid OAuth token
*
* @param {string} apiKey Required, OAuth token for authenticating requests
* @param {Function} callback Complete
*/
exports.connect = function(apiKey, callback) {
api = new Digitalocean(apiKey);
api._getUserInfo(function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Gets basic user account information
*
* @param {Function} callback Complete
*/
exports.getUserInfo = function(callback) {
api._getUserInfo(function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Lists all of the actions that have been executed
*
* @param {integer} page Number of pages to paginate by
* @param {integer} perPage Number of actions per page
* @param {Function} callback Complete
*/
exports.getActions = function(page, perPage, callback) {
var params = {};
if (page) parmas.page = page;
if (perPage) params.per_page = perPage;
api._request('actions', HTTP_GET, params, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Retrieves a specific action object
*
* @param {integer} actionId Required, unique numeric action ID
* @param {Function} callback Complete
*/
exports.getActionById = function(actionId, callback) {
api._request('actions/'+actionId, HTTP_GET, {}, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Retrieves a list of all domains
*
* @param {Function} callback Complete
*/
exports.getDomains = function(callback) {
api._request('domains', HTTP_GET, {}, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Adds a new domain to the DigitalOcean DNS management interface
*
* @param {string} domainName Required, registered domain name to add
* @param {string} ipAddress Required, IP address the domain will point to
* @param {Function} callback Complete
*/
exports.setDomain = function(domainName, ipAddress, callback) {
var params = {
name: domainName,
ip_address: ipAddress
};
api._request('domains', HTTP_POST, params, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Gets details about a sepcific domain
*
* @param {string} domainName Required, name of an account registered domain
* @param {Function} callback Complete
*/
exports.getDomainByName = function(domainName, callback) {
api._request('domains/'+domainName, HTTP_GET, {}, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Deletes a specific domain
*
* @param {string} domainName Required, name of an account registered domain
* @param {Function} callback Complete
*/
exports.deleteDomain = function(domainName, callback) {
api._request('domains/'+domainName, HTTP_DELETE, {}, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Gets a list of all records configured for a domain
*
* @param {string} domainName Required, name of an account registered domain
* @param {Function} callback Complete
*/
exports.getDomainRecords = function(domainName, callback) {
api._request('domains/'+domainName+'/records', HTTP_GET, {}, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Creates a new record for a domain
*
* @param {string} domainName Required, name of an account registered domain
* @param {string} type Record type (A, MX, CNAME, etc)
* @param {string} name Host name, alias, or service (A, AAAA, CNAME, TXT, SRV)
* @param {string} data Varies depending on record type (A, AAAA, CNAME, MX, TXT, SRV, NS)
* @param {integer} priority Priority of the host (SRV and MX records, null otherwise)
* @param {integer} port Port the service is accessible on (SRV records, null otherwise)
* @param {integer} weight Weight of records with same priority (SRV records, null otherwise)
* @param {Function} callback Complete
*/
exports.setDomainRecord = function(domainName, type, name, data, priority, port, weight, callback) {
api._setDomainRecord(HTTP_POST, domainName, null, type, name, data, priority, port, weight, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Updates an existing record for a domain
*
* @param {string} domainName Required, name of an account registered domain
* @param {integer} recordId Unique numeric record ID
* @param {string} type Record type (A, MX, CNAME, etc)
* @param {string} name Host name, alias, or service (A, AAAA, CNAME, TXT, SRV)
* @param {string} data Varies depending on record type (A, AAAA, CNAME, MX, TXT, SRV, NS)
* @param {integer} priority Priority of the host (SRV and MX records, null otherwise)
* @param {integer} port Port the service is accessible on (SRV records, null otherwise)
* @param {integer} weight Weight of records with same priority (SRV records, null otherwise)
* @param {Function} callback Complete
*/
exports.updateDomainRecord = function(domainName, recordId, type, name, data, priority, port, weight, callback) {
api._setDomainRecord(HTTP_PUT, domainName, recordId, type, name, data, priority, port, weight, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Deletes a record for a domain
*
* @param {string} domainName Required, name of an account registered domain
* @param {[type]} recordId Required, unique numeric record ID
* @param {Function} callback Complete
*/
exports.deleteDomainRecord = function(domainName, recordId, callback) {
api._request('domains/'+domainName+'/records/'+recordId, HTTP_DELETE, {}, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Retrieves a list of all Droplets
*
* @param {Function} callback Complete
*/
exports.getDroplets = function(callback) {
api._request('droplets', HTTP_GET, {}, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Retrieves an existing Droplet
*
* @param {string} dropletId Required, unique Droplet ID
* @param {Function} callback Complete
*/
exports.getDropletById = function(dropletId, callback) {
api._request('droplets/'+dropletId, HTTP_GET, {}, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};
/**
* Creates a new Droplet
*
* @param {string} name Required, if set to a managed domain name, a PTR record will be configured
* @param {string} region Required, unique slug identifier for region to deploy in (nyc3)
* @param {string} size Required, unique slug identifier for disk size (512mb)
* @param {string} image Required, unique image ID or the unique slug identifier (ubuntu-14-04-x64)
* @param {Array} ssh_keys Contains IDs or fingerprints of SSH keys embedded upon creation
* @param {boolean} backups Indicates whether automated backups should be enabled
* @param {boolean} ipv6 Indicates whether IPv6 should be enabled
* @param {string} userData Currently only available in regions with metadata features
* @param {boolean} privateNetworking Indicates whether private networking should be enabled
* @param {Function} callback Complete
*/
exports.setDroplet = function(mame, region, size, image, ssh_keys, backups, ipv6, userData, privateNetworking, callback) {
var params = {
name: name,
region: region,
size: size,
image: image,
};
if (sshKeys) params.ssh_keys = sshKeys;
if (backups) params.backups = backups;
if (ipv6) parmas.ipv6 = ipv6;
if (userData) params.user_data = userData;
if (privateNetworking) params.private_networking = privateNetworking;
api._request('droplets', HTTP_POST, params, function(err, data) {
callback((err) ? err : null, (data) ? data : null);
});
};