diff --git a/lib/cli.js b/lib/cli.js index e20aa7f..802abba 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -63,6 +63,9 @@ function CLI() { 'instances', 'instance', 'instance-audit', + 'start-instance', + 'stop-instance', + 'reboot-instance', { group: 'Images' }, 'images', 'image', @@ -112,6 +115,9 @@ CLI.prototype.do_create = require('./do_create'); CLI.prototype.do_instance = require('./do_instance'); CLI.prototype.do_instances = require('./do_instances'); CLI.prototype.do_instance_audit = require('./do_instance_audit'); +CLI.prototype.do_stop_instance = require('./do_stop_instance'); +CLI.prototype.do_start_instance = require('./do_start_instance'); +CLI.prototype.do_reboot_instance = require('./do_reboot_instance'); // Packages CLI.prototype.do_packages = require('./do_packages'); diff --git a/lib/cloudapi2.js b/lib/cloudapi2.js index ab50400..7d5a8ff 100644 --- a/lib/cloudapi2.js +++ b/lib/cloudapi2.js @@ -200,6 +200,7 @@ CloudAPI.prototype._path = function _path(subpath /*, qparams, ... */) { * @param {Object|String} options - object or string for endpoint * - {String} path - URL endpoint to hit * - {String} method - HTTP(s) request method + * - {Object} data - data to be passed * @param {Function} callback passed via the restify client */ CloudAPI.prototype._request = function _request(options, callback) { @@ -208,6 +209,7 @@ CloudAPI.prototype._request = function _request(options, callback) { options = {path: options}; assert.object(options, 'options'); assert.func(callback, 'callback'); + assert.optionalObject(options.data, 'options.data'); var method = (options.method || 'GET').toLowerCase(); assert.ok(['get', 'post', 'delete', 'head'].indexOf(method) >= 0, @@ -221,7 +223,10 @@ CloudAPI.prototype._request = function _request(options, callback) { path: options.path, headers: headers }; - self.client[method](opts, callback); + if (options.data) + self.client[method](opts, options.data, callback); + else + self.client[method](opts, callback); }); }; @@ -353,8 +358,7 @@ CloudAPI.prototype.getPackage = function getPackage(options, callback) { * XXX add getCredentials equivalent * XXX cloudapi docs don't doc the credentials=true option * - * @param {Object} options - * - {String} id (required) The machine id. + * @param {String} uuid (required) The machine id. * @param {Function} callback of the form `function (err, machine, response)` */ CloudAPI.prototype.getMachine = function getMachine(uuid, callback) { @@ -368,6 +372,56 @@ CloudAPI.prototype.getMachine = function getMachine(uuid, callback) { }); }; +/** + * start a machine by id. + * + * @param {String} uuid (required) The machine id. + * @param {Function} callback of the form `function (err, machine, response)` + */ +CloudAPI.prototype.startMachine = function startMachine(uuid, callback) { + return this._doMachine('start', uuid, callback); +}; + +/** + * stop a machine by id. + * + * @param {String} uuid (required) The machine id. + * @param {Function} callback of the form `function (err, machine, response)` + */ +CloudAPI.prototype.stopMachine = function stopMachine(uuid, callback) { + return this._doMachine('stop', uuid, callback); +}; + +/** + * reboot a machine by id. + * + * @param {String} uuid (required) The machine id. + * @param {Function} callback of the form `function (err, machine, response)` + */ +CloudAPI.prototype.rebootMachine = function rebootMachine(uuid, callback) { + return this._doMachine('reboot', uuid, callback); +}; + +/** + * internal function for start/stop/reboot + */ +CloudAPI.prototype._doMachine = function _doMachine(action, uuid, callback) { + var self = this; + assert.string(uuid, 'uuid'); + assert.func(callback, 'callback'); + + var opts = { + path: sprintf('/%s/machines/%s', self.user, uuid), + method: 'POST', + data: { + action: action + } + }; + this._request(opts, function (err, req, res, body) { + callback(err, body, res); + }); +}; + /** * List the user's machines. diff --git a/lib/do_reboot_instance.js b/lib/do_reboot_instance.js new file mode 100644 index 0000000..16a4d40 --- /dev/null +++ b/lib/do_reboot_instance.js @@ -0,0 +1,67 @@ +/* + * Copyright 2015 Joyent Inc. + * + * `triton reboot-instance ...` + */ + +var common = require('./common'); + +function do_reboot_instance(subcmd, opts, args, callback) { + var self = this; + if (opts.help) { + this.do_help('help', {}, [subcmd], callback); + return; + } else if (args.length !== 1) { + callback(new Error('invalid args: ' + args)); + return; + } + + var arg = args[0]; + var uuid; + + if (common.isUUID(arg)) { + uuid = arg; + go1(); + } else { + self.triton.getMachineByAlias(arg, function (err, machine) { + if (err) { + callback(err); + return; + } + uuid = machine.id; + go1(); + }); + } + + function go1() { + // called when "uuid" is set + self.triton.cloudapi.rebootMachine(uuid, function (err, body, res) { + if (err) { + callback(err); + return; + } + callback(); + }); + + } +} + +do_reboot_instance.options = [ + { + names: ['help', 'h'], + type: 'bool', + help: 'Show this help.' + }, +]; +do_reboot_instance.help = ( + 'Stop a single instance.\n' + + '\n' + + 'Usage:\n' + + ' {{name}} reboot \n' + + '\n' + + '{{options}}' +); + +do_reboot_instance.aliases = ['reboot']; + +module.exports = do_reboot_instance; diff --git a/lib/do_start_instance.js b/lib/do_start_instance.js new file mode 100644 index 0000000..ed11cc6 --- /dev/null +++ b/lib/do_start_instance.js @@ -0,0 +1,67 @@ +/* + * Copyright 2015 Joyent Inc. + * + * `triton start-instance ...` + */ + +var common = require('./common'); + +function do_start_instance(subcmd, opts, args, callback) { + var self = this; + if (opts.help) { + this.do_help('help', {}, [subcmd], callback); + return; + } else if (args.length !== 1) { + callback(new Error('invalid args: ' + args)); + return; + } + + var arg = args[0]; + var uuid; + + if (common.isUUID(arg)) { + uuid = arg; + go1(); + } else { + self.triton.getMachineByAlias(arg, function (err, machine) { + if (err) { + callback(err); + return; + } + uuid = machine.id; + go1(); + }); + } + + function go1() { + // called when "uuid" is set + self.triton.cloudapi.startMachine(uuid, function (err, body, res) { + if (err) { + callback(err); + return; + } + callback(); + }); + + } +} + +do_start_instance.options = [ + { + names: ['help', 'h'], + type: 'bool', + help: 'Show this help.' + }, +]; +do_start_instance.help = ( + 'Stop a single instance.\n' + + '\n' + + 'Usage:\n' + + ' {{name}} start \n' + + '\n' + + '{{options}}' +); + +do_start_instance.aliases = ['start']; + +module.exports = do_start_instance; diff --git a/lib/do_stop_instance.js b/lib/do_stop_instance.js new file mode 100644 index 0000000..46306e8 --- /dev/null +++ b/lib/do_stop_instance.js @@ -0,0 +1,67 @@ +/* + * Copyright 2015 Joyent Inc. + * + * `triton stop-instance ...` + */ + +var common = require('./common'); + +function do_stop_instance(subcmd, opts, args, callback) { + var self = this; + if (opts.help) { + this.do_help('help', {}, [subcmd], callback); + return; + } else if (args.length !== 1) { + callback(new Error('invalid args: ' + args)); + return; + } + + var arg = args[0]; + var uuid; + + if (common.isUUID(arg)) { + uuid = arg; + go1(); + } else { + self.triton.getMachineByAlias(arg, function (err, machine) { + if (err) { + callback(err); + return; + } + uuid = machine.id; + go1(); + }); + } + + function go1() { + // called when "uuid" is set + self.triton.cloudapi.stopMachine(uuid, function (err, body, res) { + if (err) { + callback(err); + return; + } + callback(); + }); + + } +} + +do_stop_instance.options = [ + { + names: ['help', 'h'], + type: 'bool', + help: 'Show this help.' + }, +]; +do_stop_instance.help = ( + 'Stop a single instance.\n' + + '\n' + + 'Usage:\n' + + ' {{name}} stop \n' + + '\n' + + '{{options}}' +); + +do_stop_instance.aliases = ['stop']; + +module.exports = do_stop_instance;