diff --git a/lib/cli.js b/lib/cli.js index 802abba..33e0250 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -115,9 +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'); +CLI.prototype.do_stop_instance = require('./do_startstop_instance')('stop'); +CLI.prototype.do_start_instance = require('./do_startstop_instance')('start'); +CLI.prototype.do_reboot_instance = require('./do_startstop_instance')('reboot'); // Packages CLI.prototype.do_packages = require('./do_packages'); diff --git a/lib/cloudapi2.js b/lib/cloudapi2.js index 7d5a8ff..1018697 100644 --- a/lib/cloudapi2.js +++ b/lib/cloudapi2.js @@ -407,6 +407,7 @@ CloudAPI.prototype.rebootMachine = function rebootMachine(uuid, callback) { */ CloudAPI.prototype._doMachine = function _doMachine(action, uuid, callback) { var self = this; + assert.string(action, 'action'); assert.string(uuid, 'uuid'); assert.func(callback, 'callback'); @@ -422,6 +423,40 @@ CloudAPI.prototype._doMachine = function _doMachine(action, uuid, callback) { }); }; +/** + * wait for a specfic state for a machine + * + * @param {Object} options + * - {String} id - machine UUID + * - {String} state - desired state + * - {Number} interval (optional) - time in ms to poll + * @param {Function} callback - called when state is reached or on error + */ +CloudAPI.prototype.waitForMachineState = function waitForMachineState(opts, callback) { + var self = this; + assert.object(opts, 'opts'); + assert.string(opts.id, 'opts.id'); + assert.string(opts.state, 'opts.state'); + assert.optionalNumber(opts.interval, 'opts.interval'); + assert.func(callback, 'callback'); + var interval = (opts.interval === undefined ? 1000 : opts.interval); + + poll(); + + function poll() { + self.getMachine(opts.id, function (err, machine) { + if (err) { + callback(err); + return; + } + if (machine.state === opts.state) { + callback(null, machine); + return; + } + setTimeout(poll, interval); + }); + } +}; /** * List the user's machines. diff --git a/lib/do_reboot_instance.js b/lib/do_reboot_instance.js deleted file mode 100644 index 16a4d40..0000000 --- a/lib/do_reboot_instance.js +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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 deleted file mode 100644 index ed11cc6..0000000 --- a/lib/do_start_instance.js +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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_startstop_instance.js b/lib/do_startstop_instance.js new file mode 100644 index 0000000..9495e5e --- /dev/null +++ b/lib/do_startstop_instance.js @@ -0,0 +1,116 @@ +/* + * Copyright 2015 Joyent Inc. + * + * `triton stop-instance ...` + */ + +var f = require('util').format; +var assert = require('assert-plus'); +var common = require('./common'); + +function do_startstop_instance(action) { + assert.ok(['start', 'stop', 'reboot'].indexOf(action) >= 0, + 'invalid action'); + + function _do_startstop_instance(subcmd, opts, args, callback) { + return _do_instance.call(this, action, subcmd, opts, args, callback); + } + + _do_startstop_instance.aliases = [action]; + _do_startstop_instance.help = [ + f('%s a single instance.', action), + f(''), + f('Usage:'), + f(' {{name}} %s ', action), + f(''), + f('{{options}}') + ]; + _do_startstop_instance.options = [ + { + names: ['help', 'h'], + type: 'bool', + help: 'Show this help.' + }, + { + names: ['wait', 'w'], + type: 'bool', + help: 'Block until desired state is reached.' + }, + ]; + + return _do_startstop_instance; +} + +function _do_instance(action, subcmd, opts, args, callback) { + var self = this; + + var command, state; + switch (action) { + case 'start': + command = 'startMachine'; + state = 'running'; + break; + case 'stop': + command = 'stopMachine'; + state = 'stopped'; + break; + case 'reboot': + command = 'rebootMachine'; + state = 'running'; + break; + } + + 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[command](uuid, function (err, body, res) { + if (err) { + callback(err); + return; + } + + if (!opts.wait) { + callback(); + return; + } + + var waitOpts = { + state: state, + id: uuid + }; + self.triton.cloudapi.waitForMachineState(waitOpts, function (err, machine) { + if (err) { + callback(err); + return; + } + callback(); + }); + }); + } +} + +module.exports = do_startstop_instance; diff --git a/lib/do_stop_instance.js b/lib/do_stop_instance.js deleted file mode 100644 index 46306e8..0000000 --- a/lib/do_stop_instance.js +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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;