From 632d5a6568b7b67eb6d73eab6e60c46824fbd750 Mon Sep 17 00:00:00 2001 From: Trent Mick Date: Wed, 30 Dec 2015 13:11:57 -0800 Subject: [PATCH] style: triton img ... --- lib/cli.js | 1 - lib/{do_image.js => do_image/do_get.js} | 20 ++- lib/do_image/do_list.js | 158 +++++++++++++++++++ lib/do_image/index.js | 52 ++++++ lib/do_images.js | 151 ++---------------- lib/do_package/do_get.js | 2 +- lib/do_package/do_list.js | 2 +- test/integration/cli-manage-workflow.test.js | 2 +- 8 files changed, 233 insertions(+), 155 deletions(-) rename lib/{do_image.js => do_image/do_get.js} (77%) create mode 100644 lib/do_image/do_list.js create mode 100644 lib/do_image/index.js diff --git a/lib/cli.js b/lib/cli.js index ce88c1e..49246ce 100644 --- a/lib/cli.js +++ b/lib/cli.js @@ -206,7 +206,6 @@ function CLI() { 'wait-instance', 'ssh', { group: 'Images, Packages, Networks' }, - 'images', 'image', 'package', 'networks', diff --git a/lib/do_image.js b/lib/do_image/do_get.js similarity index 77% rename from lib/do_image.js rename to lib/do_image/do_get.js index d583b89..af32f26 100644 --- a/lib/do_image.js +++ b/lib/do_image/do_get.js @@ -7,15 +7,15 @@ /* * Copyright 2015 Joyent, Inc. * - * `triton image ...` + * `triton image get ...` */ var format = require('util').format; -var errors = require('./errors'); +var errors = require('../errors'); -function do_image(subcmd, opts, args, callback) { +function do_get(subcmd, opts, args, callback) { if (opts.help) { this.do_help('help', {}, [subcmd], callback); return; @@ -24,7 +24,7 @@ function do_image(subcmd, opts, args, callback) { 'incorrect number of args (%d)', args.length))); } - this.tritonapi.getImage(args[0], function onRes(err, img) { + this.top.tritonapi.getImage(args[0], function onRes(err, img) { if (err) { return callback(err); } @@ -38,7 +38,7 @@ function do_image(subcmd, opts, args, callback) { }); } -do_image.options = [ +do_get.options = [ { names: ['help', 'h'], type: 'bool', @@ -50,16 +50,16 @@ do_image.options = [ help: 'JSON stream output.' } ]; -do_image.help = ( +do_get.help = ( /* BEGIN JSSTYLED */ 'Get an image.\n' + '\n' + 'Usage:\n' + - ' {{name}} image [] ID|NAME\n' + + ' {{name}} image get [] ID|NAME\n' + '\n' + '{{options}}' + '\n' + - 'If there are more than one image with the given "NAME", the latest\n' + + 'If there is more than one image with the given "NAME", the latest\n' + 'image (by "published_at") is returned.\n' + '\n' + 'Note: Currently this dumps prettified JSON by default. That might change\n' + @@ -67,6 +67,4 @@ do_image.help = ( /* END JSSTYLED */ ); -do_image.aliases = ['img']; - -module.exports = do_image; +module.exports = do_get; diff --git a/lib/do_image/do_list.js b/lib/do_image/do_list.js new file mode 100644 index 0000000..35f909f --- /dev/null +++ b/lib/do_image/do_list.js @@ -0,0 +1,158 @@ +/* + * 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 image list ...` + */ + +var format = require('util').format; +var tabula = require('tabula'); + +var common = require('../common'); +var errors = require('../errors'); + +// filters to pass triton.listImages +var validFilters = [ + 'name', + 'os', + 'version', + 'public', + 'state', + 'owner', + 'type' +]; + +// columns default without -o +var columnsDefault = 'shortid,name,version,state,flags,os,pubdate'; + +// columns default with -l +var columnsDefaultLong = 'id,name,version,state,flags,os,pubdate'; + +// sort default with -s +var sortDefault = 'published_at'; + +function do_list(subcmd, opts, args, callback) { + 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; + } + if (opts.all) { + listOpts.state = 'all'; + } + + this.top.tritonapi.listImages(listOpts, function onRes(err, imgs, res) { + if (err) { + return callback(err); + } + + if (opts.json) { + // XXX we should have a common method for all these: + // XXX sorting + // XXX if opts.o is given, then filter to just those fields? + common.jsonStream(imgs); + } else { + // Add some convenience fields + // Added fields taken from imgapi-cli.git. + for (var i = 0; i < imgs.length; i++) { + var img = imgs[i]; + img.shortid = img.id.split('-', 1)[0]; + if (img.published_at) { + // Just the date. + img.pubdate = img.published_at.slice(0, 10); + // Normalize on no milliseconds. + img.pub = img.published_at.replace(/\.\d+Z$/, 'Z'); + } + if (img.files && img.files[0]) { + img.size = img.files[0].size; + } + var flags = []; + if (img.origin) flags.push('I'); + if (img['public']) flags.push('P'); + if (img.state !== 'active') flags.push('X'); + img.flags = flags.length ? flags.join('') : undefined; + } + + tabula(imgs, { + skipHeader: opts.H, + columns: columns, + sort: sort + }); + } + callback(); + }); +} + +do_list.options = [ + { + names: ['help', 'h'], + type: 'bool', + help: 'Show this help.' + }, + { + group: 'Filtering options' + }, + { + names: ['all', 'a'], + type: 'bool', + help: 'List all images, not just "active" ones. This ' + + 'is a shortcut for the "state=all" filter.' + } +].concat(common.getCliTableOptions({ + includeLong: true, + sortDefault: sortDefault +})); + +do_list.help = ( + /* BEGIN JSSTYLED */ + 'List images.\n' + + '\n' + + 'Usage:\n' + + ' {{name}} image list [] []\n' + + '\n' + + '{{options}}' + + '\n' + + 'Filters:\n' + + ' FIELD=VALUE Field equality filter. Supported fields: \n' + + ' account, owner, state, name, os, and type.\n' + + ' FIELD=true|false Field boolean filter. Supported fields: public.\n' + + ' FIELD=~SUBSTRING Field substring filter. Supported fields: name\n' + + '\n' + + 'Fields (most are self explanatory, the client adds some for convenience):\n' + + ' shortid A short ID prefix.\n' + + ' flags This is a set of single letter flags\n' + + ' summarizing some fields. "P" indicates the\n' + + ' image is public. "I" indicates an incremental\n' + + ' image (i.e. has an origin). "X" indicates an\n' + + ' image with a state *other* than "active".\n' + + ' pubdate Short form of "published_at" with just the date\n' + + ' pub Short form of "published_at" elliding milliseconds.\n' + + ' size The number of bytes of the image file (files.0.size)\n' + /* END JSSTYLED */ +); + +do_list.aliases = ['ls']; + +module.exports = do_list; diff --git a/lib/do_image/index.js b/lib/do_image/index.js new file mode 100644 index 0000000..cc65e3b --- /dev/null +++ b/lib/do_image/index.js @@ -0,0 +1,52 @@ +/* + * 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 image ...` + */ + +var Cmdln = require('cmdln').Cmdln; +var util = require('util'); + + + +// ---- CLI class + +function ImageCLI(top) { + this.top = top; + Cmdln.call(this, { + name: top.name + ' image', + /* BEGIN JSSTYLED */ + desc: [ + 'List, get, create and update Triton images.' + ].join('\n'), + /* END JSSTYLED */ + helpOpts: { + minHelpCol: 24 /* line up with option help */ + }, + helpSubcmds: [ + 'help', + 'list', + 'get' + ] + }); +} +util.inherits(ImageCLI, Cmdln); + +ImageCLI.prototype.init = function init(opts, args, cb) { + this.log = this.top.log; + Cmdln.prototype.init.apply(this, arguments); +}; + +ImageCLI.prototype.do_list = require('./do_list'); +ImageCLI.prototype.do_get = require('./do_get'); + + +ImageCLI.aliases = ['img']; + +module.exports = ImageCLI; diff --git a/lib/do_images.js b/lib/do_images.js index 1f17eb7..abe0c89 100644 --- a/lib/do_images.js +++ b/lib/do_images.js @@ -7,152 +7,23 @@ /* * Copyright 2015 Joyent, Inc. * - * `triton images ...` + * `triton images ...` bwcompat shortcut for `triton images list ...`. */ -var format = require('util').format; -var tabula = require('tabula'); - -var common = require('./common'); -var errors = require('./errors'); - -// filters to pass triton.listImages -var validFilters = [ - 'name', - 'os', - 'version', - 'public', - 'state', - 'owner', - 'type' -]; - -// columns default without -o -var columnsDefault = 'shortid,name,version,state,flags,os,pubdate'; - -// columns default with -l -var columnsDefaultLong = 'id,name,version,state,flags,os,pubdate'; - -// sort default with -s -var sortDefault = 'published_at'; - function do_images(subcmd, opts, args, callback) { - 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; - } - if (opts.all) { - listOpts.state = 'all'; - } - - this.tritonapi.listImages(listOpts, function onRes(err, imgs, res) { - if (err) { - return callback(err); - } - - if (opts.json) { - // XXX we should have a common method for all these: - // XXX sorting - // XXX if opts.o is given, then filter to just those fields? - common.jsonStream(imgs); - } else { - // Add some convenience fields - // Added fields taken from imgapi-cli.git. - for (var i = 0; i < imgs.length; i++) { - var img = imgs[i]; - img.shortid = img.id.split('-', 1)[0]; - if (img.published_at) { - // Just the date. - img.pubdate = img.published_at.slice(0, 10); - // Normalize on no milliseconds. - img.pub = img.published_at.replace(/\.\d+Z$/, 'Z'); - } - if (img.files && img.files[0]) { - img.size = img.files[0].size; - } - var flags = []; - if (img.origin) flags.push('I'); - if (img['public']) flags.push('P'); - if (img.state !== 'active') flags.push('X'); - img.flags = flags.length ? flags.join('') : undefined; - } - - tabula(imgs, { - skipHeader: opts.H, - columns: columns, - sort: sort - }); - } - callback(); - }); + var subcmdArgv = ['node', 'triton', 'image', 'list'].concat(args); + this.dispatch('image', subcmdArgv, callback); } -do_images.options = [ - { - names: ['help', 'h'], - type: 'bool', - help: 'Show this help.' - }, - { - group: 'Filtering options' - }, - { - names: ['all', 'a'], - type: 'bool', - help: 'List all images, not just "active" ones. This ' + - 'is a shortcut for the "state=all" filter.' - } -].concat(common.getCliTableOptions({ - includeLong: true, - sortDefault: sortDefault -})); - -do_images.help = ( - /* BEGIN JSSTYLED */ - 'List images.\n' + - '\n' + - 'Usage:\n' + - ' {{name}} images [] []\n' + - '\n' + - '{{options}}' + - '\n' + - 'Filters:\n' + - ' FIELD=VALUE Field equality filter. Supported fields: \n' + - ' account, owner, state, name, os, and type.\n' + - ' FIELD=true|false Field boolean filter. Supported fields: public.\n' + - ' FIELD=~SUBSTRING Field substring filter. Supported fields: name\n' + - '\n' + - 'Fields (most are self explanatory, the client adds some for convenience):\n' + - ' shortid A short ID prefix.\n' + - ' flags This is a set of single letter flags\n' + - ' summarizing some fields. "P" indicates the\n' + - ' image is public. "I" indicates an incremental\n' + - ' image (i.e. has an origin). "X" indicates an\n' + - ' image with a state *other* than "active".\n' + - ' pubdate Short form of "published_at" with just the date\n' + - ' pub Short form of "published_at" elliding milliseconds.\n' + - ' size The number of bytes of the image file (files.0.size)\n' - /* END JSSTYLED */ -); +do_images.help = [ + 'A shortcut for "triton image list".', + '', + 'Usage:', + ' {{name}} images ...' +].join('\n'); do_images.aliases = ['imgs']; +do_images.hidden = true; + module.exports = do_images; diff --git a/lib/do_package/do_get.js b/lib/do_package/do_get.js index 38d83b9..4e2f5f7 100644 --- a/lib/do_package/do_get.js +++ b/lib/do_package/do_get.js @@ -55,7 +55,7 @@ do_get.help = ( 'Get a package.\n' + '\n' + 'Usage:\n' + - ' {{name}} package [] ID|NAME\n' + + ' {{name}} package get [] ID|NAME\n' + '\n' + '{{options}}' + '\n' + diff --git a/lib/do_package/do_list.js b/lib/do_package/do_list.js index c014827..bd0fe70 100644 --- a/lib/do_package/do_list.js +++ b/lib/do_package/do_list.js @@ -159,7 +159,7 @@ do_list.help = [ 'List packgaes.', '', 'Usage:', - ' {{name}} packages []', + ' {{name}} package list []', '', '{{options}}', 'Filters:', diff --git a/test/integration/cli-manage-workflow.test.js b/test/integration/cli-manage-workflow.test.js index a76832e..0d64b56 100644 --- a/test/integration/cli-manage-workflow.test.js +++ b/test/integration/cli-manage-workflow.test.js @@ -100,7 +100,7 @@ test('triton manage workflow', opts, function (tt) { 'minimal-32': true, 'base': true }; - h.safeTriton(t, ['imgs', '-j'], function (stdout) { + h.safeTriton(t, ['img', 'ls', '-j'], function (stdout) { var imgs = _jsonStreamParse(stdout); // Newest images first. tabula.sortArrayOfObjects(imgs, ['-published_at']);