Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge branch 'master' of https://github.com/kenperkins/rackspace-open…

…stack

Conflicts:
	lib/cloudservers/server.js
  • Loading branch information...
commit 88ed10ac72056332413fc3df0648a2e64daa342e 2 parents e9c9656 + 7102e37
Ken Perkins authored
4 lib/client/client.js
View
@@ -14,6 +14,7 @@ var request = require('request'),
CloudLoadBalancers = require('./cloudloadbalancers').CloudLoadBalancers,
CloudServers = require('./cloudservers').CloudServers,
CloudBlockStorage = require('./cloudblockstorage').CloudBlockStorage,
+ CloudDatabases = require('./clouddatabases').CloudDatabases,
_ = require('underscore'),
winston = require('winston');
@@ -207,7 +208,8 @@ var prototype = _.extend({},
CloudDns,
CloudLoadBalancers,
CloudServers,
- CloudBlockStorage);
+ CloudBlockStorage,
+ CloudDatabases);
_.each(prototype, function(value, key) {
Client.prototype[key] = value;
173 lib/client/clouddatabases.js
View
@@ -0,0 +1,173 @@
+var rackspace = require('../rackspace-openstack'),
+ _ = require('underscore');
+
+exports.CloudDatabases = {
+
+ /**
+ * @name Client.createDatabaseInstance
+ *
+ * @description Creates a Cloud Databases instance
+ *
+ * @param {Object} options the options to use in building your database instance
+ * @param {Function} callback handles the callback of your api call
+ */
+ createDatabaseInstance: function(options, callback) {
+ var self = this;
+
+ ['flavor', 'size'].forEach(function(required) {
+ if (!options[required]) throw new Error('options.' +
+ required + ' is a required argument.');
+ });
+
+ var requestOptions = {
+ uri: '/instances',
+ method: 'POST',
+ data: {
+ instance: {
+ flavorRef: options.flavor,
+ volume: {size: options.size},
+ }
+ },
+ endpoint: rackspace.Endpoints.CloudDatabases
+ };
+
+ ['name', 'databases', 'users'].forEach(function(optional) {
+ requestOptions.data.instance[optional] = options[optional];
+ });
+
+ self.authorizedRequest(requestOptions, function(err, res, body) {
+ if (err || !body.instance) {
+ callback(err ? err : body);
+ return;
+ }
+
+ callback(err, new rackspace.DatabaseInstance(self, _.extend({}, body.instance, options)));
+ });
+ },
+
+ /**
+ * @name Client.createDatabaseInstanceWithWait
+ *
+ * @description Creates a database instance and waits for it to be in Active Status
+ *
+ * @param {Object} details the instance details to use in building your instance
+ * @param {Object|Function} options optional parameters used for instance creation
+ * @param {Function} callback handles the callback of your api call
+ */
+ createDatabaseInstanceWithWait: function(details, options, callback) {
+ var self = this;
+
+ if (typeof(options) === 'function') {
+ callback = options;
+ options = {};
+ }
+
+ self.createDatabaseInstance(details, function(err, instance) {
+ if (err) {
+ callback(err);
+ return;
+ }
+
+ var waitOptions = {
+ interval: 5000,
+ maxWait: options.maxWait ? options.maxWait : 30 * 60, // 30 minute default,
+ update: options.update,
+ finish: options.finish
+ };
+
+ instance.setWait({ status: 'ACTIVE' }, waitOptions, function(err, instance) {
+ callback(err, instance);
+ });
+ });
+ },
+
+ /**
+ * @name Client.destroyDatabaseInstance
+ *
+ * @description deletes the specified instance
+ *
+ * @param {Object|String} instance instance or instance id to delete
+ * @param {Function} callback handles the callback of your api call
+ */
+ destroyDatabaseInstance: function(instance, callback) {
+ var self = this, instanceId;
+
+ instanceId = instance instanceof rackspace.DatabaseInstance ? instance.id : instance;
+
+ if (!instance) {
+ throw new Error('DatabaseInstance is a required argument.');
+ }
+
+ var requestOptions = {
+ uri: '/instances/' + instanceId,
+ method: 'DELETE',
+ endpoint: rackspace.Endpoints.CloudDatabases
+ };
+
+ self.authorizedRequest(requestOptions, function(err, res, body) {
+ if (err) {
+ callback(err);
+ return;
+ }
+
+ callback(err, res.statusCode === 202);
+ });
+ },
+
+ /**
+ * @name Client.getDatabaseInstances
+ *
+ * @description getDatabaseInstances retrieves your list of database instances
+ *
+ * @param {Function} callback handles the callback of your api call
+ */
+ getDatabaseInstances: function(callback) {
+ var self = this;
+
+ var requestOptions = {
+ uri: '/instances',
+ endpoint: rackspace.Endpoints.CloudDatabases
+ };
+
+ this.authorizedRequest(requestOptions, function(err, res, body) {
+ if (err || !body.instances) {
+ callback(err ? err : body);
+ return;
+ }
+
+ var instances = [];
+
+ for (var i = 0; i < body.instances.length; i++) {
+ instances.push(new rackspace.DatabaseInstance(self, body.instances[i]));
+ }
+
+ callback(err, instances);
+ });
+ },
+
+ /**
+ * @name Client.getDatabaseInstance
+ *
+ * @description Gets the details for a specified database instance id
+ *
+ * @param {String} id the id of the requested database instance
+ * @param {Function} callback handles the callback of your api call
+ */
+ getDatabaseInstance: function(id, callback) {
+ var self = this;
+
+ var requestOptions = {
+ uri: '/instances/' + id,
+ endpoint: rackspace.Endpoints.CloudDatabases
+ };
+
+ this.authorizedRequest(requestOptions, function(err, res, body) {
+ if (err || !body.instance) {
+ callback(err ? err : body);
+ return;
+ }
+
+ callback(err, new rackspace.DatabaseInstance(self, body.instance));
+ });
+ }
+};
40 lib/clouddatabases/database.js
View
@@ -0,0 +1,40 @@
+/*
+ * user.js: Instance of a rackspace cloud databases database
+ *
+ * (C) 2013 Andrew Regner
+ *
+ * Inspired by node-cloudservers from Nodejitsu &
+ * clouddns from davidandrewcope
+ *
+ * MIT LICENSE
+ *
+ */
+
+var rackspace = require('../rackspace-openstack');
+
+var Database = function(instance, details) {
+ if (!details) {
+ throw new Error('Database must be constructed with at-least basic details.')
+ }
+
+ this.instance = instance;
+ this._setProperties(details);
+};
+
+Database.prototype = {
+
+ /**
+ * @name Database._setProperties
+ *
+ * @description Loads the properties of an object into this instance
+ *
+ * @param {Object} details the details to load
+ */
+ _setProperties: function(details) {
+ this.name = details.name;
+ this.character_set = details.character_set;
+ this.collate = details.collate;
+ }
+};
+
+exports.Database = Database;
371 lib/clouddatabases/instance.js
View
@@ -0,0 +1,371 @@
+/*
+ * instance.js: Instance of a rackspace cloud databases server
+ *
+ * (C) 2013 Andrew Regner
+ * MIT LICENSE
+ *
+ */
+
+var rackspace = require('../rackspace-openstack'),
+ _ = require('underscore');
+
+var DatabaseInstance = function(client, details) {
+ if (!details) {
+ throw new Error("DatabaseInstance must be constructed with at-least basic details.")
+ }
+
+ this.client = client;
+ this._setProperties(details);
+};
+
+DatabaseInstance.prototype = {
+ /**
+ * @name DatabaseInstance.getDatabases
+ *
+ * @description returns all the databases on this database instance
+ *
+ * @param {Function} callback handles the callback of your api call
+ */
+ getDatabases: function(callback) {
+ var self = this;
+
+ var requestOptions = {
+ uri: '/instances/' + this.id + '/databases',
+ endpoint: rackspace.Endpoints.CloudDatabases
+ };
+
+ this.client.authorizedRequest(requestOptions, function(err, res, body) {
+ if (err || !body.databases) {
+ callback(err ? err : body);
+ return;
+ }
+
+ var databases = [];
+
+ for (var i = 0; i < body.databases.length; i++) {
+ databases.push(new rackspace.Database(self, body.databases[i]));
+ }
+
+ callback(err, databases);
+ });
+ },
+
+ /**
+ * @name DatabaseInstance.getUsers
+ *
+ * @description returns all the users on this database instance
+ *
+ * @param {Function} callback handles the callback of your api call
+ */
+ getUsers: function(callback) {
+ var self = this;
+
+ var requestOptions = {
+ uri: '/instances/' + this.id + '/users',
+ endpoint: rackspace.Endpoints.CloudDatabases
+ };
+
+ this.client.authorizedRequest(requestOptions, function(err, res, body) {
+ if (err || !body.users) {
+ callback(err ? err : body);
+ return;
+ }
+
+ var users = [];
+
+ for (var i = 0; i < body.users.length; i++) {
+ users.push(new rackspace.DatabaseUser(self, body.users[i]));
+ }
+
+ callback(err, users);
+ });
+ },
+
+ /**
+ * @name Client.createDatabase
+ *
+ * @description create a new database within the Cloud Database instance
+ *
+ * @param {Object} details the information for your new database
+ * @param {Function} callback handles the callback of your api call
+ */
+ createDatabase: function(details, callback) {
+ this.createDatabases([ details ], callback);
+ },
+
+ createDatabases: function(databases, callback) {
+ var self = this,
+ data = [];
+
+ _.each(databases, function(details) {
+
+ ['name'].forEach(function(required) {
+ if (!details[required]) throw new Error('details.' +
+ required + ' is a required argument.');
+ });
+
+ var dbase = {
+ name: details.name
+ };
+
+ if (details.character_set) {
+ dbase.character_set = details.character_set;
+ }
+
+ if (details.collate) {
+ dbase.collate = details.collate;
+ }
+
+ data.push(dbase);
+ });
+
+ var requestOptions = {
+ uri: '/instances/' + this.id + '/databases',
+ method: 'POST',
+ data: {
+ databases: data
+ },
+ endpoint: rackspace.Endpoints.CloudDatabases
+ };
+
+ this.client.authorizedRequest(requestOptions, function(err, res, body) {
+ if (err || res.statusCode !== 202) {
+ callback(err ? err : body);
+ return;
+ }
+
+ callback(err);
+ });
+ },
+
+ /**
+ * @name Client.deleteDatabase
+ * @description delete a database
+ * @param {String} name name of the database to delete
+ * @param {Function} callback handles the callback of your api call
+ */
+ deleteDatabase: function(name, callback) {
+ var self = this;
+
+ var requestOptions = {
+ uri: '/instances/' + this.id + '/databases/' + name,
+ method: 'DELETE',
+ endpoint: rackspace.Endpoints.CloudDatabase
+ };
+
+ this.client.authorizedRequest(requestOptions, function(err, res, body) {
+ if (err || res.statusCode !== 202) {
+ callback(err ? err : body);
+ return;
+ }
+
+ callback(err);
+ });
+ },
+
+ /**
+ * @name Client.createUser
+ *
+ * @description create a new database within the Cloud Database instance
+ *
+ * @param {Object} details the information for your new database
+ * @param {Function} callback handles the callback of your api call
+ */
+ createUser: function(details, callback) {
+ this.createUsers([ details ], callback);
+ },
+
+ createUsers: function(users, callback) {
+ var self = this,
+ data = [];
+
+ _.each(users, function(details) {
+
+ ['name', 'password'].forEach(function(required) {
+ if (!details[required]) throw new Error('details.' +
+ required + ' is a required argument.');
+ });
+
+ var user = {
+ name: details.name,
+ password: details.password
+ };
+
+ if (details.databases) {
+ user.databases = details.databases;
+ }
+
+ data.push(user);
+ });
+
+ var requestOptions = {
+ uri: '/instances/' + this.id + '/users',
+ method: 'POST',
+ data: {
+ users: data
+ },
+ endpoint: rackspace.Endpoints.CloudDatabases
+ };
+
+ this.client.authorizedRequest(requestOptions, function(err, res, body) {
+ if (err || res.statusCode !== 202) {
+ callback(err ? err : body);
+ return;
+ }
+
+ callback(err);
+ });
+ },
+
+ /**
+ * @name Client.deleteUser
+ * @description delete a database
+ * @param {String} name name of the database to delete
+ * @param {Function} callback handles the callback of your api call
+ */
+ deleteUser: function(name, callback) {
+ var self = this;
+
+ var requestOptions = {
+ uri: '/instances/' + this.id + '/users/' + name,
+ method: 'DELETE',
+ endpoint: rackspace.Endpoints.CloudDatabase
+ };
+
+ this.client.authorizedRequest(requestOptions, function(err, res, body) {
+ if (err || res.statusCode !== 202) {
+ callback(err ? err : body);
+ return;
+ }
+
+ callback(err);
+ });
+ },
+
+ /**
+ * @name DatabaseInstance.setWait
+ * @description Continually polls Rackspace Cloud BlockStorage and checks the
+ * results against the attributes parameter. When the attributes match
+ * the callback will be fired.
+ *
+ * @param {Object} attributes the value to check for during the interval
+ * @param {Object} options timeout in ms
+ * @param {Function} callback handles the callback of your api call
+ */
+ setWait: function(attributes, options, callback) {
+ var self = this,
+ calledBack = false;
+
+ var equalCheckId = setInterval(function() {
+
+ self.getDetails(function(err, instance) {
+ if (err) return; // Ignore errors
+
+ if (options.update) {
+ options.update();
+ }
+
+ var equal = true, keys = Object.keys(attributes);
+ for (var index in keys) {
+ if (attributes[keys[index]].toLowerCase() !==
+ instance[keys[index]].toLowerCase()) {
+ equal = false;
+ break;
+ }
+ }
+
+ if (equal && !calledBack) {
+ finalize(null);
+ }
+ else if (calledBack) {
+ clearInterval(equalCheckId);
+ clearTimeout(equalTimeoutId);
+ }
+ });
+ }, options.interval);
+
+ var equalTimeoutId = setTimeout(function() {
+ if (!calledBack) {
+ finalize({ error: 'Max timeout exceeded' });
+ }
+ }, options.maxWait ? options.maxWait * 1000 : 60 * 30 * 1000);
+
+ function finalize(err) {
+ calledBack = true;
+ clearInterval(equalCheckId);
+ clearTimeout(equalTimeoutId);
+ if (options.finish) {
+ options.finish();
+ }
+ callback(err, self);
+ }
+
+ return equalCheckId;
+ },
+
+ /**
+ * @name DatabaseInstance.clearWait
+ * @description Clears a previously setWait for this instance
+ * @param {Number} intervalId the interval to clear
+ */
+ clearWait: function(intervalId) {
+ clearInterval(intervalId);
+ },
+
+ /**
+ * @name DatabaseInstance.getDetails
+ * @description Update the details of this database instance
+ * @param {Function} callback handles the callback of your api call
+ */
+ getDetails: function(callback) {
+ var self = this;
+ this.client.getDatabaseInstance(this.id, function(err, instance) {
+ if (err) {
+ callback(err);
+ return;
+ }
+
+ self._setProperties(instance);
+ callback(null, self);
+ });
+ },
+
+ enableRoot: function(callback) {
+ var requestOptions = {
+ uri: '/instances/' + this.id + '/root',
+ method: 'POST',
+ endpoint: rackspace.Endpoints.CloudDatabases
+ };
+
+ this.client.authorizedRequest(requestOptions, function(err, res, body) {
+ if (err || res.statusCode !== 200 || !body.user) {
+ callback(err ? err : body);
+ return;
+ }
+
+ callback(err, body.user.password);
+ });
+ },
+
+ destroy: function(callback) {
+ this.client.destroyDatabaseInstance(this, callback);
+ },
+
+ /**
+ * @name DatabaseInstance._setProperties
+ * @description Loads the properties of an object into this instance
+ * @param {Object} details the details to load
+ */
+ _setProperties: function(details) {
+ this.id = details.id;
+ this.created_at = details.created_at;
+ this.flavor = details.flavor;
+ this.hostname = details.hostname;
+ this.name = details.name;
+ this.status = details.status;
+ this.updated = details.updated;
+ this.volume = details.volume;
+ }
+};
+
+exports.DatabaseInstance = DatabaseInstance;
50 lib/clouddatabases/user.js
View
@@ -0,0 +1,50 @@
+/*
+ * user.js: Instance of a rackspace cloud databases user
+ *
+ * (C) 2013 Andrew Regner
+ *
+ * Inspired by node-cloudservers from Nodejitsu &
+ * clouddns from davidandrewcope
+ *
+ * MIT LICENSE
+ *
+ */
+
+var rackspace = require('../rackspace-openstack');
+
+var DatabaseUser = function(instance, details) {
+ if (!details) {
+ throw new Error('DatabaseUser must be constructed with at-least basic details.')
+ }
+
+ this.instance = instance;
+ this._setProperties(details);
+};
+
+DatabaseUser.prototype = {
+
+ /**
+ * @name DatabaseUser._setProperties
+ *
+ * @description Loads the properties of an object into this instance
+ *
+ * @param {Object} details the details to load
+ */
+ _setProperties: function(details) {
+ var self = this;
+ this.name = details.name;
+ this.password = details.password;
+
+ if (details.databases) {
+ var dbs = [];
+
+ for (var i = 0; i < details.databases.length; i++) {
+ dbs.push(new rackspace.Database(self.instance, details.databases[i]));
+ }
+
+ this.databases = dbs;
+ }
+ }
+};
+
+exports.DatabaseUser = DatabaseUser;
4 lib/cloudservers/server.js
View
@@ -481,11 +481,12 @@ Server.prototype = {
}
else if (calledBack) {
clearInterval(equalCheckId);
+ clearTimeout(equalTimeoutId);
}
});
}, options.interval);
- setTimeout(function() {
+ var equalTimeoutId = setTimeout(function() {
if (!calledBack) {
finalize({ error: 'Max timeout exceeded' });
}
@@ -494,6 +495,7 @@ Server.prototype = {
function finalize(err) {
calledBack = true;
clearInterval(equalCheckId);
+ clearTimeout(equalTimeoutId);
if (options.finish) {
options.finish();
}
11 lib/rackspace-openstack.js
View
@@ -43,6 +43,11 @@ rackspace.Node = require('./cloudloadbalancers/node').Node;
rackspace.NodeConditions = require('./cloudloadbalancers/node').NodeConditions;
rackspace.NodeType = require('./cloudloadbalancers/node').NodeType;
+// Cloud Databases
+rackspace.DatabaseInstance = require('./clouddatabases/instance').DatabaseInstance;
+rackspace.Database = require('./clouddatabases/database').Database;
+rackspace.DatabaseUser = require('./clouddatabases/user').DatabaseUser;
+
rackspace.Endpoints = {
Openstack: {
type: 'compute',
@@ -59,5 +64,9 @@ rackspace.Endpoints = {
CloudBlockStorage: {
type: 'volume',
name: 'cloudBlockStorage'
+ },
+ CloudDatabases: {
+ type: 'rax:database',
+ name: 'cloudDatabases'
}
-};
+};
Please sign in to comment.
Something went wrong with that request. Please try again.