joyent/node-triton#4 triton networks/network to support shortId as well and to include fabric
flag
This commit is contained in:
parent
ae8a19d568
commit
58a7c9977b
@ -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' +
|
||||||
|
@ -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 = [
|
||||||
|
@ -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;
|
||||||
|
@ -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)));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
146
test/integration/cli-networks.test.js
Normal file
146
test/integration/cli-networks.test.js
Normal 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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
Reference in New Issue
Block a user