joyent/node-triton#4 triton networks/network to support shortId as well and to include fabric

flag
This commit is contained in:
Trent Mick 2015-09-02 00:03:17 -07:00
parent ae8a19d568
commit 58a7c9977b
5 changed files with 250 additions and 82 deletions

View File

@ -130,6 +130,7 @@ do_images.options = [
help: 'JSON stream output.' help: 'JSON stream output.'
} }
]; ];
do_images.help = ( do_images.help = (
/* BEGIN JSSTYLED */ /* BEGIN JSSTYLED */
'List images.\n' + 'List images.\n' +
@ -144,6 +145,7 @@ do_images.help = (
' FIELD=~SUBSTRING Field substring filter. Supported fields: name\n' + ' FIELD=~SUBSTRING Field substring filter. Supported fields: name\n' +
'\n' + '\n' +
'Fields (most are self explanatory, the client adds some for convenience):\n' + 'Fields (most are self explanatory, the client adds some for convenience):\n' +
' shortid A short ID prefix.\n' +
' flags This is a set of single letter flags\n' + ' flags This is a set of single letter flags\n' +
' summarizing some fields. "P" indicates the\n' + ' summarizing some fields. "P" indicates the\n' +
' image is public. "I" indicates an incremental\n' + ' image is public. "I" indicates an incremental\n' +

View File

@ -4,60 +4,33 @@
* `triton network ...` * `triton network ...`
*/ */
var format = require('util').format;
var common = require('./common'); var common = require('./common');
var errors = require('./errors');
function do_network(subcmd, opts, args, cb) { function do_network(subcmd, opts, args, cb) {
if (opts.help) { if (opts.help) {
this.do_help('help', {}, [subcmd], cb); this.do_help('help', {}, [subcmd], cb);
return; return;
} else if (args.length !== 1) { } else if (args.length !== 1) {
cb(new Error('invalid args: ' + args)); return cb(new errors.UsageError(format(
return; 'incorrect number of args (%d): %s', args.length, args.join(' '))));
} }
var id = args[0]; this.triton.getNetwork(args[0], function (err, net) {
if (common.isUUID(id)) {
this.triton.cloudapi.getNetwork(id, done);
} else {
// we have to list all networks and find the one pertaining
// to the alias given
this.triton.cloudapi.listNetworks(function (err, networks) {
if (err) {
done(err);
return;
}
var net;
// try to find the network
networks.forEach(function (network) {
if (network.name === id)
net = network;
});
if (net) {
// found!
done(null, net);
} else {
// not found
done(new Error('network ' + id + ' not found'));
}
});
}
function done(err, network) {
if (err) { if (err) {
cb(err); return cb(err);
return;
} }
if (opts.json) { if (opts.json) {
console.log(JSON.stringify(network)); console.log(JSON.stringify(net));
} else { } else {
console.log(JSON.stringify(network, null, 4)); console.log(JSON.stringify(net, null, 4));
} }
cb(); cb();
} });
} }
do_network.options = [ do_network.options = [

View File

@ -16,21 +16,6 @@ var validFilters = [
'description' 'description'
]; ];
// valid output fields to be printed
var validFields = [
'id',
'name',
'public',
'fabric',
'gateway',
'internet_nat',
'provision_end_ip',
'provision_start_ip',
'resolvers',
'subnet',
'vlan_id'
];
function do_networks(subcmd, opts, args, callback) { function do_networks(subcmd, opts, args, callback) {
if (opts.help) { if (opts.help) {
this.do_help('help', {}, [subcmd], callback); this.do_help('help', {}, [subcmd], callback);
@ -40,18 +25,14 @@ function do_networks(subcmd, opts, args, callback) {
return; return;
} }
var columns = opts.o.trim().split(','); var columns = 'shortid,name,subnet,gateway,fabric,vlan,public'.split(',');
var sort = opts.s.trim().split(','); if (opts.o) {
/* JSSTYLED */
/* not supported columns = opts.o.trim().split(/\s*,\s*/g);
var listOpts; } else if (opts.long) {
try { columns[0] = 'id';
listOpts = common.kvToObj(args, validFilters);
} catch (e) {
callback(e);
return;
} }
*/ var sort = opts.s.trim().split(',');
this.triton.cloudapi.listNetworks(function (err, networks) { this.triton.cloudapi.listNetworks(function (err, networks) {
if (err) { if (err) {
@ -62,12 +43,15 @@ function do_networks(subcmd, opts, args, callback) {
if (opts.json) { if (opts.json) {
common.jsonStream(networks); common.jsonStream(networks);
} else { } else {
// pretty print for (var i = 0; i < networks.length; i++) {
var net = networks[i];
net.shortid = net.id.split('-', 1)[0];
net.vlan = net.vlan_id;
}
tabula(networks, { tabula(networks, {
skipHeader: opts.H, skipHeader: opts.H,
columns: columns, columns: columns,
sort: sort, sort: sort
validFields: validFields
}); });
} }
callback(); callback();
@ -88,10 +72,14 @@ do_networks.options = [
{ {
names: ['o'], names: ['o'],
type: 'string', type: 'string',
default: 'id,name,subnet,public,vlan_id,gateway',
help: 'Specify fields (columns) to output.', help: 'Specify fields (columns) to output.',
helpArg: 'field1,...' helpArg: 'field1,...'
}, },
{
names: ['long', 'l'],
type: 'bool',
help: 'Long/wider output. Ignored if "-o ..." is used.'
},
{ {
names: ['s'], names: ['s'],
type: 'string', type: 'string',
@ -105,13 +93,17 @@ do_networks.options = [
help: 'JSON output.' help: 'JSON output.'
} }
]; ];
do_networks.help = ( do_networks.help = [
'List available networks.\n' 'List available networks.',
+ '\n' '',
+ 'Usage:\n' 'Usage:',
+ ' {{name}} networks\n' ' {{name}} networks',
+ '\n' '',
+ '{{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}}'
].join('\n');
module.exports = do_networks; module.exports = do_networks;

View File

@ -231,10 +231,10 @@ Triton.prototype.getImage = function getImage(name, cb) {
cb(null, shortIdMatches[0]); cb(null, shortIdMatches[0]);
} else if (shortIdMatches.length === 0) { } else if (shortIdMatches.length === 0) {
cb(new Error(format( cb(new Error(format(
'no image with name or shortId "%s" was found', name))); 'no image with name or short id "%s" was found', name)));
} else { } else {
cb(new Error(format('no image with name "%s" was found ' cb(new Error(format('no image with name "%s" was found '
+ 'and "%s" is an ambiguous shortId', name))); + 'and "%s" is an ambiguous short id', name)));
} }
}); });
} }
@ -255,7 +255,7 @@ Triton.prototype.getPackage = function getPackage(name, cb) {
if (err) { if (err) {
cb(err); cb(err);
} else if (!pkg.active) { } else if (!pkg.active) {
cb(new Error(format('image %s is not active', name))); cb(new Error(format('package %s is not active', name)));
} else { } else {
cb(null, pkg); cb(null, pkg);
} }
@ -288,10 +288,65 @@ Triton.prototype.getPackage = function getPackage(name, cb) {
cb(null, shortIdMatches[0]); cb(null, shortIdMatches[0]);
} else if (shortIdMatches.length === 0) { } else if (shortIdMatches.length === 0) {
cb(new Error(format( cb(new Error(format(
'no package with name or shortId "%s" was found', name))); 'no package with name or short id "%s" was found', name)));
} else { } else {
cb(new Error(format('no package with name "%s" was found ' cb(new Error(format('no package with name "%s" was found '
+ 'and "%s" is an ambiguous shortId', name))); + 'and "%s" is an ambiguous short id', name)));
}
});
}
};
/**
* Get an network by ID, exact name, or short ID, in that order.
*
* If the name is ambiguous, then this errors out.
*/
Triton.prototype.getNetwork = function getNetwork(name, cb) {
assert.string(name, 'name');
assert.func(cb, 'cb');
if (common.isUUID(name)) {
this.cloudapi.getNetwork(name, function (err, net) {
if (err) {
cb(err);
} else {
cb(null, net);
}
});
} else {
this.cloudapi.listNetworks(function (err, nets) {
if (err) {
return cb(err);
}
var nameMatches = [];
var shortIdMatches = [];
for (var i = 0; i < nets.length; i++) {
var net = nets[i];
if (net.name === name) {
nameMatches.push(net);
}
if (net.id.slice(0, 8) === name) {
shortIdMatches.push(net);
}
}
if (nameMatches.length === 1) {
cb(null, nameMatches[0]);
} else if (nameMatches.length > 1) {
cb(new Error(format(
'network name "%s" is ambiguous: matches %d networks',
name, nameMatches.length)));
} else if (shortIdMatches.length === 1) {
cb(null, shortIdMatches[0]);
} else if (shortIdMatches.length === 0) {
cb(new Error(format(
'no network with name or short id "%s" was found', name)));
} else {
cb(new Error(format('no network with name "%s" was found '
+ 'and "%s" is an ambiguous short id', name)));
} }
}); });
} }
@ -392,7 +447,7 @@ Triton.prototype.getInstance = function getInstance(name, cb) {
cb(null, inst); cb(null, inst);
} else { } else {
cb(new Error(format( cb(new Error(format(
'no instance with name or shortId "%s" was found', name))); 'no instance with name or short id "%s" was found', name)));
} }
}); });
}; };

