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

View File

@ -4,60 +4,33 @@
* `triton network ...`
*/
var format = require('util').format;
var common = require('./common');
var errors = require('./errors');
function do_network(subcmd, opts, args, cb) {
if (opts.help) {
this.do_help('help', {}, [subcmd], cb);
return;
} else if (args.length !== 1) {
cb(new Error('invalid args: ' + args));
return;
return cb(new errors.UsageError(format(
'incorrect number of args (%d): %s', args.length, args.join(' '))));
}
var id = args[0];
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) {
this.triton.getNetwork(args[0], function (err, net) {
if (err) {
cb(err);
return;
return cb(err);
}
if (opts.json) {
console.log(JSON.stringify(network));
console.log(JSON.stringify(net));
} else {
console.log(JSON.stringify(network, null, 4));
console.log(JSON.stringify(net, null, 4));
}
cb();
}
});
}
do_network.options = [

View File

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

View File

@ -231,10 +231,10 @@ Triton.prototype.getImage = function getImage(name, cb) {
cb(null, shortIdMatches[0]);
} else if (shortIdMatches.length === 0) {
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 {
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) {
cb(err);
} 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 {
cb(null, pkg);
}
@ -288,10 +288,65 @@ Triton.prototype.getPackage = function getPackage(name, cb) {
cb(null, shortIdMatches[0]);
} else if (shortIdMatches.length === 0) {
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 {
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);
} else {
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();
});
});
});