joyent/node-triton#113 error help for usage errors
This builds on cmdln 4.x's "errHelp" facilities.
This commit is contained in:
parent
42d5382c7e
commit
fabe0a0841
26
CHANGES.md
26
CHANGES.md
@ -5,9 +5,31 @@ Known issues:
|
||||
- `triton ssh ...` disables ssh ControlMaster to avoid issue #52.
|
||||
|
||||
|
||||
## 4.12.1 (not yet released)
|
||||
## 4.13.0 (not yet released)
|
||||
|
||||
(nothing yet)
|
||||
- [#113] *Usage* errors now some "error help", including option or command
|
||||
synopses. Some examples (the new thing is marked with `>`):
|
||||
|
||||
- Command synopses when argument errors:
|
||||
|
||||
$ triton create
|
||||
triton instance create: error (Usage): incorrect number of args
|
||||
> usage: triton instance create [OPTIONS] IMAGE PACKAGE
|
||||
|
||||
- Option synopsis with option errors:
|
||||
|
||||
$ triton image ls --bogus
|
||||
triton image ls: error (Option): unknown option: "--bogus"
|
||||
> usage: triton image ls [ --help | -h ] [ --all | -a ] [ -H ] [ -o field1,... ]
|
||||
> [ --long | -l ] [ -s field1,... ] [ --json | -j ] ...
|
||||
|
||||
- Suggested command name misspellings:
|
||||
|
||||
$ triton in
|
||||
triton: error (UnknownCommand): unknown command: "in"
|
||||
> Did you mean this?
|
||||
> info
|
||||
> inst
|
||||
|
||||
|
||||
## 4.12.0
|
||||
|
30
lib/cli.js
30
lib/cli.js
@ -342,7 +342,7 @@ CLI.prototype.fini = function fini(subcmd, err, cb) {
|
||||
this._tritonapi.close();
|
||||
delete this._tritonapi;
|
||||
}
|
||||
cb(err, subcmd);
|
||||
cb();
|
||||
};
|
||||
|
||||
|
||||
@ -667,7 +667,7 @@ function main(argv) {
|
||||
}
|
||||
|
||||
var cli = new CLI();
|
||||
cli.main(argv, function (err, subcmd) {
|
||||
cli.main(argv, function (err) {
|
||||
var exitStatus = (err ? err.exitStatus || 1 : 0);
|
||||
var showErr = (cli.showErr !== undefined ? cli.showErr : true);
|
||||
|
||||
@ -677,7 +677,7 @@ function main(argv) {
|
||||
/* jsl:pass */
|
||||
} else if (err.message !== undefined) {
|
||||
/*
|
||||
* If the err has `body.errors` (as some Triton/SDC APIs do per
|
||||
* If the err has `body.errors`, as some Triton/SDC APIs do per
|
||||
* // JSSTYLED
|
||||
* https://github.com/joyent/eng/blob/master/docs/index.md#error-handling
|
||||
* then append a one-line summary for each error object.
|
||||
@ -692,27 +692,14 @@ function main(argv) {
|
||||
});
|
||||
}
|
||||
|
||||
console.error('%s%s: error%s: %s%s',
|
||||
cli.name,
|
||||
(subcmd ? ' ' + subcmd : ''),
|
||||
console.error('%s: error%s: %s%s',
|
||||
cmdln.nameFromErr(err),
|
||||
(code ? format(' (%s)', code) : ''),
|
||||
(cli.showErrStack ? err.stack : err.message),
|
||||
bodyErrors);
|
||||
|
||||
// If this is a usage error, attempt to show some usage info.
|
||||
if (['Usage', 'Option'].indexOf(code) !== -1 && subcmd) {
|
||||
var help = cli.helpFromSubcmd(subcmd);
|
||||
if (help && typeof (help) === 'string') {
|
||||
// Would like a shorter synopsis. Attempt to
|
||||
// parse it down, somewhat generally. Unfortunately this
|
||||
// doesn't work for multi-level subcmds, like
|
||||
// `triton rbac subcmd ...`.
|
||||
var usageIdx = help.indexOf('\nUsage:');
|
||||
if (usageIdx !== -1) {
|
||||
help = help.slice(usageIdx);
|
||||
}
|
||||
console.error(help);
|
||||
}
|
||||
var errHelp = cmdln.errHelpFromErr(err);
|
||||
if (errHelp) {
|
||||
console.error(errHelp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -728,6 +715,7 @@ function main(argv) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//---- exports
|
||||
|
||||
module.exports = {
|
||||
|
@ -129,6 +129,8 @@ function jsonStream(arr, stream) {
|
||||
*
|
||||
* @param {Array} kvs - an array of key=value pairs
|
||||
* @param {Array} valid (optional) - an array to validate pairs
|
||||
*
|
||||
* TODO: merge this with objFromKeyValueArgs !
|
||||
*/
|
||||
function kvToObj(kvs, valid) {
|
||||
assert.arrayOfString(kvs, 'kvs');
|
||||
|
@ -58,13 +58,15 @@ do_get.options = [
|
||||
help: 'JSON output.'
|
||||
}
|
||||
];
|
||||
do_get.help = (
|
||||
'Show account information\n'
|
||||
+ '\n'
|
||||
+ 'Usage:\n'
|
||||
+ ' {{name}} get\n'
|
||||
+ '\n'
|
||||
+ '{{options}}'
|
||||
);
|
||||
|
||||
do_get.synopses = ['{{name}} {{cmd}}'];
|
||||
|
||||
do_get.help = [
|
||||
'Show account information',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
].join('\n');
|
||||
|
||||
module.exports = do_get;
|
||||
|
@ -148,13 +148,17 @@ do_update.options = [
|
||||
'JSON from stdin.'
|
||||
}
|
||||
];
|
||||
|
||||
do_update.synopses = [
|
||||
'{{name}} {{cmd}} [FIELD=VALUE ...]',
|
||||
'{{name}} {{cmd}} -f JSON-FILE'
|
||||
];
|
||||
|
||||
do_update.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Update account information',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} update [FIELD=VALUE ...]',
|
||||
' {{name}} update -f JSON-FILE',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
|
||||
|
@ -57,7 +57,7 @@ function do_cloudapi(subcmd, opts, args, callback) {
|
||||
reqOpts.data = JSON.parse(opts.data);
|
||||
} catch (parseErr) {
|
||||
callback(new errors.TritonError(parseErr,
|
||||
'given <data> is not valid JSON: ' + parseErr.message));
|
||||
'given DATA is not valid JSON: ' + parseErr.message));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -94,13 +94,13 @@ do_cloudapi.options = [
|
||||
{
|
||||
names: ['method', 'X'],
|
||||
type: 'string',
|
||||
helpArg: '<method>',
|
||||
helpArg: 'METHOD',
|
||||
help: 'Request method to use. Default is "GET".'
|
||||
},
|
||||
{
|
||||
names: ['header', 'H'],
|
||||
type: 'arrayOfString',
|
||||
helpArg: '<header>',
|
||||
helpArg: 'HEADER',
|
||||
help: 'Headers to send with request.'
|
||||
},
|
||||
{
|
||||
@ -111,19 +111,25 @@ do_cloudapi.options = [
|
||||
{
|
||||
names: ['data', 'd'],
|
||||
type: 'string',
|
||||
helpArg: '<data>',
|
||||
helpArg: 'DATA',
|
||||
help: 'Add POST data. This must be valid JSON.'
|
||||
}
|
||||
];
|
||||
do_cloudapi.help = (
|
||||
'Raw cloudapi request.\n'
|
||||
+ '\n'
|
||||
+ 'Usage:\n'
|
||||
+ ' {{name}} cloudapi [-X <method>] [-H <header=value>] \\\n'
|
||||
+ ' [-d <data>] <endpoint>\n'
|
||||
+ '\n'
|
||||
+ '{{options}}'
|
||||
);
|
||||
|
||||
do_cloudapi.synopses = [
|
||||
'{{name}} {{cmd}} [-X METHOD] [-H HEADER=VAL] [-d DATA] ENDPOINT'
|
||||
];
|
||||
|
||||
do_cloudapi.help = [
|
||||
'Raw cloudapi request.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Examples:',
|
||||
' {{name}} {{cmd}} /--ping',
|
||||
' {{name}} {{cmd}} /my/machines'
|
||||
].join('\n');
|
||||
|
||||
do_cloudapi.hidden = true;
|
||||
|
||||
|
@ -75,15 +75,16 @@ do_datacenters.options = [
|
||||
sortDefault: sortDefault
|
||||
}));
|
||||
|
||||
do_datacenters.help = (
|
||||
'Show datacenters in this cloud.\n'
|
||||
+ 'A "cloud" is a set of related datacenters that share account\n'
|
||||
+ 'information.\n'
|
||||
+ '\n'
|
||||
+ 'Usage:\n'
|
||||
+ ' {{name}} datacenters\n'
|
||||
+ '\n'
|
||||
+ '{{options}}'
|
||||
);
|
||||
do_datacenters.synopses = ['{{name}} {{cmd}}'];
|
||||
|
||||
do_datacenters.help = [
|
||||
'Show datacenters in this cloud.',
|
||||
'A "cloud" is a set of related datacenters that share account',
|
||||
'information.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
].join('\n');
|
||||
|
||||
module.exports = do_datacenters;
|
||||
|
@ -198,7 +198,8 @@ do_env.options = [
|
||||
}
|
||||
];
|
||||
|
||||
// TODO: support env for docker usage.
|
||||
do_env.synopses = ['{{name}} {{cmd}} [PROFILE]'];
|
||||
|
||||
do_env.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Emit shell commands to setup environment.',
|
||||
@ -207,8 +208,7 @@ do_env.help = [
|
||||
'and node-triton itself. By default this emits the environment for all',
|
||||
'supported tools. Use options to be specific.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} env [PROFILE]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'If no options are given, environment variables are emitted for all clients.',
|
||||
|
@ -28,7 +28,7 @@ function do_create(subcmd, opts, args, cb) {
|
||||
return;
|
||||
}
|
||||
if (args.length === 0) {
|
||||
cb(new errors.UsageError('missing <fwrule> argument'));
|
||||
cb(new errors.UsageError('missing FWRULE argument'));
|
||||
return;
|
||||
} else if (args.length > 1) {
|
||||
cb(new errors.UsageError('incorrect number of arguments'));
|
||||
@ -79,17 +79,31 @@ do_create.options = [
|
||||
{
|
||||
names: ['description', 'D'],
|
||||
type: 'string',
|
||||
helpArg: '<desc>',
|
||||
helpArg: 'DESC',
|
||||
help: 'Description of the firewall rule.'
|
||||
}
|
||||
];
|
||||
|
||||
do_create.synopses = ['{{name}} {{cmd}} [OPTIONS] RULE-TEXT'];
|
||||
|
||||
do_create.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Create a firewall rule.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} create [<options>] <fwrule>',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
'{{options}}',
|
||||
'Examples:',
|
||||
' # Allow SSH access from any IP to all instances in a datacenter.',
|
||||
' triton fwrule create -D "ssh" "FROM any TO all vms ALLOW tcp PORT 22"',
|
||||
'',
|
||||
' # Allow SSH access to a specific instance.',
|
||||
' triton fwrule create \\',
|
||||
' "FROM any TO vm ba2c95e9-1cdf-4295-8253-3fee371374d9 ALLOW tcp PORT 22"'
|
||||
// TODO: link to
|
||||
// https://github.com/joyent/sdc-fwrule/blob/master/docs/examples.md
|
||||
// or docs.jo Cloud Firewall examples? What link? Ditto in parent.
|
||||
/* END JSSTYLED */
|
||||
].join('\n');
|
||||
|
||||
do_create.helpOpts = {
|
||||
|
@ -27,7 +27,7 @@ function do_delete(subcmd, opts, args, cb) {
|
||||
}
|
||||
|
||||
if (args.length < 1) {
|
||||
cb(new errors.UsageError('missing <fwrule-id> argument(s)'));
|
||||
cb(new errors.UsageError('missing FWRULE argument(s)'));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -96,13 +96,16 @@ do_delete.options = [
|
||||
help: 'Skip confirmation of delete.'
|
||||
}
|
||||
];
|
||||
|
||||
do_delete.synopses = ['{{name}} {{cmd}} FWRULE [FWRULE ...]'];
|
||||
|
||||
do_delete.help = [
|
||||
'Remove a firewall rule.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} delete [<options>] <fwrule-id> [<fwrule-id>...]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
'{{options}}',
|
||||
'Where FWRULE is a firewall rule id (full UUID) or short id.'
|
||||
].join('\n');
|
||||
|
||||
do_delete.aliases = ['rm'];
|
||||
|
@ -26,7 +26,7 @@ function do_disable(subcmd, opts, args, cb) {
|
||||
}
|
||||
|
||||
if (args.length === 0) {
|
||||
cb(new errors.UsageError('Missing <fwrule-id> argument(s)'));
|
||||
cb(new errors.UsageError('missing FWRULE argument(s)'));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -56,13 +56,16 @@ do_disable.options = [
|
||||
help: 'Show this help.'
|
||||
}
|
||||
];
|
||||
|
||||
do_disable.synopses = ['{{name}} {{cmd}} FWRULE [FWRULE ...]'];
|
||||
|
||||
do_disable.help = [
|
||||
'Disable a specific firewall rule.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} disable <fwrule-id> [<fwrule-id>...]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
'{{options}}',
|
||||
'Where FWRULE is a firewall rule id (full UUID) or short id.'
|
||||
].join('\n');
|
||||
|
||||
do_disable.completionArgtypes = ['tritonfwrule'];
|
||||
|
@ -26,7 +26,7 @@ function do_enable(subcmd, opts, args, cb) {
|
||||
}
|
||||
|
||||
if (args.length === 0) {
|
||||
cb(new errors.UsageError('Missing <fwrule-id> argument(s)'));
|
||||
cb(new errors.UsageError('missing FWRULE argument(s)'));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -56,13 +56,16 @@ do_enable.options = [
|
||||
help: 'Show this help.'
|
||||
}
|
||||
];
|
||||
|
||||
do_enable.synopses = ['{{name}} {{cmd}} FWRULE [FWRULE ...]'];
|
||||
|
||||
do_enable.help = [
|
||||
'Enable a specific firewall rule.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} enable <fwrule-id> [<fwrule-id>...]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
'{{options}}',
|
||||
'Where FWRULE is a firewall rule id (full UUID) or short id.'
|
||||
].join('\n');
|
||||
|
||||
do_enable.completionArgtypes = ['tritonfwrule'];
|
||||
|
@ -25,7 +25,7 @@ function do_get(subcmd, opts, args, cb) {
|
||||
}
|
||||
|
||||
if (args.length === 0) {
|
||||
cb(new errors.UsageError('missing <fwrule-id> argument'));
|
||||
cb(new errors.UsageError('missing FWRULE argument'));
|
||||
return;
|
||||
} else if (args.length > 1) {
|
||||
cb(new errors.UsageError('incorrect number of arguments'));
|
||||
@ -64,13 +64,16 @@ do_get.options = [
|
||||
help: 'JSON stream output.'
|
||||
}
|
||||
];
|
||||
|
||||
do_get.synopses = ['{{name}} {{cmd}} FWRULE'];
|
||||
|
||||
do_get.help = [
|
||||
'Show a specific firewall rule.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} get <fwrule-id>',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
'{{options}}',
|
||||
'Where FWRULE is a firewall rule id (full UUID) or short id.'
|
||||
].join('\n');
|
||||
|
||||
do_get.completionArgtypes = ['tritonfwrule', 'none'];
|
||||
|
@ -30,7 +30,7 @@ function do_instances(subcmd, opts, args, cb) {
|
||||
}
|
||||
|
||||
if (args.length === 0) {
|
||||
cb(new errors.UsageError('missing <fwrule-id> argument'));
|
||||
cb(new errors.UsageError('missing FWRULE argument'));
|
||||
return;
|
||||
} else if (args.length > 1) {
|
||||
cb(new errors.UsageError('incorrect number of arguments'));
|
||||
@ -135,14 +135,16 @@ do_instances.options = [
|
||||
sortDefault: SORT_DEFAULT
|
||||
}));
|
||||
|
||||
do_instances.synopses = ['{{name}} {{cmd}} [OPTIONS] FWRULE'];
|
||||
|
||||
do_instances.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'List instances a firewall rule is applied to.',
|
||||
'List instances to which a firewall rule applies',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} instances [<options>] <fwrule-id>',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where FWRULE is a firewall rule id (full UUID) or short id.',
|
||||
'',
|
||||
'Fields (most are self explanatory, "*" indicates a field added client-side',
|
||||
'for convenience):',
|
||||
|
@ -84,11 +84,12 @@ do_list.options = [
|
||||
sortDefault: SORT_DEFAULT
|
||||
}));
|
||||
|
||||
do_list.synopses = ['{{name}} {{cmd}} [OPTIONS]'];
|
||||
|
||||
do_list.help = [
|
||||
'Show all firewall rules.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} list [<options>]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
].join('\n');
|
||||
|
@ -31,7 +31,7 @@ function do_update(subcmd, opts, args, cb) {
|
||||
var tritonapi = this.top.tritonapi;
|
||||
|
||||
if (args.length === 0) {
|
||||
cb(new errors.UsageError('missing <fwrule-id> argument'));
|
||||
cb(new errors.UsageError('missing FWRULE argument'));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -164,17 +164,20 @@ do_update.options = [
|
||||
{
|
||||
names: ['file', 'f'],
|
||||
type: 'string',
|
||||
helpArg: '<json-file>',
|
||||
helpArg: 'JSON-FILE',
|
||||
help: 'A file holding a JSON file of updates, or "-" to read ' +
|
||||
'JSON from stdin.'
|
||||
}
|
||||
];
|
||||
|
||||
do_update.synopses = [
|
||||
'{{name}} {{cmd}} FWRULE [FIELD=VALUE ...]',
|
||||
'{{name}} {{cmd}} -f JSON-FILE FWRULE'
|
||||
];
|
||||
do_update.help = [
|
||||
'Update a firewall rule',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} update <fwrule-id> [FIELD=VALUE ...]',
|
||||
' {{name}} update -f <json-file> <fwrule-id>',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
|
||||
@ -182,7 +185,8 @@ do_update.help = [
|
||||
' ' + Object.keys(UPDATE_FWRULE_FIELDS).sort().map(function (f) {
|
||||
return f + ' (' + UPDATE_FWRULE_FIELDS[f] + ')';
|
||||
}).join('\n '),
|
||||
''
|
||||
'',
|
||||
'Where FWRULE is a firewall rule id (full UUID) or short id.'
|
||||
].join('\n');
|
||||
|
||||
do_update.completionArgtypes = ['tritonfwrule', 'tritonupdatefwrulefield'];
|
||||
|
@ -250,16 +250,20 @@ do_create.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_create.help = (
|
||||
do_create.synopses = [
|
||||
'{{name}} {{cmd}} [OPTIONS] INST IMAGE-NAME IMAGE-VERSION'
|
||||
];
|
||||
|
||||
do_create.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Create a new instance.\n' +
|
||||
'\n' +
|
||||
'Usage:\n' +
|
||||
' {{name}} create [<options>] INSTANCE IMAGE-NAME IMAGE-VERSION\n' +
|
||||
'\n' +
|
||||
'{{options}}'
|
||||
'Create a new instance.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where "INST" is an instance name, id, or short id.'
|
||||
/* END JSSTYLED */
|
||||
);
|
||||
].join('\n');
|
||||
|
||||
do_create.helpOpts = {
|
||||
maxHelpCol: 20
|
||||
|
@ -125,19 +125,21 @@ function do_delete(subcmd, opts, args, cb) {
|
||||
});
|
||||
}
|
||||
|
||||
do_delete.synopses = ['{{name}} {{cmd}} [OPTIONS] IMAGE [IMAGE ...]'];
|
||||
|
||||
do_delete.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Delete one or more images.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} delete IMAGE [IMAGE...]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where "IMAGE" is an image ID (a full UUID), an image name (selects the',
|
||||
'Where "IMAGE" is an image id (a full UUID), an image name (selects the',
|
||||
'latest, by "published_at", image with that name), an image "name@version"',
|
||||
'(selects latest match by "published_at"), or an image short ID (ID prefix).'
|
||||
/* END JSSTYLED */
|
||||
].join('\n');
|
||||
|
||||
do_delete.options = [
|
||||
{
|
||||
names: ['help', 'h'],
|
||||
|
@ -50,22 +50,24 @@ do_get.options = [
|
||||
help: 'JSON stream output.'
|
||||
}
|
||||
];
|
||||
do_get.help = (
|
||||
|
||||
do_get.synopses = ['{{name}} {{cmd}} [OPTIONS] IMAGE'];
|
||||
|
||||
do_get.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Get an image.\n' +
|
||||
'\n' +
|
||||
'Usage:\n' +
|
||||
' {{name}} get [<options>] ID|NAME\n' +
|
||||
'\n' +
|
||||
'{{options}}' +
|
||||
'\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' +
|
||||
'in the future. Use "-j" to explicitly get JSON output.\n'
|
||||
'Get an image.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where "IMAGE" is an image id (a full UUID), an image name (selects the',
|
||||
'latest, by "published_at", image with that name), an image "name@version"',
|
||||
'(selects latest match by "published_at"), or an image short ID (ID prefix).',
|
||||
'',
|
||||
'Note: Currently this dumps prettified JSON by default. That might change',
|
||||
'in the future. Use "-j" to explicitly get JSON output.'
|
||||
/* END JSSTYLED */
|
||||
);
|
||||
].join('\n');
|
||||
|
||||
do_get.completionArgtypes = ['tritonimage', 'none'];
|
||||
|
||||
|
@ -122,6 +122,8 @@ do_list.options = [
|
||||
sortDefault: sortDefault
|
||||
}));
|
||||
|
||||
do_list.synopses = ['{{name}} {{cmd}} [OPTIONS] [FILTERS]'];
|
||||
|
||||
do_list.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'List images.',
|
||||
@ -130,8 +132,7 @@ do_list.help = [
|
||||
'You must use `docker images` against the Docker service for this data center.',
|
||||
'See <https://apidocs.joyent.com/docker>.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} list [<options>] [<filters>]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Filters:',
|
||||
|
@ -112,11 +112,12 @@ function do_wait(subcmd, opts, args, cb) {
|
||||
});
|
||||
}
|
||||
|
||||
do_wait.synopses = ['{{name}} {{cmd}} [-s STATES] IMAGE [IMAGE ...]'];
|
||||
|
||||
do_wait.help = [
|
||||
'Wait for images to change to a particular state.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} wait [-s STATES] IMAGE [IMAGE ...]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where "states" is a comma-separated list of target instance states,',
|
||||
|
@ -105,13 +105,15 @@ do_info.options = [
|
||||
help: 'JSON output.'
|
||||
}
|
||||
];
|
||||
do_info.help = (
|
||||
'Print an account summary.\n'
|
||||
+ '\n'
|
||||
+ 'Usage:\n'
|
||||
+ ' {{name}} info\n'
|
||||
+ '\n'
|
||||
+ '{{options}}'
|
||||
);
|
||||
|
||||
do_info.synopses = ['{{name}} {{cmd}}'];
|
||||
|
||||
do_info.help = [
|
||||
'Print an account summary.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
].join('\n');
|
||||
|
||||
module.exports = do_info;
|
||||
|
@ -28,13 +28,15 @@ var sortDefault = 'id,time';
|
||||
|
||||
function do_audit(subcmd, opts, args, cb) {
|
||||
var self = this;
|
||||
|
||||
if (opts.help) {
|
||||
this.do_help('help', {}, [subcmd], cb);
|
||||
return;
|
||||
} else if (args.length !== 1) {
|
||||
//XXX Support multiple machines.
|
||||
return cb(new Error('incorrect args: ' + args));
|
||||
} else if (args.length === 0) {
|
||||
cb(new errors.UsageError('missing INST argument'));
|
||||
return;
|
||||
} else if (args.length > 1) {
|
||||
cb(new errors.UsageError('too many arguments: ' + args));
|
||||
return;
|
||||
}
|
||||
|
||||
var columns = columnsDefault;
|
||||
@ -102,14 +104,15 @@ do_audit.options = [
|
||||
sortDefault: sortDefault
|
||||
}));
|
||||
|
||||
do_audit.help = (
|
||||
'List instance actions.\n'
|
||||
+ '\n'
|
||||
+ 'Usage:\n'
|
||||
+ ' {{name}} audit <alias|id>\n'
|
||||
+ '\n'
|
||||
+ '{{options}}'
|
||||
);
|
||||
do_audit.synopses = ['{{name}} {{cmd}} [OPTIONS] INST'];
|
||||
do_audit.help = [
|
||||
'List instance actions.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where "INST" is an instance name, id, or short id.'
|
||||
].join('\n');
|
||||
|
||||
do_audit.completionArgtypes = ['tritoninstance', 'none'];
|
||||
|
||||
|
@ -498,16 +498,20 @@ do_create.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_create.help = (
|
||||
do_create.synopses = ['{{name}} {{cmd}} [OPTIONS] IMAGE PACKAGE'];
|
||||
|
||||
do_create.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Create a new instance.\n' +
|
||||
'\n' +
|
||||
'Usage:\n' +
|
||||
' {{name}} create [<options>] IMAGE PACKAGE\n' +
|
||||
'\n' +
|
||||
'{{options}}'
|
||||
'Create a new instance.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where IMAGE is an image name, name@version, id, or short id (from ',
|
||||
'`triton image list`) and PACKAGE is a package name, id, or short id',
|
||||
'(from `triton package list`).'
|
||||
/* END JSSTYLED */
|
||||
);
|
||||
].join('\n');
|
||||
|
||||
do_create.helpOpts = {
|
||||
maxHelpCol: 16
|
||||
|
@ -26,7 +26,7 @@ function do_disable_firewall(subcmd, opts, args, cb) {
|
||||
}
|
||||
|
||||
if (args.length === 0) {
|
||||
cb(new errors.UsageError('Missing <inst> argument(s)'));
|
||||
cb(new errors.UsageError('missing INST argument(s)'));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -88,13 +88,16 @@ do_disable_firewall.options = [
|
||||
help: 'Wait for the firewall to be disabled.'
|
||||
}
|
||||
];
|
||||
do_disable_firewall.synopses = [
|
||||
'{{name}} disable-firewall [OPTIONS] INST [INST ...]'
|
||||
];
|
||||
do_disable_firewall.help = [
|
||||
'Disable the firewall of one or more instances.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} disable-firewall [<options>] <inst> [<inst>...]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
'{{options}}',
|
||||
'Where "INST" is an instance name, id, or short id.'
|
||||
].join('\n');
|
||||
|
||||
do_disable_firewall.completionArgtypes = ['tritoninstance'];
|
||||
|
@ -26,7 +26,7 @@ function do_enable_firewall(subcmd, opts, args, cb) {
|
||||
}
|
||||
|
||||
if (args.length === 0) {
|
||||
cb(new errors.UsageError('Missing <inst> argument(s)'));
|
||||
cb(new errors.UsageError('missing INST argument(s)'));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -88,13 +88,16 @@ do_enable_firewall.options = [
|
||||
help: 'Wait for the firewall to be enabled.'
|
||||
}
|
||||
];
|
||||
do_enable_firewall.synopses = [
|
||||
'{{name}} enable-firewall [OPTIONS] INST [INST ...]'
|
||||
];
|
||||
do_enable_firewall.help = [
|
||||
'Enable the firewall of one or more instances.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} enable-firewall [<options>] <inst> [<inst>...]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
'{{options}}',
|
||||
'Where "INST" is an instance name, id, or short id.'
|
||||
].join('\n');
|
||||
|
||||
do_enable_firewall.completionArgtypes = ['tritoninstance'];
|
||||
|
@ -31,10 +31,10 @@ function do_fwrules(subcmd, opts, args, cb) {
|
||||
}
|
||||
|
||||
if (args.length === 0) {
|
||||
cb(new errors.UsageError('missing <inst> argument'));
|
||||
cb(new errors.UsageError('missing INST argument'));
|
||||
return;
|
||||
} else if (args.length > 1) {
|
||||
cb(new errors.UsageError('incorrect number of arguments'));
|
||||
cb(new errors.UsageError('too many arguments: ' + args.join(' ')));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -91,13 +91,15 @@ do_fwrules.options = [
|
||||
sortDefault: SORT_DEFAULT
|
||||
}));
|
||||
|
||||
do_fwrules.synopses = ['{{name}} {{cmd}} [OPTIONS] INST'];
|
||||
|
||||
do_fwrules.help = [
|
||||
'Show firewall rules applied to an instance.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} fwrules [<options>] <inst>',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
'{{options}}',
|
||||
'Where "INST" is an instance name, id, or short id.'
|
||||
].join('\n');
|
||||
|
||||
do_fwrules.completionArgtypes = ['tritoninstance', 'none'];
|
||||
|
@ -43,22 +43,24 @@ do_get.options = [
|
||||
help: 'JSON output.'
|
||||
}
|
||||
];
|
||||
do_get.help = (
|
||||
do_get.synopses = ['{{name}} {{cmd}} [OPTIONS] INST'];
|
||||
do_get.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Get an instance.\n'
|
||||
+ '\n'
|
||||
+ 'Usage:\n'
|
||||
+ ' {{name}} get <alias|id>\n'
|
||||
+ '\n'
|
||||
+ '{{options}}'
|
||||
+ '\n'
|
||||
+ 'A *deleted* instance may still respond with the instance object. In that\n'
|
||||
+ 'case a the instance will be print *and* an error will be raised.\n'
|
||||
+ '\n'
|
||||
+ 'Currently this dumps prettified JSON by default. That might change\n'
|
||||
+ 'in the future. Use "-j" to explicitly get JSON output.\n'
|
||||
'Get an instance.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'',
|
||||
'Where "INST" is an instance name, id, or short id.',
|
||||
'',
|
||||
'A *deleted* instance may still respond with the instance object. In that',
|
||||
'case a the instance will be print *and* an error will be raised.',
|
||||
'',
|
||||
'Currently this dumps prettified JSON by default. That might change',
|
||||
'in the future. Use "-j" to explicitly get JSON output.'
|
||||
/* END JSSTYLED */
|
||||
);
|
||||
].join('\n');
|
||||
|
||||
do_get.completionArgtypes = ['tritoninstance', 'none'];
|
||||
|
||||
|
@ -20,10 +20,10 @@ function do_ip(subcmd, opts, args, cb) {
|
||||
this.do_help('help', {}, [subcmd], cb);
|
||||
return;
|
||||
} else if (args.length === 0) {
|
||||
cb(new errors.UsageError('missing <inst> argument'));
|
||||
cb(new errors.UsageError('missing INST argument'));
|
||||
return;
|
||||
} else if (args.length > 1) {
|
||||
cb(new errors.UsageError('too many arguments: ' + args));
|
||||
cb(new errors.UsageError('too many arguments: ' + args.join(' ')));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -54,14 +54,16 @@ do_ip.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_ip.synopses = ['{{name}} {{cmd}} INST'];
|
||||
|
||||
do_ip.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Print the primaryIp of the given instance.',
|
||||
'Print the primary IP of the given instance.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} ip <inst>',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where "INST" is an instance name, id, or short id.',
|
||||
'For example: ssh root@$(triton ip my-instance)'
|
||||
].join('\n');
|
||||
|
||||
|
@ -159,12 +159,13 @@ do_list.options = [
|
||||
sortDefault: sortDefault
|
||||
}));
|
||||
|
||||
do_list.synopses = ['{{name}} {{cmd}} [OPTIONS] [FILTERS...]'];
|
||||
|
||||
do_list.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'List instances.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} list [<filters>...]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Filters:',
|
||||
|
@ -114,7 +114,7 @@ do_create.options = [
|
||||
{
|
||||
names: ['name', 'n'],
|
||||
type: 'string',
|
||||
helpArg: '<snapname>',
|
||||
helpArg: 'SNAPNAME',
|
||||
help: 'An optional name for a snapshot.'
|
||||
},
|
||||
{
|
||||
@ -123,11 +123,13 @@ do_create.options = [
|
||||
help: 'Wait for the creation to complete.'
|
||||
}
|
||||
];
|
||||
|
||||
do_create.synopses = ['{{name}} {{cmd}} [OPTIONS] INST'];
|
||||
|
||||
do_create.help = [
|
||||
'Create a snapshot of an instance.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} create [<options>] <inst>',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Snapshot do not work for instances of type "kvm".'
|
||||
|
@ -27,7 +27,7 @@ function do_delete(subcmd, opts, args, cb) {
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
cb(new errors.UsageError('missing <inst> and <snapname> argument(s)'));
|
||||
cb(new errors.UsageError('missing INST and SNAPNAME argument(s)'));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -139,11 +139,13 @@ do_delete.options = [
|
||||
help: 'Wait for the deletion to complete.'
|
||||
}
|
||||
];
|
||||
|
||||
do_delete.synopses = ['{{name}} {{cmd}} [OPTIONS] INST SNAPNAME [SNAPNAME...]'];
|
||||
|
||||
do_delete.help = [
|
||||
'Remove a snapshot from an instance.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} delete [<options>] <inst> <snapname> [<snapname>...]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
].join('\n');
|
||||
|
@ -25,7 +25,7 @@ function do_get(subcmd, opts, args, cb) {
|
||||
}
|
||||
|
||||
if (args.length < 2) {
|
||||
cb(new errors.UsageError('missing <inst> and/or <snapname> arguments'));
|
||||
cb(new errors.UsageError('missing INST and/or SNAPNAME arguments'));
|
||||
return;
|
||||
} else if (args.length > 2) {
|
||||
cb(new errors.UsageError('incorrect number of arguments'));
|
||||
@ -55,7 +55,6 @@ function do_get(subcmd, opts, args, cb) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
do_get.options = [
|
||||
{
|
||||
names: ['help', 'h'],
|
||||
@ -68,11 +67,13 @@ do_get.options = [
|
||||
help: 'JSON stream output.'
|
||||
}
|
||||
];
|
||||
|
||||
do_get.synopses = ['{{name}} {{cmd}} [OPTIONS] INST SNAPNAME'];
|
||||
|
||||
do_get.help = [
|
||||
'Show a specific snapshot of an instance.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} get <inst> <snapname>',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
].join('\n');
|
||||
|
@ -30,7 +30,7 @@ function do_list(subcmd, opts, args, cb) {
|
||||
}
|
||||
|
||||
if (args.length === 0) {
|
||||
cb(new errors.UsageError('missing <inst> argument'));
|
||||
cb(new errors.UsageError('missing INST argument'));
|
||||
return;
|
||||
} else if (args.length > 1) {
|
||||
cb(new errors.UsageError('incorrect number of arguments'));
|
||||
@ -84,11 +84,12 @@ do_list.options = [
|
||||
sortDefault: SORT_DEFAULT
|
||||
}));
|
||||
|
||||
do_list.synopses = ['{{name}} {{cmd}} [OPTIONS] INST'];
|
||||
|
||||
do_list.help = [
|
||||
'Show all of an instance\'s snapshots.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} list [<options>] <inst>',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
].join('\n');
|
||||
|
@ -31,7 +31,7 @@ function SnapshotCLI(top) {
|
||||
'delete'
|
||||
],
|
||||
helpBody: 'Instances can be rolled back to a snapshot using\n' +
|
||||
'`triton instance start --snapshot=<snapname>`.'
|
||||
'`triton instance start --snapshot=SNAPNAME`.'
|
||||
});
|
||||
}
|
||||
util.inherits(SnapshotCLI, Cmdln);
|
||||
|
@ -14,6 +14,7 @@ var path = require('path');
|
||||
var spawn = require('child_process').spawn;
|
||||
|
||||
var common = require('../common');
|
||||
var errors = require('../errors');
|
||||
|
||||
|
||||
function do_ssh(subcmd, opts, args, callback) {
|
||||
@ -23,7 +24,7 @@ function do_ssh(subcmd, opts, args, callback) {
|
||||
this.do_help('help', {}, [subcmd], callback);
|
||||
return;
|
||||
} else if (args.length === 0) {
|
||||
callback(new Error('invalid args: ' + args));
|
||||
callback(new errors.UsageError('missing INST arg'));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -94,23 +95,23 @@ do_ssh.options = [
|
||||
help: 'Show this help.'
|
||||
}
|
||||
];
|
||||
do_ssh.synopses = ['{{name}} ssh [-h] INST [SSH-ARGUMENTS]'];
|
||||
do_ssh.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'SSH to the primary IP of an instance',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} ssh [-h] [-M] <inst> [<ssh-arguments>]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where <inst> is the name, short ID or ID of a given instance. Note that',
|
||||
'the <inst> argument must come before any `ssh` options or arguments.',
|
||||
'Where INST is the name, id, or short id of an instance. Note that',
|
||||
'the INST argument must come before any `ssh` options or arguments.',
|
||||
'',
|
||||
'There is a known issue with SSH connection multiplexing (a.k.a. ',
|
||||
'ControlMaster, mux) where stdout/stderr is lost. As a workaround, `ssh`',
|
||||
'is spawned with options disabling ControlMaster. See ',
|
||||
'<https://github.com/joyent/node-triton/issues/52> for details. If you ',
|
||||
'want to use ControlMaster, an alternative is:',
|
||||
' ssh root@$(triton ip <inst>)'
|
||||
' ssh root@$(triton ip INST)'
|
||||
/* END JSSTYLED */
|
||||
].join('\n');
|
||||
|
||||
|
@ -91,20 +91,21 @@ do_delete.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_delete.synopses = [
|
||||
'{{name}} {{cmd}} INST [NAME ...]',
|
||||
'{{name}} {{cmd}} --all INST # delete all tags'
|
||||
];
|
||||
|
||||
do_delete.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Delete one or more instance tags.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} delete <inst> [<name> ...]',
|
||||
' {{name}} delete --all <inst> # delete all tags',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where <inst> is an instance id, name, or shortid and <name> is a tag name.',
|
||||
'Where INST is an instance id, name, or shortid and NAME is a tag name.',
|
||||
'',
|
||||
'Changing instance tags is asynchronous. Use "--wait" to not return until',
|
||||
'the changes are completed.'
|
||||
/* END JSSTYLED */
|
||||
].join('\n');
|
||||
|
||||
do_delete.aliases = ['rm'];
|
||||
|
@ -53,16 +53,15 @@ do_get.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_get.synopses = ['{{name}} {{cmd}} INST NAME'];
|
||||
|
||||
do_get.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Get an instance tag.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} get <inst> <name>',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where <inst> is an instance id, name, or shortid and <name> is a tag name.'
|
||||
/* END JSSTYLED */
|
||||
'Where INST is an instance id, name, or shortid and NAME is a tag name.'
|
||||
].join('\n');
|
||||
|
||||
// TODO: When have 'tritoninstancetag' completion, add that in.
|
||||
|
@ -49,19 +49,18 @@ do_list.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_list.synopses = ['{{name}} {{cmd}} INST'];
|
||||
|
||||
do_list.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'List instance tags.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} list <inst>',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where <inst> is an instance id, name, or shortid.',
|
||||
'Where INST is an instance id, name, or shortid.',
|
||||
'',
|
||||
'Note: Currently this dumps prettified JSON by default. That might change',
|
||||
'in the future. Use "-j" to explicitly get JSON output.'
|
||||
/* END JSSTYLED */
|
||||
].join('\n');
|
||||
|
||||
do_list.aliases = ['ls'];
|
||||
|
@ -108,17 +108,19 @@ do_replace_all.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_replace_all.synopses = [
|
||||
'{{name}} {{cmd}} INST [NAME=VALUE ...]',
|
||||
'{{name}} {{cmd}} INST -f FILE # tags from file'
|
||||
];
|
||||
|
||||
do_replace_all.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Replace all tags on the given instance.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} replace-all <inst> [<name>=<value> ...]',
|
||||
' {{name}} replace-all <inst> -f <file> # tags from file',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where <inst> is an instance id, name, or shortid; <name> is a tag name;',
|
||||
'and <value> is a tag value (bool and numeric "value" are converted to ',
|
||||
'Where INST is an instance id, name, or shortid; NAME is a tag name;',
|
||||
'and VALUE is a tag value (bool and numeric "value" are converted to ',
|
||||
'that type).',
|
||||
'',
|
||||
'Currently this dumps prettified JSON by default. That might change in the',
|
||||
@ -126,7 +128,6 @@ do_replace_all.help = [
|
||||
'',
|
||||
'Changing instance tags is asynchronous. Use "--wait" to not return until',
|
||||
'the changes are completed.'
|
||||
/* END JSSTYLED */
|
||||
].join('\n');
|
||||
|
||||
do_replace_all.completionArgtypes = ['tritoninstance', 'file'];
|
||||
|
@ -109,17 +109,20 @@ do_set.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_set.synopses = [
|
||||
'{{name}} set INST [NAME=VALUE ...]',
|
||||
'{{name}} set INST -f FILE # tags from file'
|
||||
];
|
||||
|
||||
do_set.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Set one or more instance tags.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} set <inst> [<name>=<value> ...]',
|
||||
' {{name}} set <inst> -f <file> # tags from file',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where <inst> is an instance id, name, or shortid; <name> is a tag name;',
|
||||
'and <value> is a tag value (bool and numeric "value" are converted to ',
|
||||
'Where INST is an instance id, name, or shortid; NAME is a tag name;',
|
||||
'and VALUE is a tag value (bool and numeric "value" are converted to ',
|
||||
'that type).',
|
||||
'',
|
||||
'Currently this dumps prettified JSON by default. That might change in the',
|
||||
|
@ -21,7 +21,7 @@ function do_wait(subcmd, opts, args, cb) {
|
||||
if (opts.help) {
|
||||
return this.do_help('help', {}, [subcmd], cb);
|
||||
} else if (args.length < 1) {
|
||||
return cb(new errors.UsageError('missing INSTANCE arg(s)'));
|
||||
return cb(new errors.UsageError('missing INST arg(s)'));
|
||||
}
|
||||
var ids = args;
|
||||
var states = [];
|
||||
@ -110,16 +110,19 @@ function do_wait(subcmd, opts, args, cb) {
|
||||
});
|
||||
}
|
||||
|
||||
do_wait.synopses = ['{{name}} {{cmd}} [-s STATES] INST [INST ...]'];
|
||||
do_wait.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Wait on instances changing state.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} wait [-s STATES] INSTANCE [INSTANCE ...]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where "states" is a comma-separated list of target instance states,',
|
||||
'by default "running,failed". In other words, "triton inst wait foo0" will',
|
||||
'wait for instance "foo0" to complete provisioning.'
|
||||
'Where "INST" is an instance name, id, or short id; and "STATES" is a',
|
||||
'comma-separated list of target instance states, by default "running,failed".',
|
||||
'In other words, "triton inst wait foo0" will wait for instance "foo0" to',
|
||||
'complete provisioning.'
|
||||
/* END JSSTYLED */
|
||||
].join('\n');
|
||||
do_wait.options = [
|
||||
{
|
||||
|
@ -5,7 +5,7 @@
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 2015 Joyent, Inc.
|
||||
* Copyright 2016 Joyent, Inc.
|
||||
*
|
||||
* Shared support for:
|
||||
* `triton instance start ...`
|
||||
@ -18,9 +18,7 @@ var assert = require('assert-plus');
|
||||
var vasync = require('vasync');
|
||||
|
||||
var common = require('../common');
|
||||
|
||||
|
||||
var f = require('util').format;
|
||||
var errors = require('../errors');
|
||||
|
||||
|
||||
function perror(err) {
|
||||
@ -40,18 +38,20 @@ function gen_do_ACTION(opts) {
|
||||
function do_ACTION(subcmd, _opts, args, callback) {
|
||||
return _doTheAction.call(this, action, subcmd, _opts, args, callback);
|
||||
}
|
||||
do_ACTION.name = 'do_' + action;
|
||||
|
||||
if (opts.aliases) {
|
||||
do_ACTION.aliases = opts.aliases;
|
||||
}
|
||||
|
||||
do_ACTION.synopses = ['{{name}} ' + action + ' [OPTIONS] INST [INST ...]'];
|
||||
do_ACTION.help = [
|
||||
f('%s one or more instances.', common.capitalize(action)),
|
||||
f(''),
|
||||
f('Usage:'),
|
||||
f(' {{name}} %s <alias|id> ...', action),
|
||||
f(''),
|
||||
f('{{options}}')
|
||||
common.capitalize(action) + ' one or more instances.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where "INST" is an instance name, id, or short id.'
|
||||
].join('\n');
|
||||
do_ACTION.options = [
|
||||
{
|
||||
@ -72,7 +72,8 @@ function gen_do_ACTION(opts) {
|
||||
do_ACTION.options.push({
|
||||
names: ['snapshot'],
|
||||
type: 'string',
|
||||
help: 'Name of snapshot to start machine with.'
|
||||
help: 'Name of snapshot with which to start the instance.',
|
||||
helpArg: 'SNAPNAME'
|
||||
});
|
||||
}
|
||||
|
||||
@ -112,7 +113,7 @@ function _doTheAction(action, subcmd, opts, args, callback) {
|
||||
this.do_help('help', {}, [subcmd], callback);
|
||||
return;
|
||||
} else if (args.length < 1) {
|
||||
callback(new Error('invalid args: ' + args));
|
||||
callback(new errors.UsageError('missing INST arg(s)'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -125,11 +125,13 @@ do_add.options = [
|
||||
help: 'An optional name for an added key.'
|
||||
}
|
||||
];
|
||||
|
||||
do_add.synopses = ['{{name}} {{cmd}} [OPTIONS] FILE'];
|
||||
|
||||
do_add.help = [
|
||||
'Add an SSH key to an account.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} add [<options>] FILE',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where "FILE" must be a file path to an SSH public key, ',
|
||||
|
@ -104,11 +104,13 @@ do_delete.options = [
|
||||
help: 'Answer yes to confirmation to delete.'
|
||||
}
|
||||
];
|
||||
|
||||
do_delete.synopses = ['{{name}} {{cmd}} [OPTIONS] KEY [KEY ...]'];
|
||||
|
||||
do_delete.help = [
|
||||
'Remove an SSH key from an account.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} delete [<options>] KEY [KEY...]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where "KEY" is an SSH key "name" or "fingerprint".'
|
||||
|
@ -67,11 +67,13 @@ do_get.options = [
|
||||
help: 'JSON stream output.'
|
||||
}
|
||||
];
|
||||
|
||||
do_get.synopses = ['{{name}} {{cmd}} KEY'];
|
||||
|
||||
do_get.help = [
|
||||
'Show a specific SSH key in an account.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} get KEY',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where "KEY" is an SSH key "name" or "fingerprint".'
|
||||
|
@ -90,11 +90,11 @@ do_list.options = [
|
||||
}
|
||||
]);
|
||||
|
||||
do_list.synopses = ['{{name}} {{cmd}} [OPTIONS]'];
|
||||
do_list.help = [
|
||||
'Show all of an account\'s SSH keys.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} list [<options>]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
].join('\n');
|
||||
|
@ -51,14 +51,17 @@ do_get.options = [
|
||||
help: 'JSON output.'
|
||||
}
|
||||
];
|
||||
do_get.help = (
|
||||
'Show a network.\n'
|
||||
+ '\n'
|
||||
+ 'Usage:\n'
|
||||
+ ' {{name}} get <id|name>\n'
|
||||
+ '\n'
|
||||
+ '{{options}}'
|
||||
);
|
||||
|
||||
do_get.synopses = ['{{name}} {{cmd}} NETWORK'];
|
||||
|
||||
do_get.help = [
|
||||
'Show a network.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where NETWORK is a network id (full UUID), name, or short id.'
|
||||
].join('\n');
|
||||
|
||||
do_get.completionArgtypes = ['tritonnetwork', 'none'];
|
||||
|
||||
|
@ -85,17 +85,17 @@ do_list.options = [
|
||||
sortDefault: sortDefault
|
||||
}));
|
||||
|
||||
do_list.synopses = ['{{name}} {{cmd}}'];
|
||||
|
||||
do_list.help = [
|
||||
'List available networks.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} list',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Fields (most are self explanatory, the client adds some for convenience):',
|
||||
' vlan A shorter alias for "vlan_id".',
|
||||
' shortid A short ID prefix.',
|
||||
'',
|
||||
'{{options}}'
|
||||
' shortid A short ID prefix.'
|
||||
].join('\n');
|
||||
|
||||
do_list.aliases = ['ls'];
|
||||
|
@ -50,21 +50,23 @@ do_get.options = [
|
||||
help: 'JSON stream output.'
|
||||
}
|
||||
];
|
||||
do_get.help = (
|
||||
|
||||
do_get.synopses = ['{{name}} {{cmd}} [OPTIONS] PACKAGE'];
|
||||
|
||||
do_get.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Get a package.\n' +
|
||||
'\n' +
|
||||
'Usage:\n' +
|
||||
' {{name}} get [<options>] ID|NAME\n' +
|
||||
'\n' +
|
||||
'{{options}}' +
|
||||
'\n' +
|
||||
'The given "NAME" must be a unique match.\n' +
|
||||
'\n' +
|
||||
'Note: Currently this dumps prettified JSON by default. That might change\n' +
|
||||
'in the future. Use "-j" to explicitly get JSON output.\n'
|
||||
'Get a package.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'',
|
||||
'Where PACKAGE is a package id (full UUID), exact name, or short id.',
|
||||
'',
|
||||
'Note: Currently this dumps prettified JSON by default. That might change',
|
||||
'in the future. Use "-j" to explicitly get JSON output.'
|
||||
/* END JSSTYLED */
|
||||
);
|
||||
].join('\n');
|
||||
|
||||
do_get.completionArgtypes = ['tritonpackage', 'none'];
|
||||
|
||||
|
@ -28,10 +28,10 @@ var validFilters = [
|
||||
];
|
||||
|
||||
// columns default without -o
|
||||
var columnsDefault = 'shortid,name,default,memory,swap,disk,vcpus';
|
||||
var columnsDefault = 'shortid,name,memory,swap,disk,vcpus';
|
||||
|
||||
// columns default with -l
|
||||
var columnsDefaultLong = 'id,name,default,memory,swap,disk,vcpus';
|
||||
var columnsDefaultLong = 'id,name,memory,swap,disk,vcpus,description';
|
||||
|
||||
// sort default with -s
|
||||
var sortDefault = '_groupPlus,memory';
|
||||
@ -154,12 +154,12 @@ do_list.options = [
|
||||
}
|
||||
]);
|
||||
|
||||
do_list.synopses = ['{{name}} {{cmd}} [FILTERS]'];
|
||||
do_list.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'List packages.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} list [<filters>]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Filters:',
|
||||
@ -177,7 +177,7 @@ do_list.help = [
|
||||
' zero is shown as "-" in tabular output.',
|
||||
'',
|
||||
'Examples:',
|
||||
' {{name}} packages memory=8192 # list packages with 8G RAM'
|
||||
' {{name}} list memory=8192 # list packages with 8G RAM'
|
||||
/* END JSSTYLED */
|
||||
].join('\n');
|
||||
|
||||
|
@ -23,7 +23,11 @@ function PackageCLI(top) {
|
||||
name: top.name + ' package',
|
||||
/* BEGIN JSSTYLED */
|
||||
desc: [
|
||||
'List and get Triton packages.'
|
||||
'List and get Triton packages.',
|
||||
'',
|
||||
'A package is a collection of attributes -- for example disk quota,',
|
||||
'amount of RAM -- used when creating an instance. They have a name',
|
||||
'and ID for identification.'
|
||||
].join('\n'),
|
||||
/* END JSSTYLED */
|
||||
helpOpts: {
|
||||
|
@ -366,11 +366,11 @@ do_create.options = [
|
||||
];
|
||||
|
||||
|
||||
do_create.synopses = ['{{name}} {{cmd}} [OPTIONS]'];
|
||||
do_create.help = [
|
||||
'Create a Triton CLI profile.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} create <options>',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'',
|
||||
|
@ -120,11 +120,11 @@ do_delete.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_delete.synopses = ['{{name}} {{cmd}} PROFILE'];
|
||||
do_delete.help = [
|
||||
'Delete a Triton CLI profile.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} delete NAME',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
].join('\n');
|
||||
|
@ -33,12 +33,12 @@ do_docker_setup.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_docker_setup.synopses = ['{{name}} {{cmd}} [PROFILE]'];
|
||||
do_docker_setup.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Setup for using Docker with the current Triton CLI profile.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} docker-setup [PROFILE]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'A Triton datacenter can act as a virtual Docker Engine, where the entire',
|
||||
@ -54,5 +54,6 @@ do_docker_setup.help = [
|
||||
/* END JSSTYLED */
|
||||
].join('\n');
|
||||
|
||||
do_docker_setup.completionArgtypes = ['tritonprofile', 'none'];
|
||||
|
||||
module.exports = do_docker_setup;
|
||||
|
@ -154,11 +154,11 @@ do_edit.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_edit.synopses = ['{{name}} {{cmd}} [PROFILE]'];
|
||||
do_edit.help = [
|
||||
'Edit a Triton CLI profile in your $EDITOR.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} edit [NAME]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
].join('\n');
|
||||
|
@ -74,15 +74,16 @@ do_get.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_get.synopses = ['{{name}} {{cmd}} [PROFILE]'];
|
||||
do_get.help = [
|
||||
'Get a Triton CLI profile.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} get [NAME]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'If NAME is not specified, the current profile is shown.'
|
||||
].join('\n');
|
||||
|
||||
do_get.completionArgtypes = ['tritonprofile', 'none'];
|
||||
|
||||
module.exports = do_get;
|
||||
|
@ -112,22 +112,21 @@ do_list.options = [
|
||||
includeLong: true,
|
||||
sortDefault: sortDefault
|
||||
}));
|
||||
do_list.synopses = ['{{name}} {{cmd}} [OPTIONS]'];
|
||||
do_list.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'List Triton CLI profiles.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'A profile is a configured Triton CloudAPI endpoint and associated info.',
|
||||
'I.e. the URL, account name, SSH key fingerprint, etc. information required',
|
||||
'to call a CloudAPI endpoint in a Triton datacenter. You can then switch',
|
||||
'between profiles with `triton -p PROFILE`, the TRITON_PROFILE environment',
|
||||
'variable, or by setting your current profile.',
|
||||
'',
|
||||
'The "CURR" column indicates which profile is the current one.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} list',
|
||||
'',
|
||||
'{{options}}'
|
||||
'The "CURR" column indicates which profile is the current one.'
|
||||
/* END JSSTYLED */
|
||||
].join('\n');
|
||||
|
||||
|
@ -13,8 +13,12 @@ function do_set_current(subcmd, opts, args, cb) {
|
||||
if (opts.help) {
|
||||
this.do_help('help', {}, [subcmd], cb);
|
||||
return;
|
||||
} else if (args.length !== 1) {
|
||||
return cb(new errors.UsageError('NAME argument is required'));
|
||||
} else if (args.length === 0) {
|
||||
cb(new errors.UsageError('missing NAME argument'));
|
||||
return;
|
||||
} else if (args.length > 1) {
|
||||
cb(new errors.UsageError('too many arguments: ' + args.join(' ')));
|
||||
return;
|
||||
}
|
||||
|
||||
profilecommon.setCurrentProfile({cli: this.top, name: args[0]}, cb);
|
||||
@ -28,11 +32,11 @@ do_set_current.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_set_current.synopses = ['{{name}} {{cmd}} PROFILE'];
|
||||
do_set_current.help = [
|
||||
'Set the current Triton CLI profile.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} set-current NAME',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'NAME is the name of an existing profile, or "-" to switch to the',
|
||||
|
@ -416,6 +416,8 @@ function profileDockerSetup(opts, cb) {
|
||||
* `docker-compose` versions). It is debatable if we want to
|
||||
* play this game. E.g. someone moving from Docker 1.8 to newer,
|
||||
* *but not re-setting up envvars* may start hitting timeouts.
|
||||
*
|
||||
* TODO: consider using `docker-compose` version on PATH?
|
||||
*/
|
||||
if (!arg.dockerVersion) {
|
||||
setup.env.DOCKER_CLIENT_TIMEOUT = '300';
|
||||
|
@ -203,12 +203,13 @@ do_apply.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_apply.synopses = ['{{name}} {{cmd}} [OPTIONS]'];
|
||||
|
||||
do_apply.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Apply an RBAC configuration.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} apply [<options>]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'If "--file FILE" is not specified, this defaults to using "./rbac.json".',
|
||||
|
@ -211,12 +211,13 @@ do_info.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_info.synopses = ['{{name}} {{cmd}} [OPTIONS]'];
|
||||
|
||||
do_info.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Show current RBAC state.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} info [<options>]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'List RBAC users, roles and policies and. This summary does not show all',
|
||||
|
@ -303,20 +303,23 @@ do_key.options = [
|
||||
help: 'Delete the named key.'
|
||||
}
|
||||
];
|
||||
|
||||
do_key.synopses = [
|
||||
'{{name}} {{cmd}} USER KEY # show USER\'s KEY',
|
||||
'{{name}} {{cmd}} -d|--delete USER [KEY...] # delete USER\'s KEY',
|
||||
'{{name}} {{cmd}} -a|--add [-n NAME] USER FILE # add an SSH key'
|
||||
];
|
||||
|
||||
do_key.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Show, upload, and delete RBAC user SSH keys.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} key USER KEY # show USER\'s KEY',
|
||||
' {{name}} key -d|--delete USER [KEY...] # delete USER\'s KEY',
|
||||
' {{name}} key -a|--add [-n NAME] USER FILE',
|
||||
' # Add a new role. FILE must be a file path to an SSH public',
|
||||
' # key or "-" to pass the public key in on stdin.',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where "USER" is a full RBAC user "id", "login" name or a "shortid"; and',
|
||||
'KEY is an SSH key "name" or "fingerprint".'
|
||||
'KEY is an SSH key "name" or "fingerprint". FILE must be a file path to',
|
||||
'an SSH public key or "-" to pass the public key in on stdin.'
|
||||
/* END JSSTYLED */
|
||||
].join('\n');
|
||||
|
||||
|
@ -84,19 +84,18 @@ do_keys.options = [
|
||||
}
|
||||
]);
|
||||
|
||||
do_keys.help = (
|
||||
/* BEGIN JSSTYLED */
|
||||
'List RBAC user SSH keys.\n' +
|
||||
'\n' +
|
||||
'Usage:\n' +
|
||||
' {{name}} keys [<options>] USER\n' +
|
||||
'\n' +
|
||||
'{{options}}' +
|
||||
'\n' +
|
||||
'Where "USER" is an RBAC user login or id (a UUID).\n'
|
||||
/* END JSSTYLED */
|
||||
);
|
||||
do_keys.synopses = ['{{name}} {{cmd}} [OPTIONS] USER'];
|
||||
|
||||
do_keys.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'List RBAC user SSH keys.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where "USER" is an RBAC user login or id (a UUID).'
|
||||
/* END JSSTYLED */
|
||||
].join('\n');
|
||||
|
||||
|
||||
module.exports = do_keys;
|
||||
|
@ -82,20 +82,17 @@ do_policies.options = [
|
||||
sortDefault: sortDefault
|
||||
}));
|
||||
|
||||
do_policies.help = (
|
||||
/* BEGIN JSSTYLED */
|
||||
'List RBAC policies.\n' +
|
||||
'\n' +
|
||||
'Usage:\n' +
|
||||
' {{name}} policies [<options>]\n' +
|
||||
'\n' +
|
||||
'{{options}}' +
|
||||
'\n' +
|
||||
'Fields (most are self explanatory, the client adds some for convenience):\n' +
|
||||
' nrules The number of rules in this policy.\n'
|
||||
/* END JSSTYLED */
|
||||
);
|
||||
do_policies.synopses = ['{{name}} {{cmd}} [OPTIONS]'];
|
||||
|
||||
do_policies.help = [
|
||||
'List RBAC policies.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Fields (most are self explanatory, the client adds some for convenience):',
|
||||
' nrules The number of rules in this policy.'
|
||||
].join('\n');
|
||||
|
||||
|
||||
module.exports = do_policies;
|
||||
|
@ -512,16 +512,24 @@ do_policy.options = [
|
||||
help: 'Delete the named policy.'
|
||||
}
|
||||
];
|
||||
|
||||
do_policy.synopses = [
|
||||
'{{name}} {{cmd}} POLICY # show policy POLICY',
|
||||
'{{name}} {{cmd}} -e|--edit POLICY # edit policy POLICY in $EDITOR',
|
||||
'{{name}} {{cmd}} -d|--delete [POLICY...] # delete policy POLICY',
|
||||
'{{name}} {{cmd}} -a|--add [FILE] # add a new policy'
|
||||
];
|
||||
|
||||
do_policy.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Show, add, edit and delete RBAC policies.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} policy POLICY # show policy POLICY',
|
||||
' {{name}} policy -e|--edit POLICY # edit policy POLICY in $EDITOR',
|
||||
' {{name}} policy -d|--delete [POLICY...] # delete policy POLICY',
|
||||
' {{name}} {{cmd}} POLICY # show policy POLICY',
|
||||
' {{name}} {{cmd}} -e|--edit POLICY # edit policy POLICY in $EDITOR',
|
||||
' {{name}} {{cmd}} -d|--delete [POLICY...] # delete policy POLICY',
|
||||
'',
|
||||
' {{name}} policy -a|--add [FILE]',
|
||||
' {{name}} {{cmd}} -a|--add [FILE]',
|
||||
' # Add a new policy. FILE must be a file path to a JSON file',
|
||||
' # with the policy data or "-" to pass the policy in on stdin.',
|
||||
' # Or exclude FILE to interactively add.',
|
||||
|
@ -104,13 +104,16 @@ do_reset.options = [
|
||||
}
|
||||
];
|
||||
|
||||
do_reset.synopses = [
|
||||
'{{name}} {{cmd}} [OPTIONS]'
|
||||
];
|
||||
|
||||
do_reset.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Reset RBAC state for this account.',
|
||||
'**Warning: This will delete all RBAC info for this account.**',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} reset [<options>]',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Warning: Currently, RBAC state updates can take a few seconds to appear',
|
||||
|
@ -490,16 +490,24 @@ do_role.options = [
|
||||
help: 'Delete the named role.'
|
||||
}
|
||||
];
|
||||
|
||||
do_role.synopses = [
|
||||
'{{name}} {{cmd}} ROLE # show role ROLE',
|
||||
'{{name}} {{cmd}} -e|--edit ROLE # edit role ROLE in $EDITOR',
|
||||
'{{name}} {{cmd}} -d|--delete [ROLE...] # delete role ROLE',
|
||||
'{{name}} {{cmd}} -a|--add [FILE] # add a new role'
|
||||
];
|
||||
|
||||
do_role.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Show, add, edit and delete RBAC roles.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} role ROLE # show role ROLE',
|
||||
' {{name}} role -e|--edit ROLE # edit role ROLE in $EDITOR',
|
||||
' {{name}} role -d|--delete [ROLE...] # delete role ROLE',
|
||||
' {{name}} {{cmd}} ROLE # show role ROLE',
|
||||
' {{name}} {{cmd}} -e|--edit ROLE # edit role ROLE in $EDITOR',
|
||||
' {{name}} {{cmd}} -d|--delete [ROLE...] # delete role ROLE',
|
||||
'',
|
||||
' {{name}} role -a|--add [FILE]',
|
||||
' {{name}} {{cmd}} -a|--add [FILE]',
|
||||
' # Add a new role. FILE must be a file path to a JSON file',
|
||||
' # with the role data or "-" to pass the role in on stdin.',
|
||||
' # Or exclude FILE to interactively add.',
|
||||
|
@ -508,7 +508,8 @@ function makeRoleTagsFunc(cfg) {
|
||||
}
|
||||
};
|
||||
|
||||
func.name = cfg.funcName;
|
||||
func.name = cfg.funcName; // XXX
|
||||
func.subcmd = cfg.funcName;
|
||||
|
||||
func.options = [
|
||||
{
|
||||
@ -564,24 +565,31 @@ function makeRoleTagsFunc(cfg) {
|
||||
helpCol: 23
|
||||
};
|
||||
|
||||
func.synopses = [
|
||||
'{{name}} {{cmd}} $argName # list role tags',
|
||||
'{{name}} {{cmd}} -a ROLE[,ROLE...] $argName # add',
|
||||
'{{name}} {{cmd}} -s ROLE[,ROLE...] $argName # set/replace',
|
||||
'{{name}} {{cmd}} -e $argName # edit in $EDITOR',
|
||||
'{{name}} {{cmd}} -d ROLE[,ROLE...] $argName # delete',
|
||||
'{{name}} {{cmd}} -D $argName # delete all'
|
||||
];
|
||||
func.synopses = func.synopses.map(function (synopsis) {
|
||||
var key = 'argName';
|
||||
return synopsis.replace(new RegExp('\\$' + key, 'g'), cfg[key]);
|
||||
});
|
||||
|
||||
func.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'List and manage role tags for the given $resourceType.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} $cmdName $argName # list role tags',
|
||||
' {{name}} $cmdName -a ROLE[,ROLE...] $argName # add',
|
||||
' {{name}} $cmdName -s ROLE[,ROLE...] $argName # set/replace',
|
||||
' {{name}} $cmdName -e $argName # edit in $EDITOR',
|
||||
' {{name}} $cmdName -d ROLE[,ROLE...] $argName # delete',
|
||||
' {{name}} $cmdName -D $argName # delete all',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Where "ROLE" is a role tag name (see `triton rbac roles`) and',
|
||||
'$argName is $helpArgIs.'
|
||||
/* END JSSTYLED */
|
||||
].join('\n');
|
||||
['resourceType', 'cmdName', 'argName', 'helpArgIs'].forEach(function (key) {
|
||||
['resourceType', 'cmdName', 'helpArgIs'].forEach(function (key) {
|
||||
func.help = func.help.replace(new RegExp('\\$' + key, 'g'), cfg[key]);
|
||||
});
|
||||
|
||||
|
@ -97,20 +97,20 @@ do_roles.options = [
|
||||
sortDefault: sortDefault
|
||||
}));
|
||||
|
||||
do_roles.help = (
|
||||
do_roles.synopses = ['{{name}} {{cmd}} [OPTIONS]'];
|
||||
|
||||
do_roles.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'List RBAC roles.\n' +
|
||||
'\n' +
|
||||
'Usage:\n' +
|
||||
' {{name}} roles [<options>]\n' +
|
||||
'\n' +
|
||||
'{{options}}' +
|
||||
'\n' +
|
||||
'Fields (most are self explanatory, the client adds some for convenience):\n' +
|
||||
' members Non-default members (not in the "default_members")\n' +
|
||||
'List RBAC roles.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Fields (most are self explanatory, the client adds some for convenience):',
|
||||
' members Non-default members (not in the "default_members")',
|
||||
' are shown in magenta.\n'
|
||||
/* END JSSTYLED */
|
||||
);
|
||||
].join('\n');
|
||||
|
||||
|
||||
|
||||
|
@ -497,16 +497,24 @@ do_user.options = [
|
||||
help: 'Delete the named user.'
|
||||
}
|
||||
];
|
||||
|
||||
do_user.synopses = [
|
||||
'{{name}} {{cmd}} [OPTIONS] USER # show user USER',
|
||||
'{{name}} {{cmd}} -e|--edit USER # edit user USER in $EDITOR',
|
||||
'{{name}} {{cmd}} -d|--delete [USER...] # delete user USER',
|
||||
'{{name}} {{cmd}} -a|--add [FILE] # add a user'
|
||||
];
|
||||
|
||||
do_user.help = [
|
||||
/* BEGIN JSSTYLED */
|
||||
'Show, add, edit and delete RBAC users.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} user [<options>] USER # show user USER',
|
||||
' {{name}} user -e|--edit USER # edit user USER in $EDITOR',
|
||||
' {{name}} user -d|--delete [USER...] # delete user USER',
|
||||
' {{name}} {{cmd}} [OPTIONS] USER # show user USER',
|
||||
' {{name}} {{cmd}} -e|--edit USER # edit user USER in $EDITOR',
|
||||
' {{name}} {{cmd}} -d|--delete [USER...] # delete user USER',
|
||||
'',
|
||||
' {{name}} user -a|--add [FILE]',
|
||||
' {{name}} {{cmd}} -a|--add [FILE]',
|
||||
' # Add a new user. FILE must be a file path to a JSON file',
|
||||
' # with the user data or "-" to pass the user in on stdin.',
|
||||
' # Or exclude FILE to interactively add.',
|
||||
|
@ -84,22 +84,19 @@ do_users.options = [
|
||||
sortDefault: sortDefault
|
||||
}));
|
||||
|
||||
do_users.help = (
|
||||
/* BEGIN JSSTYLED */
|
||||
'List RBAC users.\n' +
|
||||
'\n' +
|
||||
'Usage:\n' +
|
||||
' {{name}} users [<options>]\n' +
|
||||
'\n' +
|
||||
'Fields (most are self explanatory, the client adds some for convenience):\n' +
|
||||
' name "firstName lastName"\n' +
|
||||
' cdate Just the date portion of "created"\n' +
|
||||
' udate Just the date portion of "updated"\n' +
|
||||
'\n' +
|
||||
'{{options}}'
|
||||
/* END JSSTYLED */
|
||||
);
|
||||
do_users.synopses = ['{{name}} {{cmd}} [OPTIONS]'];
|
||||
|
||||
do_users.help = [
|
||||
'List RBAC users.',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}',
|
||||
'Fields (most are self explanatory, the client adds some for convenience):',
|
||||
' name "firstName lastName"',
|
||||
' cdate Just the date portion of "created"',
|
||||
' udate Just the date portion of "updated"'
|
||||
].join('\n');
|
||||
|
||||
|
||||
module.exports = do_users;
|
||||
|
@ -77,13 +77,14 @@ do_services.options = [
|
||||
sortDefault: sortDefault
|
||||
}));
|
||||
|
||||
do_services.help = (
|
||||
'Show services information\n'
|
||||
+ '\n'
|
||||
+ 'Usage:\n'
|
||||
+ ' {{name}} services\n'
|
||||
+ '\n'
|
||||
+ '{{options}}'
|
||||
);
|
||||
do_services.synopses = ['{{name}} {{cmd}}'];
|
||||
|
||||
do_services.help = [
|
||||
'Show services information',
|
||||
'',
|
||||
'{{usage}}',
|
||||
'',
|
||||
'{{options}}'
|
||||
].join('\n');
|
||||
|
||||
module.exports = do_services;
|
||||
|
@ -10,6 +10,7 @@
|
||||
* Error classes that the joyent CLI may produce.
|
||||
*/
|
||||
|
||||
var cmdln = require('cmdln');
|
||||
var util = require('util'),
|
||||
format = util.format;
|
||||
var assert = require('assert-plus');
|
||||
@ -145,25 +146,6 @@ function ConfigError(cause, message) {
|
||||
util.inherits(ConfigError, _TritonBaseVError);
|
||||
|
||||
|
||||
/**
|
||||
* CLI usage error
|
||||
*/
|
||||
function UsageError(cause, message) {
|
||||
if (message === undefined) {
|
||||
message = cause;
|
||||
cause = undefined;
|
||||
}
|
||||
assert.string(message);
|
||||
_TritonBaseVError.call(this, {
|
||||
cause: cause,
|
||||
message: message,
|
||||
code: 'Usage',
|
||||
exitStatus: 2
|
||||
});
|
||||
}
|
||||
util.inherits(UsageError, _TritonBaseVError);
|
||||
|
||||
|
||||
/**
|
||||
* Error in setting up (typically in profile update/creation).
|
||||
*/
|
||||
@ -299,7 +281,7 @@ module.exports = {
|
||||
TritonError: TritonError,
|
||||
InternalError: InternalError,
|
||||
ConfigError: ConfigError,
|
||||
UsageError: UsageError,
|
||||
UsageError: cmdln.UsageError,
|
||||
SetupError: SetupError,
|
||||
SigningError: SigningError,
|
||||
SelfSignedCertError: SelfSignedCertError,
|
||||
|
@ -28,7 +28,6 @@ var vasync = require('vasync');
|
||||
var cloudapi = require('./cloudapi2');
|
||||
var common = require('./common');
|
||||
var errors = require('./errors');
|
||||
var loadConfigSync = require('./config').loadConfigSync;
|
||||
|
||||
|
||||
// ---- globals
|
||||
|
@ -1,14 +1,14 @@
|
||||
{
|
||||
"name": "triton",
|
||||
"description": "Joyent Triton CLI and client (https://www.joyent.com/triton)",
|
||||
"version": "4.12.1",
|
||||
"version": "4.13.0",
|
||||
"author": "Joyent (joyent.com)",
|
||||
"dependencies": {
|
||||
"assert-plus": "0.2.0",
|
||||
"backoff": "2.4.1",
|
||||
"bigspinner": "3.1.0",
|
||||
"bunyan": "1.5.1",
|
||||
"cmdln": "3.5.4",
|
||||
"cmdln": "4.1.1",
|
||||
"extsprintf": "1.0.2",
|
||||
"lomstream": "1.1.0",
|
||||
"mkdirp": "0.5.1",
|
||||
|
Reference in New Issue
Block a user