View File

@ -0,0 +1,146 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/*
* Copyright (c) 2015, Joyent, Inc.
*/
/*
* Integration tests for `triton network(s)`
*/
var h = require('./helpers');
var test = require('tape');
var common = require('../../lib/common');
// --- Globals
var networks;
// --- Tests
test('triton networks', function (tt) {
tt.test(' triton networks -h', function (t) {
h.triton('networks -h', function (err, stdout, stderr) {
if (h.ifErr(t, err))
return t.end();
t.ok(/Usage:\s+triton networks/.test(stdout));
t.end();
});
});
tt.test(' triton help networks', function (t) {
h.triton('help networks', function (err, stdout, stderr) {
if (h.ifErr(t, err))
return t.end();
t.ok(/Usage:\s+triton networks/.test(stdout));
t.end();
});
});
tt.test(' triton networks', function (t) {
h.triton('networks', function (err, stdout, stderr) {
if (h.ifErr(t, err))
return t.end();
t.ok(/^SHORTID\b/.test(stdout));
t.ok(/\bFABRIC\b/.test(stdout));
t.end();
});
});
tt.test(' triton networks -l', function (t) {
h.triton('networks -l', function (err, stdout, stderr) {
if (h.ifErr(t, err))
return t.end();
t.ok(/^ID\b/.test(stdout));
t.end();
});
});
tt.test(' triton networks -j', function (t) {
h.triton('networks -j', function (err, stdout, stderr) {
if (h.ifErr(t, err))
return t.end();
networks = [];
stdout.split('\n').forEach(function (line) {
if (!line.trim()) {
return;
}
networks.push(JSON.parse(line));
});
t.ok(networks.length > 0, 'have at least one network');
t.ok(common.isUUID(networks[0].id));
t.end();
});
});
});
test('triton network', function (tt) {
tt.test(' triton network -h', function (t) {
h.triton('network -h', function (err, stdout, stderr) {
if (h.ifErr(t, err))
return t.end();
t.ok(/Usage:\s+triton network\b/.test(stdout));
t.end();
});
});
tt.test(' triton help network', function (t) {
h.triton('help network', function (err, stdout, stderr) {
if (h.ifErr(t, err))
return t.end();
t.ok(/Usage:\s+triton network\b/.test(stdout));
t.end();
});
});
tt.test(' triton network', function (t) {
h.triton('network', function (err, stdout, stderr) {
t.ok(err);
t.ok(/error \(Usage\)/.test(stderr));
t.end();
});
});
tt.test(' triton network ID', function (t) {
h.triton('network ' + networks[0].id, function (err, stdout, stderr) {
if (h.ifErr(t, err))
return t.end();
var network = JSON.parse(stdout);
t.equal(network.id, networks[0].id);
t.end();
});
});
tt.test(' triton network SHORTID', function (t) {
var shortid = networks[0].id.split('-')[0];
h.triton('network ' + shortid, function (err, stdout, stderr) {
if (h.ifErr(t, err))
return t.end();
var network = JSON.parse(stdout);
t.equal(network.id, networks[0].id);
t.end();
});
});
tt.test(' triton network NAME', function (t) {
h.triton('network ' + networks[0].name, function (err, stdout, stderr) {
if (h.ifErr(t, err))
return t.end();
var network = JSON.parse(stdout);
t.equal(network.id, networks[0].id);
t.end();
});
});
});