From e21635eaa3ddad582b733465c3914f4c46f96f5c Mon Sep 17 00:00:00 2001 From: Trent Mick Date: Mon, 4 Jan 2016 09:05:53 -0800 Subject: [PATCH] clistyle: part of 'triton instance ...' --- lib/cli.js | 8 +- lib/do_create.js | 25 +++ lib/do_images.js | 2 +- .../do_audit.js} | 23 +-- .../do_create.js} | 36 ++-- lib/{do_instance.js => do_instance/do_get.js} | 16 +- lib/do_instance/do_list.js | 156 ++++++++++++++++++ lib/do_instance/index.js | 56 +++++++ lib/do_instances.js | 148 ++--------------- lib/do_packages.js | 2 +- test/unit/metadataFromOpts.test.js | 3 +- test/unit/tagsFromOpts.test.js | 2 +- 12 files changed, 292 insertions(+), 185 deletions(-) create mode 100644 lib/do_create.js rename lib/{do_instance_audit.js => do_instance/do_audit.js} (82%) rename lib/{do_create_instance.js => do_instance/do_create.js} (95%) rename lib/{do_instance.js => do_instance/do_get.js} (81%) create mode 100644 lib/do_instance/do_list.js create mode 100644 lib/do_instance/index.js diff --git a/lib/cli.js b/lib/cli.js index 7061d28..a246312 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -194,10 +194,9 @@ function CLI() { 'help', 'profile', { group: 'Instances (aka VMs/Machines/Containers)' }, - 'create-instance', - 'instances', 'instance', - 'instance-audit', + 'instances', + 'create', 'start-instance', 'stop-instance', 'reboot-instance', @@ -349,8 +348,7 @@ CLI.prototype.do_image = require('./do_image'); // Instances (aka VMs/containers/machines) CLI.prototype.do_instance = require('./do_instance'); CLI.prototype.do_instances = require('./do_instances'); -CLI.prototype.do_create_instance = require('./do_create_instance'); -CLI.prototype.do_instance_audit = require('./do_instance_audit'); +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'); diff --git a/lib/do_create.js b/lib/do_create.js new file mode 100644 index 0000000..2339566 --- /dev/null +++ b/lib/do_create.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 create ...` bwcompat shortcut for `triton instance create ...`. + */ + +function do_create(subcmd, opts, args, callback) { + var subcmdArgv = ['node', 'triton', 'instance', 'create'].concat(args); + this.dispatch('instance', subcmdArgv, callback); +} + +do_create.help = [ + 'A shortcut for "triton instance create".', + '', + 'Usage:', + ' {{name}} create ...' +].join('\n'); + +module.exports = do_create; diff --git a/lib/do_images.js b/lib/do_images.js index abe0c89..fa8afcd 100644 --- a/lib/do_images.js +++ b/lib/do_images.js @@ -7,7 +7,7 @@ /* * Copyright 2015 Joyent, Inc. * - * `triton images ...` bwcompat shortcut for `triton images list ...`. + * `triton images ...` bwcompat shortcut for `triton image list ...`. */ function do_images(subcmd, opts, args, callback) { diff --git a/lib/do_instance_audit.js b/lib/do_instance/do_audit.js similarity index 82% rename from lib/do_instance_audit.js rename to lib/do_instance/do_audit.js index 7619e25..ce0854c 100644 --- a/lib/do_instance_audit.js +++ b/lib/do_instance/do_audit.js @@ -7,14 +7,14 @@ /* * Copyright 2015 Joyent, Inc. * - * `triton instance-audit ...` + * `triton instance audit ...` */ var format = require('util').format; var tabula = require('tabula'); -var common = require('./common'); -var errors = require('./errors'); +var common = require('../common'); +var errors = require('../errors'); // columns default without -o var columnsDefault = 'shortid,time,action,success'; @@ -25,7 +25,8 @@ var columnsDefaultLong = 'id,time,action,success'; // sort default with -s var sortDefault = 'id,time'; -function do_instance_audit(subcmd, opts, args, cb) { + +function do_audit(subcmd, opts, args, cb) { var self = this; if (opts.help) { @@ -53,7 +54,7 @@ function do_instance_audit(subcmd, opts, args, cb) { uuid = arg; go1(); } else { - self.tritonapi.getInstance(arg, function (err, inst) { + self.top.tritonapi.getInstance(arg, function (err, inst) { if (err) { cb(err); return; @@ -64,7 +65,7 @@ function do_instance_audit(subcmd, opts, args, cb) { } function go1() { - self.tritonapi.cloudapi.machineAudit(uuid, function (err, audit) { + self.top.tritonapi.cloudapi.machineAudit(uuid, function (err, audit) { if (err) { cb(err); return; @@ -90,9 +91,9 @@ function do_instance_audit(subcmd, opts, args, cb) { } } -do_instance_audit.aliases = ['audit']; +do_audit.aliases = ['audit']; -do_instance_audit.options = [ +do_audit.options = [ { names: ['help', 'h'], type: 'bool', @@ -103,13 +104,13 @@ do_instance_audit.options = [ sortDefault: sortDefault })); -do_instance_audit.help = ( +do_audit.help = ( 'List instance actions.\n' + '\n' + 'Usage:\n' - + ' {{name}} instance-audit \n' + + ' {{name}} audit \n' + '\n' + '{{options}}' ); -module.exports = do_instance_audit; +module.exports = do_audit; diff --git a/lib/do_create_instance.js b/lib/do_instance/do_create.js similarity index 95% rename from lib/do_create_instance.js rename to lib/do_instance/do_create.js index d778b9c..b567bc6 100644 --- a/lib/do_create_instance.js +++ b/lib/do_instance/do_create.js @@ -7,7 +7,7 @@ /* * Copyright 2015 Joyent, Inc. * - * `triton create ...` + * `triton instance create ...` */ var assert = require('assert-plus'); @@ -18,9 +18,9 @@ var tabula = require('tabula'); var tilde = require('tilde-expansion'); var vasync = require('vasync'); -var common = require('./common'); -var distractions = require('./distractions'); -var errors = require('./errors'); +var common = require('../common'); +var distractions = require('../distractions'); +var errors = require('../errors'); // ---- loading/parsing metadata (and tags) from relevant options @@ -293,7 +293,7 @@ function _addMetadatumFromFile(ilk, metadata, key, file, from, cb) { // ---- the command -function do_create_instance(subcmd, opts, args, cb) { +function do_create(subcmd, opts, args, cb) { var self = this; if (opts.help) { this.do_help('help', {}, [subcmd], cb); @@ -302,8 +302,8 @@ function do_create_instance(subcmd, opts, args, cb) { return cb(new errors.UsageError('incorrect number of args')); } - var log = this.tritonapi.log; - var cloudapi = this.tritonapi.cloudapi; + var log = this.top.log; + var cloudapi = this.top.tritonapi.cloudapi; vasync.pipeline({arg: {}, funcs: [ function loadMetadata(ctx, next) { @@ -338,7 +338,7 @@ function do_create_instance(subcmd, opts, args, cb) { name: args[0], useCache: true }; - self.tritonapi.getImage(_opts, function (err, img) { + self.top.tritonapi.getImage(_opts, function (err, img) { if (err) { return next(err); } @@ -359,7 +359,7 @@ function do_create_instance(subcmd, opts, args, cb) { return; } - self.tritonapi.getPackage(id, function (err, pkg) { + self.top.tritonapi.getPackage(id, function (err, pkg) { if (err) { return next(err); } @@ -377,7 +377,7 @@ function do_create_instance(subcmd, opts, args, cb) { vasync.forEachPipeline({ inputs: opts.network, func: function getOneNetwork(name, nextNet) { - self.tritonapi.getNetwork(name, function (err, net) { + self.top.tritonapi.getNetwork(name, function (err, net) { if (err) { nextNet(err); } else { @@ -497,7 +497,7 @@ function do_create_instance(subcmd, opts, args, cb) { }); } -do_create_instance.options = [ +do_create.options = [ { names: ['help', 'h'], type: 'bool', @@ -587,25 +587,25 @@ do_create_instance.options = [ } ]; -do_create_instance.help = ( +do_create.help = ( /* BEGIN JSSTYLED */ 'Create a new instance.\n' + '\n' + 'Usage:\n' + - ' {{name}} create-instance [] IMAGE PACKAGE\n' + + ' {{name}} create [] IMAGE PACKAGE\n' + '\n' + '{{options}}' /* END JSSTYLED */ ); -do_create_instance.helpOpts = { +do_create.helpOpts = { maxHelpCol: 18 }; -do_create_instance.aliases = ['create']; +do_create.aliases = ['create']; -module.exports = do_create_instance; -do_create_instance.metadataFromOpts = metadataFromOpts; // export for testing -do_create_instance.tagsFromOpts = tagsFromOpts; // export for testing +module.exports = do_create; +do_create.metadataFromOpts = metadataFromOpts; // export for testing +do_create.tagsFromOpts = tagsFromOpts; // export for testing diff --git a/lib/do_instance.js b/lib/do_instance/do_get.js similarity index 81% rename from lib/do_instance.js rename to lib/do_instance/do_get.js index 127c053..29536c4 100644 --- a/lib/do_instance.js +++ b/lib/do_instance/do_get.js @@ -7,19 +7,19 @@ /* * Copyright 2015 Joyent, Inc. * - * `triton instance ...` + * `triton instance get ...` */ -var common = require('./common'); +var common = require('../common'); -function do_instance(subcmd, opts, args, cb) { +function do_get(subcmd, opts, args, cb) { if (opts.help) { return this.do_help('help', {}, [subcmd], cb); } else if (args.length !== 1) { return cb(new Error('invalid args: ' + args)); } - this.tritonapi.getInstance(args[0], function (err, inst) { + this.top.tritonapi.getInstance(args[0], function (err, inst) { if (err) { return cb(err); } @@ -33,7 +33,7 @@ function do_instance(subcmd, opts, args, cb) { }); } -do_instance.options = [ +do_get.options = [ { names: ['help', 'h'], type: 'bool', @@ -45,7 +45,7 @@ do_instance.options = [ help: 'JSON output.' } ]; -do_instance.help = ( +do_get.help = ( /* BEGIN JSSTYLED */ 'Get an instance.\n' + '\n' @@ -59,6 +59,4 @@ do_instance.help = ( /* END JSSTYLED */ ); -do_instance.aliases = ['inst']; - -module.exports = do_instance; +module.exports = do_get; diff --git a/lib/do_instance/do_list.js b/lib/do_instance/do_list.js new file mode 100644 index 0000000..9851343 --- /dev/null +++ b/lib/do_instance/do_list.js @@ -0,0 +1,156 @@ +/* + * 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 instance list ...` + */ + +var format = require('util').format; +var tabula = require('tabula'); +var vasync = require('vasync'); + +var common = require('../common'); + + + +// to be passed as query string args to /my/machines +var validFilters = [ + 'name', + 'image', + 'state', + 'memory', + 'tombstone', + 'credentials' +]; + +// columns default without -o +var columnsDefault = 'shortid,name,img,state,primaryIp,ago'; + +// columns default with -l +var columnsDefaultLong = 'id,name,img,package,state,primaryIp,created'; + +// sort default with -s +var sortDefault = 'created'; + +function do_list(subcmd, opts, args, callback) { + var self = this; + if (opts.help) { + this.do_help('help', {}, [subcmd], callback); + return; + } + + var columns = columnsDefault; + if (opts.o) { + columns = opts.o; + } else if (opts.long) { + columns = columnsDefaultLong; + } + columns = columns.split(','); + + var sort = opts.s.split(','); + + var listOpts; + try { + listOpts = common.kvToObj(args, validFilters); + } catch (e) { + callback(e); + return; + } + + + var imgs; + var insts; + + vasync.parallel({funcs: [ + function getTheImages(next) { + self.top.tritonapi.listImages({useCache: true}, + function (err, _imgs) { + if (err) { + next(err); + } else { + imgs = _imgs; + next(); + } + }); + }, + function getTheMachines(next) { + self.top.tritonapi.cloudapi.listMachines(listOpts, + function (err, _insts) { + if (err) { + next(err); + } else { + insts = _insts; + next(); + } + }); + } + ]}, function (err, results) { + /* + * Error handling: vasync.parallel's `err` is always a MultiError. We + * want to prefer the `getTheMachines` err, e.g. if both get a + * self-signed cert error. + */ + if (err) { + err = results.operations[1].err || err; + return callback(err); + } + + // map "uuid" => "image_name" + var imgmap = {}; + imgs.forEach(function (img) { + imgmap[img.id] = format('%s@%s', img.name, img.version); + }); + + // Add extra fields for nice output. + // XXX FWIW, the "extra fields" for images and packages are not added + // for `opts.json`. Thoughts? We should be consistent there. --TM + var now = new Date(); + insts.forEach(function (inst) { + var created = new Date(inst.created); + inst.ago = common.longAgo(created, now); + inst.img = imgmap[inst.image] || inst.image; + inst.shortid = inst.id.split('-', 1)[0]; + }); + + if (opts.json) { + common.jsonStream(insts); + } else { + tabula(insts, { + skipHeader: opts.H, + columns: columns, + sort: sort, + dottedLookup: true + }); + } + callback(); + }); +} + +do_list.options = [ + { + names: ['help', 'h'], + type: 'bool', + help: 'Show this help.' + } +].concat(common.getCliTableOptions({ + includeLong: true, + sortDefault: sortDefault +})); + +do_list.help = ( + 'List instances.\n' + + '\n' + + 'Usage:\n' + + ' {{name}} instance list [...]\n' + + '\n' + + '{{options}}' +); + +do_list.aliases = ['ls']; + +module.exports = do_list; diff --git a/lib/do_instance/index.js b/lib/do_instance/index.js new file mode 100644 index 0000000..f164974 --- /dev/null +++ b/lib/do_instance/index.js @@ -0,0 +1,56 @@ +/* + * 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 instance ...` + */ + +var Cmdln = require('cmdln').Cmdln; +var util = require('util'); + + + +// ---- CLI class + +function InstanceCLI(top) { + this.top = top; + Cmdln.call(this, { + name: top.name + ' instance', + /* BEGIN JSSTYLED */ + desc: [ + 'List, get, create and manage Triton instances.' + ].join('\n'), + /* END JSSTYLED */ + helpOpts: { + minHelpCol: 24 /* line up with option help */ + }, + helpSubcmds: [ + 'help', + 'list', + 'get', + 'create', + 'audit' + ] + }); +} +util.inherits(InstanceCLI, Cmdln); + +InstanceCLI.prototype.init = function init(opts, args, cb) { + this.log = this.top.log; + Cmdln.prototype.init.apply(this, arguments); +}; + +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.aliases = ['inst']; + +module.exports = InstanceCLI; diff --git a/lib/do_instances.js b/lib/do_instances.js index 4583d14..5bcaff7 100644 --- a/lib/do_instances.js +++ b/lib/do_instances.js @@ -7,149 +7,21 @@ /* * Copyright 2015 Joyent, Inc. * - * `triton instances ...` + * `triton instances ...` bwcompat shortcut for `triton instance list ...`. */ -var format = require('util').format; -var tabula = require('tabula'); -var vasync = require('vasync'); - -var common = require('./common'); - - - -// to be passed as query string args to /my/machines -var validFilters = [ - 'name', - 'image', - 'state', - 'memory', - 'tombstone', - 'credentials' -]; - -// columns default without -o -var columnsDefault = 'shortid,name,img,state,primaryIp,ago'; - -// columns default with -l -var columnsDefaultLong = 'id,name,img,package,state,primaryIp,created'; - -// sort default with -s -var sortDefault = 'created'; - function do_instances(subcmd, opts, args, callback) { - var self = this; - if (opts.help) { - this.do_help('help', {}, [subcmd], callback); - return; - } - - var columns = columnsDefault; - if (opts.o) { - columns = opts.o; - } else if (opts.long) { - columns = columnsDefaultLong; - } - columns = columns.split(','); - - var sort = opts.s.split(','); - - var listOpts; - try { - listOpts = common.kvToObj(args, validFilters); - } catch (e) { - callback(e); - return; - } - - - var imgs; - var insts; - - vasync.parallel({funcs: [ - function getTheImages(next) { - self.tritonapi.listImages({useCache: true}, function (err, _imgs) { - if (err) { - next(err); - } else { - imgs = _imgs; - next(); - } - }); - }, - function getTheMachines(next) { - self.tritonapi.cloudapi.listMachines(listOpts, - function (err, _insts) { - if (err) { - next(err); - } else { - insts = _insts; - next(); - } - }); - } - ]}, function (err, results) { - /* - * Error handling: vasync.parallel's `err` is always a MultiError. We - * want to prefer the `getTheMachines` err, e.g. if both get a - * self-signed cert error. - */ - if (err) { - err = results.operations[1].err || err; - return callback(err); - } - - // map "uuid" => "image_name" - var imgmap = {}; - imgs.forEach(function (img) { - imgmap[img.id] = format('%s@%s', img.name, img.version); - }); - - // Add extra fields for nice output. - // XXX FWIW, the "extra fields" for images and packages are not added - // for `opts.json`. Thoughts? We should be consistent there. --TM - var now = new Date(); - insts.forEach(function (inst) { - var created = new Date(inst.created); - inst.ago = common.longAgo(created, now); - inst.img = imgmap[inst.image] || inst.image; - inst.shortid = inst.id.split('-', 1)[0]; - }); - - if (opts.json) { - common.jsonStream(insts); - } else { - tabula(insts, { - skipHeader: opts.H, - columns: columns, - sort: sort, - dottedLookup: true - }); - } - callback(); - }); + var subcmdArgv = ['node', 'triton', 'instance', 'list'].concat(args); + this.dispatch('instance', subcmdArgv, callback); } -do_instances.options = [ - { - names: ['help', 'h'], - type: 'bool', - help: 'Show this help.' - } -].concat(common.getCliTableOptions({ - includeLong: true, - sortDefault: sortDefault -})); +do_instances.help = [ + 'A shortcut for "triton instance list".', + '', + 'Usage:', + ' {{name}} instances ...' +].join('\n'); -do_instances.help = ( - 'List instances.\n' - + '\n' - + 'Usage:\n' - + ' {{name}} instances [...]\n' - + '\n' - + '{{options}}' -); - -do_instances.aliases = ['insts', 'list', 'ls']; +do_instances.aliases = ['insts', 'ls']; module.exports = do_instances; diff --git a/lib/do_packages.js b/lib/do_packages.js index f4ad952..c853c7e 100644 --- a/lib/do_packages.js +++ b/lib/do_packages.js @@ -7,7 +7,7 @@ /* * Copyright 2015 Joyent, Inc. * - * `triton packages ...` bwcompat shortcut for `triton packages list ...`. + * `triton packages ...` bwcompat shortcut for `triton package list ...`. */ function do_packages(subcmd, opts, args, callback) { diff --git a/test/unit/metadataFromOpts.test.js b/test/unit/metadataFromOpts.test.js index 67939de..0227b75 100644 --- a/test/unit/metadataFromOpts.test.js +++ b/test/unit/metadataFromOpts.test.js @@ -17,7 +17,8 @@ var cmdln = require('cmdln'); var format = require('util').format; var test = require('tape'); -var metadataFromOpts = require('../../lib/do_create_instance').metadataFromOpts; +var metadataFromOpts = + require('../../lib/do_instance/do_create').metadataFromOpts; // ---- globals diff --git a/test/unit/tagsFromOpts.test.js b/test/unit/tagsFromOpts.test.js index 733543f..e71a064 100644 --- a/test/unit/tagsFromOpts.test.js +++ b/test/unit/tagsFromOpts.test.js @@ -17,7 +17,7 @@ var cmdln = require('cmdln'); var format = require('util').format; var test = require('tape'); -var tagsFromOpts = require('../../lib/do_create_instance').tagsFromOpts; +var tagsFromOpts = require('../../lib/do_instance/do_create').tagsFromOpts; // ---- globals