UNPKG

@yawetse/pkgcloud

Version:

An infrastructure-as-a-service agnostic cloud library for node.js

442 lines (381 loc) 12.5 kB
/* * zones.js: Rackspace DNS client zone functionality * * (C) 2013 Rackspace * Ken Perkins * MIT LICENSE * */ var urlJoin = require('url-join'), pkgcloud = require('../../../../../lib/pkgcloud'), _ = require('underscore'), dns = pkgcloud.providers.rackspace.dns; var _urlPrefix = 'domains'; module.exports = { /** * @name Client.getZones * * @description getZones retrieves your list of zones * * @param {Object|Function} details provides filters on your zones request * @param {Function} callback handles the callback of your api call */ getZones: function (details, callback) { var self = this; if (typeof(details) === 'function') { callback = details; details = {}; } var requestOptions = { path: _urlPrefix }; requestOptions.qs = _.pick(details, 'name'); return self._request(requestOptions, function (err, body, res) { return err ? callback(err) : callback(null, body.domains.map(function (result) { return new dns.Zone(self, result); }), res); }); }, /** * @name Client.getZone * * @description Gets the details for a specified zone id * * @param {String|object} zone the zone id of the requested zone * @param {Function} callback handles the callback of your api call */ getZone: function (zone, callback) { var self = this, zoneId = zone instanceof dns.Zone ? zone.id : zone; self._request({ path: urlJoin(_urlPrefix, zoneId) }, function (err, body, res) { return err ? callback(err) : callback(null, new dns.Zone(self, body), res); }); }, /** * @name Client.createZone * * @description register a new zone in the rackspace cloud dns * * @param {Object} details the information for your new zone * @param {Function} callback handles the callback of your api call */ createZone: function (details, callback) { this.createZones([ details ], function (err, zones) { if (err) { return callback(err); } if (zones && zones.length === 1) { return callback(err, zones[0]); } else { return callback(new Error('Unexpected error when creating single zone'), zones); } }); }, /** * @name Client.createZones * * @description register a new zone in the rackspace cloud dns * * @param {Array} zones the array of zones to create * @param {Function} callback handles the callback of your api call */ createZones: function (zones, callback) { var self = this; var listOfZones = []; _.each(zones, function (zone) { ['name', 'email'].forEach(function (required) { if (!zone[required]) { throw new Error('details.' + required + ' is a required argument.'); } }); var newZone = { name: zone.name, emailAddress: zone.email }; if (zone.ttl && typeof(zone.ttl) === 'number' && zone.ttl >= 300) { newZone.ttl = zone.ttl; } if (zone.comment) { newZone.comment = zone.comment; } listOfZones.push(newZone); }); var requestOptions = { path: _urlPrefix, method: 'POST', body: { domains: listOfZones } }; self._asyncRequest(requestOptions, function (err, result) { return err ? callback(err) : callback(err, result.response.domains.map(function (domain) { return new dns.Zone(self, domain); })); }); }, /** * @name Client.importZone * * @description This call provisions a new DNS zone under the account * specified by the BIND 9 formatted file configuration contents defined * in the request object. * * @param {Object} details the information for your new zone * @param {Function} callback handles the callback of your api call */ importZone: function (details, callback) { var self = this; ['contentType', 'contents'].forEach(function (required) { if (!details[required]) { throw new Error('details.' + required + ' is a required argument.'); } }); if (details.contentType !== 'BIND_9') { callback(new Error({ invalidRequest: true })); return; } var importedZone = { contentType: details.contentType, contents: details.contents }; var requestOptions = { path: urlJoin(_urlPrefix, 'import'), method: 'POST', body: { domains: [ importedZone ] } }; self._asyncRequest(requestOptions, function (err, result) { return err ? callback(err) : callback(err, result.response.domains.map(function (domain) { return new dns.Zone(self, domain); })[0]); }); }, /** * @name Client.exportZone * * @description This call exports a provided domain as a BIND zone file * * @param {Object|String} zone the information for your new zone * @param {Function} callback handles the callback of your api call */ exportZone: function (zone, callback) { var self = this, zoneId = zone instanceof dns.Zone ? zone.id : zone; var requestOptions = { path: urlJoin(_urlPrefix, zoneId, 'export'), method: 'GET' }; self._asyncRequest(requestOptions, function (err, result) { return err ? callback(err) : callback(err, result.response); }); }, /** * @name Client.updateZone * @description update a zone * @param {Zone} zone the zone to update * @param {Function} callback handles the callback of your api call */ updateZone: function (zone, callback) { this.updateZones([ zone ], callback); }, /** * @name Client.updateZones * @description update an array of zones * @param {Array} zones the array of zones to update * @param {Function} callback handles the callback of your api call */ updateZones: function (zones, callback) { var self = this; var data = []; _.each(zones, function (zone) { if (!(zone instanceof dns.Zone)) { return; } var update = { id: zone.id, ttl: zone.ttl, emailAddress: zone.emailAddress, comment: zone.comment }; data.push(update); }); var requestOptions = { path: _urlPrefix, method: 'PUT', body: { domains: data } }; self._asyncRequest(requestOptions, function(err) { callback(err); }); }, /** * @name Client.deleteZone * @description delete a zone * @param {Zone} zone the zone to delete * @param {object|Function} options options for the deleteZone call * @param {Function} callback handles the callback of your api call */ deleteZone: function (zone, options, callback) { this.deleteZones([ zone ], options, callback); }, /** * @name Client.deleteZones * @description delete an array of zones * @param {Array} zones the array of zones or zoneIds to delete * @param {object|Function} options options for the deleteZones call * @param {Function} callback handles the callback of your api call */ deleteZones: function (zones, options, callback) { var self = this; if (typeof(options) === 'function') { callback = options; options = {}; } var zoneIds = []; _.each(zones, function (zone) { if (zone instanceof dns.Zone) { zoneIds.push(zone.id); } else { zoneIds.push(zone); } }); var deleteSubzones = typeof options.deleteSubzones === 'boolean' ? options.deleteSubzones : true; // HACK: Can't use qs here as it puts array keys with index location // which breaks API parsing of supplied ids // https://github.com/visionmedia/node-querystring/issues/71 var requestOptions = { path: _urlPrefix + '?' + zoneIds.map(function(z) { return 'id=' + z }).join('&') + '&deleteSubzones=' + deleteSubzones.toString(), method: 'DELETE' }; self._asyncRequest(requestOptions, function(err) { return callback(err); }); }, /** * @name Client.getZoneChanges * @description get a list of changes for a provided zone, optionally setting a date to filter by * @param {Zone} zone the zone or zoneId for the changes * @param {object|Function} options options for call * @param {Date} [options.since] changes after given date * @param {Function} callback handles the callback of your api call */ getZoneChanges: function (zone, options, callback) { var self = this, zoneId = zone instanceof dns.Zone ? zone.id : zone; if (typeof(options) === 'function') { callback = options; options = {}; } var requestOptions = { path: urlJoin(_urlPrefix, zoneId, 'changes'), method: 'GET' }; if (options.since) { requestOptions.qs = { since: options.since.toString() }; } self._request(requestOptions, function (err, body) { return err ? callback(err) : callback(err, body); }); }, /** * @name Client.cloneZone * @description clone a zone from a provided domain name * * @param {Zone} zone the zone or zoneId for the changes * * @param {object|Function} options options for call * * @param {String} [options.cloneName] The name of the new (cloned) domain. * * @param {Boolean} [options.cloneSubdomains] Recursively clone * subdomains. If set to false, then only the top level domain and its records are * cloned. Cloned subdomain configurations are modified the same way that cloned * top level domain configurations are modified. (Default=true) * * @param {Boolean} [options.modifyComment] Replace occurrences * of the reference domain name with the new domain name in comments on the cloned * (new) domain. (Default=true) * * @param {Boolean} [options.modifyEmailAddress] Replace occurrences * of the reference domain name with the new domain name in email addresses on the * cloned (new) domain. (Default=true) * * @param {Boolean} [options.modifyRecordData] Replace occurrences * of the reference domain name with the new domain name in data fields (of records) * on the cloned (new) domain. Does not affect NS records. (Default=true) * * @param {Function} callback handles the callback of your api call */ cloneZone: function (zone, options, callback) { var self = this, zoneId = zone instanceof dns.Zone ? zone.id : zone; if (typeof(options) === 'function') { callback = options; options = {}; } var requestOptions = { path: urlJoin(_urlPrefix, zoneId, 'clone'), method: 'POST', qs: { cloneName: options.cloneName } }; _.extend(requestOptions.qs, _.pick(options, ['cloneSubdomains', 'modifyComment', 'modifyEmailAddress', 'modifyRecordData'])); self._asyncRequest(requestOptions, function (err, result) { return err ? callback(err) : callback(err, result.response.domains.map(function (domain) { return new dns.Zone(self, domain); })[0]); }); }, /** * @name Client.getSubZones * @description gets a list of the subzones for a provided zone * * @param {object|Number} zone the zone of the record to query for * @param {Function} callback handles the callback of your api call */ getSubZones: function(zone, callback) { var self = this, zoneId = zone instanceof dns.Zone ? zone.id : zone; var requestOptions = { path: urlJoin(_urlPrefix, zoneId, 'subdomains'), method: 'GET' }; self._request(requestOptions, function(err, body, res) { return err ? callback(err) : callback(null, body.domains.map(function (result) { return new dns.Zone(self, result); }), res); }); } };