diff --git a/lib/cli.js b/lib/cli.js index a246312..ea4ff94 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -197,11 +197,10 @@ function CLI() { 'instance', 'instances', 'create', - 'start-instance', - 'stop-instance', - 'reboot-instance', - 'delete-instance', - 'wait-instance', + 'delete', + 'start', + 'stop', + 'reboot', 'ssh', { group: 'Images, Packages, Networks' }, 'image', @@ -349,12 +348,10 @@ CLI.prototype.do_image = require('./do_image'); CLI.prototype.do_instance = require('./do_instance'); CLI.prototype.do_instances = require('./do_instances'); CLI.prototype.do_create = require('./do_create'); -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'); -CLI.prototype.do_delete_instance = - require('./do_startstop_instance')({action: 'delete', aliases: ['rm']}); -CLI.prototype.do_wait_instance = require('./do_wait_instance'); +CLI.prototype.do_delete = require('./do_delete'); +CLI.prototype.do_start = require('./do_start'); +CLI.prototype.do_stop = require('./do_stop'); +CLI.prototype.do_reboot = require('./do_reboot'); CLI.prototype.do_ssh = require('./do_ssh'); // Packages diff --git a/lib/do_delete.js b/lib/do_delete.js new file mode 100644 index 0000000..c030159 --- /dev/null +++ b/lib/do_delete.js @@ -0,0 +1,27 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/* + * Copyright 2015 Joyent, Inc. + * + * `triton delete ...` bwcompat shortcut for `triton instance delete ...`. + */ + +function do_delete(subcmd, opts, args, callback) { + var subcmdArgv = ['node', 'triton', 'instance', 'delete'].concat(args); + this.dispatch('instance', subcmdArgv, callback); +} + +do_delete.help = [ + 'A shortcut for "triton instance delete".', + '', + 'Usage:', + ' {{name}} delete ...' +].join('\n'); + +do_delete.aliases = ['rm']; + +module.exports = do_delete; diff --git a/lib/do_instance/do_audit.js b/lib/do_instance/do_audit.js index ce0854c..86223f0 100644 --- a/lib/do_instance/do_audit.js +++ b/lib/do_instance/do_audit.js @@ -91,8 +91,6 @@ function do_audit(subcmd, opts, args, cb) { } } -do_audit.aliases = ['audit']; - do_audit.options = [ { names: ['help', 'h'], diff --git a/lib/do_instance/do_create.js b/lib/do_instance/do_create.js index b567bc6..89c348c 100644 --- a/lib/do_instance/do_create.js +++ b/lib/do_instance/do_create.js @@ -602,9 +602,6 @@ do_create.helpOpts = { maxHelpCol: 18 }; -do_create.aliases = ['create']; - - module.exports = do_create; do_create.metadataFromOpts = metadataFromOpts; // export for testing diff --git a/lib/do_instance/do_ssh.js b/lib/do_instance/do_ssh.js new file mode 100644 index 0000000..5330963 --- /dev/null +++ b/lib/do_instance/do_ssh.js @@ -0,0 +1,78 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/* + * Copyright 2016 Joyent, Inc. + * + * `triton instance ssh ...` + */ + +var spawn = require('child_process').spawn; + +var common = require('../common'); + + +function do_ssh(subcmd, opts, args, callback) { + var self = this; + + if (opts.help) { + this.do_help('help', {}, [subcmd], callback); + return; + } else if (args.length === 0) { + callback(new Error('invalid args: ' + args)); + return; + } + + var id = args.shift(); + + var user = 'root'; + var i = id.indexOf('@'); + if (i >= 0) { + user = id.substr(0, i); + id = id.substr(i + 1); + } + + this.top.tritonapi.getInstance(id, function (err, inst) { + if (err) { + callback(err); + return; + } + + var ip = inst.primaryIp; + if (!ip) { + callback(new Error('primaryIp not found for instance')); + return; + } + + args = ['-l', user].concat(ip).concat(args); + + self.top.log.info({args: args}, 'forking ssh'); + var child = spawn('ssh', args, {stdio: 'inherit'}); + child.on('close', function (code) { + process.exit(code); + }); + }); +} + +do_ssh.options = [ + { + names: ['help', 'h'], + type: 'bool', + help: 'Show this help.' + } +]; +do_ssh.help = ( + 'SSH to the primary IP of an instance\n' + + '\n' + + 'Usage:\n' + + ' {{name}} ssh [arguments]\n' + + '\n' + + '{{options}}' +); + +do_ssh.interspersedOptions = false; + +module.exports = do_ssh; diff --git a/lib/do_wait_instance.js b/lib/do_instance/do_wait.js similarity index 88% rename from lib/do_wait_instance.js rename to lib/do_instance/do_wait.js index d4e53a6..898ce65 100644 --- a/lib/do_wait_instance.js +++ b/lib/do_instance/do_wait.js @@ -5,18 +5,18 @@ */ /* - * Copyright 2015 Joyent, Inc. + * Copyright 2016 Joyent, Inc. * - * `triton wait-instance ...` + * `triton instance wait ...` */ var vasync = require('vasync'); -var distractions = require('./distractions'); -var errors = require('./errors'); +var distractions = require('../distractions'); +var errors = require('../errors'); -function do_wait_instance(subcmd, opts, args, cb) { +function do_wait(subcmd, opts, args, cb) { var self = this; if (opts.help) { return this.do_help('help', {}, [subcmd], cb); @@ -39,7 +39,7 @@ function do_wait_instance(subcmd, opts, args, cb) { vasync.forEachParallel({ inputs: ids, func: function getInst(id, nextInst) { - self.tritonapi.getInstance(id, function (err, inst) { + self.top.tritonapi.getInstance(id, function (err, inst) { if (err) { return nextInst(err); } @@ -87,7 +87,7 @@ function do_wait_instance(subcmd, opts, args, cb) { vasync.forEachParallel({ inputs: idsToWaitFor, func: function waitForInst(id, nextInst) { - self.tritonapi.cloudapi.waitForMachineStates({ + self.top.tritonapi.cloudapi.waitForMachineStates({ id: id, states: states }, function (err, inst, res) { @@ -110,8 +110,7 @@ function do_wait_instance(subcmd, opts, args, cb) { }); } -do_wait_instance.aliases = ['wait']; -do_wait_instance.help = [ +do_wait.help = [ 'Wait on instances changing state.', '', 'Usage:', @@ -119,10 +118,10 @@ do_wait_instance.help = [ '', '{{options}}', 'Where "states" is a comma-separated list of target instance states,', - 'by default "running,failed". In other words, "triton wait foo0" will', + 'by default "running,failed". In other words, "triton inst wait foo0" will', 'wait for instance "foo0" to complete provisioning.' ].join('\n'); -do_wait_instance.options = [ +do_wait.options = [ { names: ['help', 'h'], type: 'bool', @@ -138,4 +137,4 @@ do_wait_instance.options = [ } ]; -module.exports = do_wait_instance; +module.exports = do_wait; diff --git a/lib/do_startstop_instance.js b/lib/do_instance/gen_do_ACTION.js similarity index 82% rename from lib/do_startstop_instance.js rename to lib/do_instance/gen_do_ACTION.js index 7ec4002..8a13fab 100644 --- a/lib/do_startstop_instance.js +++ b/lib/do_instance/gen_do_ACTION.js @@ -7,24 +7,27 @@ /* * Copyright 2015 Joyent, Inc. * - * `triton stop-instance ...` - * `triton start-instance ...` - * `triton reboot-instance ...` + * `triton instance start ...` + * `triton instance stop ...` + * `triton instance reboot ...` + * `triton instance delete ...` */ -var f = require('util').format; var assert = require('assert-plus'); -var common = require('./common'); - var vasync = require('vasync'); +var common = require('../common'); + + +var f = require('util').format; + + function perror(err) { console.error('error: %s', err.message); } -function do_startstop_instance(opts) { - if (typeof (opts) === 'string') - opts = {action: opts}; + +function gen_do_ACTION(opts) { assert.object(opts, 'opts'); assert.string(opts.action, 'opts.action'); assert.optionalArrayOfString(opts.aliases, 'opts.aliases'); @@ -33,16 +36,15 @@ function do_startstop_instance(opts) { assert.ok(['start', 'stop', 'reboot', 'delete'].indexOf(action) >= 0, 'invalid action'); - function _do_startstop_instance(subcmd, _opts, args, callback) { - return _do_instance.call(this, action, subcmd, _opts, args, callback); + function do_ACTION(subcmd, _opts, args, callback) { + return _doTheAction.call(this, action, subcmd, _opts, args, callback); } - var aliases = [action]; - if (opts.aliases) - aliases = aliases.concat(opts.aliases); - _do_startstop_instance.aliases = aliases; + if (opts.aliases) { + do_ACTION.aliases = opts.aliases; + } - _do_startstop_instance.help = [ + do_ACTION.help = [ f('%s one or more instances.', common.capitalize(action)), f(''), f('Usage:'), @@ -50,7 +52,7 @@ function do_startstop_instance(opts) { f(''), f('{{options}}') ].join('\n'); - _do_startstop_instance.options = [ + do_ACTION.options = [ { names: ['help', 'h'], type: 'bool', @@ -59,14 +61,14 @@ function do_startstop_instance(opts) { { names: ['wait', 'w'], type: 'bool', - help: 'Block until desired state is reached.' + help: 'Block until instance state indicates the action is complete.' } ]; - return _do_startstop_instance; + return do_ACTION; } -function _do_instance(action, subcmd, opts, args, callback) { +function _doTheAction(action, subcmd, opts, args, callback) { var self = this; var now = Date.now(); @@ -109,7 +111,7 @@ function _do_instance(action, subcmd, opts, args, callback) { uuid = arg; done(); } else { - self.tritonapi.getInstance(arg, function (err, inst) { + self.top.tritonapi.getInstance(arg, function (err, inst) { if (err) { perror(err); cb(err); @@ -123,7 +125,7 @@ function _do_instance(action, subcmd, opts, args, callback) { // called when "uuid" is set function done() { - self.tritonapi.cloudapi[command](uuid, + self.top.tritonapi.cloudapi[command](uuid, function (err, body, res) { if (err) { @@ -143,7 +145,7 @@ function _do_instance(action, subcmd, opts, args, callback) { return; } - self.tritonapi.cloudapi.waitForMachineStates({ + self.top.tritonapi.cloudapi.waitForMachineStates({ id: uuid, states: [state] }, function (err2, inst2, res2) { @@ -177,4 +179,4 @@ function _do_instance(action, subcmd, opts, args, callback) { }); } -module.exports = do_startstop_instance; +module.exports = gen_do_ACTION; diff --git a/lib/do_instance/index.js b/lib/do_instance/index.js index f164974..1279a9e 100644 --- a/lib/do_instance/index.js +++ b/lib/do_instance/index.js @@ -13,6 +13,7 @@ var Cmdln = require('cmdln').Cmdln; var util = require('util'); +var gen_do_ACTION = require('./gen_do_ACTION'); // ---- CLI class @@ -34,6 +35,14 @@ function InstanceCLI(top) { 'list', 'get', 'create', + 'delete', + { group: '' }, + 'start', + 'stop', + 'reboot', + { group: '' }, + 'ssh', + 'wait', 'audit' ] }); @@ -48,8 +57,16 @@ InstanceCLI.prototype.init = function init(opts, args, cb) { InstanceCLI.prototype.do_list = require('./do_list'); InstanceCLI.prototype.do_get = require('./do_get'); InstanceCLI.prototype.do_create = require('./do_create'); -InstanceCLI.prototype.do_audit = require('./do_audit'); +InstanceCLI.prototype.do_delete = gen_do_ACTION( + {action: 'delete', aliases: ['rm']}); +InstanceCLI.prototype.do_start = gen_do_ACTION({action: 'start'}); +InstanceCLI.prototype.do_stop = gen_do_ACTION({action: 'stop'}); +InstanceCLI.prototype.do_reboot = gen_do_ACTION({action: 'reboot'}); + +InstanceCLI.prototype.do_ssh = require('./do_ssh'); +InstanceCLI.prototype.do_wait = require('./do_wait'); +InstanceCLI.prototype.do_audit = require('./do_audit'); InstanceCLI.aliases = ['inst']; diff --git a/lib/do_reboot.js b/lib/do_reboot.js new file mode 100644 index 0000000..9474239 --- /dev/null +++ b/lib/do_reboot.js @@ -0,0 +1,25 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/* + * Copyright 2015 Joyent, Inc. + * + * `triton reboot ...` bwcompat shortcut for `triton instance reboot ...`. + */ + +function do_reboot(subcmd, opts, args, callback) { + var subcmdArgv = ['node', 'triton', 'instance', 'reboot'].concat(args); + this.dispatch('instance', subcmdArgv, callback); +} + +do_reboot.help = [ + 'A shortcut for "triton instance reboot".', + '', + 'Usage:', + ' {{name}} reboot ...' +].join('\n'); + +module.exports = do_reboot; diff --git a/lib/do_ssh.js b/lib/do_ssh.js index d8b7b40..60d967c 100644 --- a/lib/do_ssh.js +++ b/lib/do_ssh.js @@ -5,72 +5,21 @@ */ /* - * Copyright 2015 Joyent, Inc. + * Copyright 2016 Joyent, Inc. * - * `triton ssh ...` + * `triton ssh ...` bwcompat shortcut for `triton instance ssh ...`. */ -var common = require('./common'); -var spawn = require('child_process').spawn; - function do_ssh(subcmd, opts, args, callback) { - var self = this; - - if (opts.help) { - this.do_help('help', {}, [subcmd], callback); - return; - } else if (args.length === 0) { - callback(new Error('invalid args: ' + args)); - return; - } - - var id = args.shift(); - - var user = 'root'; - var i = id.indexOf('@'); - if (i >= 0) { - user = id.substr(0, i); - id = id.substr(i + 1); - } - - this.tritonapi.getInstance(id, function (err, inst) { - if (err) { - callback(err); - return; - } - - var ip = inst.primaryIp; - if (!ip) { - callback(new Error('primaryIp not found for instance')); - return; - } - - args = ['-l', user].concat(ip).concat(args); - - self.tritonapi.log.info({args: args}, 'forking ssh'); - var child = spawn('ssh', args, {stdio: 'inherit'}); - child.on('close', function (code) { - process.exit(code); - }); - }); + var subcmdArgv = ['node', 'triton', 'instance', 'ssh'].concat(args); + this.dispatch('instance', subcmdArgv, callback); } -do_ssh.options = [ - { - names: ['help', 'h'], - type: 'bool', - help: 'Show this help.' - } -]; -do_ssh.help = ( - 'SSH to the primary IP of an instance\n' - + '\n' - + 'Usage:\n' - + ' {{name}} ssh [arguments]\n' - + '\n' - + '{{options}}' -); - -do_ssh.interspersedOptions = false; +do_ssh.help = [ + 'A shortcut for "triton instance ssh".', + '', + 'Usage:', + ' {{name}} ssh ...' +].join('\n'); module.exports = do_ssh; diff --git a/lib/do_start.js b/lib/do_start.js new file mode 100644 index 0000000..9478a7a --- /dev/null +++ b/lib/do_start.js @@ -0,0 +1,25 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/* + * Copyright 2015 Joyent, Inc. + * + * `triton start ...` bwcompat shortcut for `triton instance start ...`. + */ + +function do_start(subcmd, opts, args, callback) { + var subcmdArgv = ['node', 'triton', 'instance', 'start'].concat(args); + this.dispatch('instance', subcmdArgv, callback); +} + +do_start.help = [ + 'A shortcut for "triton instance start".', + '', + 'Usage:', + ' {{name}} start ...' +].join('\n'); + +module.exports = do_start; diff --git a/lib/do_stop.js b/lib/do_stop.js new file mode 100644 index 0000000..008b0d3 --- /dev/null +++ b/lib/do_stop.js @@ -0,0 +1,25 @@ +/* + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +/* + * Copyright 2015 Joyent, Inc. + * + * `triton stop ...` bwcompat shortcut for `triton instance stop ...`. + */ + +function do_stop(subcmd, opts, args, callback) { + var subcmdArgv = ['node', 'triton', 'instance', 'stop'].concat(args); + this.dispatch('instance', subcmdArgv, callback); +} + +do_stop.help = [ + 'A shortcut for "triton instance stop".', + '', + 'Usage:', + ' {{name}} stop ...' +].join('\n'); + +module.exports = do_stop; diff --git a/test/integration/cli-manage-workflow.test.js b/test/integration/cli-manage-workflow.test.js index fa054c6..81f49dd 100644 --- a/test/integration/cli-manage-workflow.test.js +++ b/test/integration/cli-manage-workflow.test.js @@ -259,8 +259,8 @@ test('triton manage workflow', opts, function (tt) { }); // wait for the machine to start - tt.test(' triton wait', function (t) { - h.safeTriton(t, ['wait', instance.id], + tt.test(' triton inst wait', function (t) { + h.safeTriton(t, ['inst', 'wait', instance.id], function (stdout) { // parse JSON response diff --git a/test/integration/cli-subcommands.test.js b/test/integration/cli-subcommands.test.js index c60e1fa..b2e79d3 100644 --- a/test/integration/cli-subcommands.test.js +++ b/test/integration/cli-subcommands.test.js @@ -35,12 +35,12 @@ var subs = [ ['instance list', 'instance ls', 'instances', 'insts', 'ls'], ['instance get'], ['instance create', 'create'], + ['instance start', 'start'], + ['instance stop', 'stop'], + ['instance reboot', 'reboot'], + ['instance delete', 'instance rm', 'delete', 'rm'], + ['instance wait'], ['instance audit'], - ['start-instance', 'start'], - ['stop-instance', 'stop'], - ['reboot-instance', 'reboot'], - ['delete-instance', 'delete'], - ['wait-instance', 'wait'], ['ssh'], ['networks'], ['network'],