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