triton instances
This commit is contained in:
parent
23fc9d4b3f
commit
eaf93e619b
124
lib/cloudapi2.js
124
lib/cloudapi2.js
@ -29,6 +29,7 @@ var p = console.log;
|
|||||||
var assert = require('assert-plus');
|
var assert = require('assert-plus');
|
||||||
var auth = require('smartdc-auth');
|
var auth = require('smartdc-auth');
|
||||||
var format = require('util').format;
|
var format = require('util').format;
|
||||||
|
var LOMStream = require('lomstream').LOMStream;
|
||||||
var os = require('os');
|
var os = require('os');
|
||||||
var querystring = require('querystring');
|
var querystring = require('querystring');
|
||||||
var restifyClients = require('restify-clients');
|
var restifyClients = require('restify-clients');
|
||||||
@ -387,83 +388,60 @@ CloudAPI.prototype.getMachine = function getMachine(options, callback) {
|
|||||||
* List the user's machines.
|
* List the user's machines.
|
||||||
* <http://apidocs.joyent.com/cloudapi/#ListMachines>
|
* <http://apidocs.joyent.com/cloudapi/#ListMachines>
|
||||||
*
|
*
|
||||||
* If no `offset` is given, then this will return all machines, calling
|
* @param {Object} options
|
||||||
* multiple times if necessary. If `offset` is specified given, then just
|
* See document above
|
||||||
* a single response will be made.
|
* @return {LOMStream} a stream for each machine entry
|
||||||
*
|
|
||||||
* @param {Object} options (optional)
|
|
||||||
* - {Number} offset (optional) An offset number of machine at which to
|
|
||||||
* return results.
|
|
||||||
* - {Number} limit (optional) Max number of machines to return.
|
|
||||||
* @param {Function} callback of the form `function (err, machines, responses)`
|
|
||||||
* where `responses` is an array of response objects in retrieving all
|
|
||||||
* the machines. ListMachines has a max number of machines, so can require
|
|
||||||
* multiple requests to list all of them.
|
|
||||||
*/
|
*/
|
||||||
CloudAPI.prototype.listMachines = function listMachines(options, callback) {
|
CloudAPI.prototype.createListMachinesStream =
|
||||||
var self = this;
|
function createListMachinesStream(options) {
|
||||||
if (callback === undefined) {
|
var self = this;
|
||||||
callback = options;
|
|
||||||
options = {};
|
// if the user specifies an offset we don't paginate
|
||||||
|
var once = options.limit !== undefined;
|
||||||
|
|
||||||
|
return new LOMStream({
|
||||||
|
fetch: fetch,
|
||||||
|
limit: 1000,
|
||||||
|
offset: true
|
||||||
|
});
|
||||||
|
|
||||||
|
function fetch(fetcharg, limitObj, datacb, donecb) {
|
||||||
|
options.limit = limitObj.limit;
|
||||||
|
options.offset = limitObj.offset;
|
||||||
|
var endpoint = self._path(format('/%s/machines', self.user), options);
|
||||||
|
|
||||||
|
self._request(endpoint, function (err, req, res, body) {
|
||||||
|
var resourcecount = res.headers['x-resource-count'];
|
||||||
|
var done = once || resourcecount < options.limit;
|
||||||
|
donecb(err, {done: done, results: body});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
assert.object(options, 'options');
|
|
||||||
assert.func(callback, 'callback');
|
|
||||||
|
|
||||||
var query = {
|
|
||||||
limit: options.limit
|
|
||||||
};
|
|
||||||
|
|
||||||
var paging = options.offset === undefined;
|
|
||||||
var offset = options.offset || 0;
|
|
||||||
var lastHeaders;
|
|
||||||
var responses = [];
|
|
||||||
var bodies = [];
|
|
||||||
async.doWhilst(
|
|
||||||
function getPage(next) {
|
|
||||||
self._getAuthHeaders(function (hErr, headers) {
|
|
||||||
if (hErr) {
|
|
||||||
next(hErr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
query.offset = offset;
|
|
||||||
var path = sprintf('/%s/machines?%s', self.user,
|
|
||||||
querystring.stringify(query));
|
|
||||||
var opts = {
|
|
||||||
path: path,
|
|
||||||
headers: headers
|
|
||||||
};
|
|
||||||
self.client.get(opts, function (err, req, res, body) {
|
|
||||||
lastHeaders = res.headers;
|
|
||||||
responses.push(res);
|
|
||||||
bodies.push(body);
|
|
||||||
next(err);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
|
||||||
function testContinue() {
|
|
||||||
if (!paging) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
xQueryLimit = Number(lastHeaders['x-query-limit']);
|
|
||||||
xResourceCount = Number(lastHeaders['x-resource-count']);
|
|
||||||
assert.number(xQueryLimit, 'x-query-limit header');
|
|
||||||
assert.number(xResourceCount, 'x-resource-count header');
|
|
||||||
offset += Number(lastHeaders['x-resource-count']);
|
|
||||||
return xResourceCount >= xQueryLimit;
|
|
||||||
},
|
|
||||||
function doneMachines(err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err, null, responses);
|
|
||||||
} else if (bodies.length === 1) {
|
|
||||||
callback(null, bodies[0], responses);
|
|
||||||
} else {
|
|
||||||
var machines = Array.prototype.concat.apply([], bodies);
|
|
||||||
callback(null, machines, responses);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* List the user's machines.
|
||||||
|
* <http://apidocs.joyent.com/cloudapi/#ListMachines>
|
||||||
|
*
|
||||||
|
* @param {Object} options
|
||||||
|
* See document above
|
||||||
|
* @param {Function} callback - called like `function (err, machines)`
|
||||||
|
*/
|
||||||
|
CloudAPI.prototype.listMachines = function listMachines(options, callback) {
|
||||||
|
var machines = [];
|
||||||
|
var s = this.createListMachinesStream(options);
|
||||||
|
s.on('error', function (e) {
|
||||||
|
callback(e);
|
||||||
|
});
|
||||||
|
s.on('readable', function () {
|
||||||
|
var machine;
|
||||||
|
while ((machine = s.read()) !== null) {
|
||||||
|
machines.push(machine);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
s.on('end', function () {
|
||||||
|
callback(null, machines);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* List machine audit (successful actions on the machine).
|
* List machine audit (successful actions on the machine).
|
||||||
|
@ -10,17 +10,24 @@ function do_cloudapi (subcmd, opts, args, callback) {
|
|||||||
if (opts.help) {
|
if (opts.help) {
|
||||||
this.do_help('help', {}, [subcmd], callback);
|
this.do_help('help', {}, [subcmd], callback);
|
||||||
return;
|
return;
|
||||||
} else if (args.length !== 2) {
|
} else if (args.length < 1 || args.length > 2) {
|
||||||
callback(new Error('invalid arguments'));
|
callback(new Error('invalid arguments'));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var method = args[0];
|
||||||
|
var path = args[1];
|
||||||
|
if (path === undefined) {
|
||||||
|
path = method;
|
||||||
|
method = 'GET';
|
||||||
|
}
|
||||||
|
|
||||||
var reqopts = {
|
var reqopts = {
|
||||||
method: args[0].toLowerCase(),
|
method: method.toLowerCase(),
|
||||||
path: args[1]
|
path: path
|
||||||
};
|
};
|
||||||
|
|
||||||
this.triton.cloudapi.request(reqopts, function (err, req, res, body) {
|
this.triton.cloudapi._request(reqopts, function (err, req, res, body) {
|
||||||
if (err) {
|
if (err) {
|
||||||
callback(err);
|
callback(err);
|
||||||
return;
|
return;
|
||||||
|
@ -1,68 +1,104 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2015 Joyent Inc. All rights reserved.
|
* Copyright 2015 Joyent Inc.
|
||||||
*
|
*
|
||||||
* `triton instances ...`
|
* `triton instances ...`
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var format = require('util').format;
|
|
||||||
var tabula = require('tabula');
|
var tabula = require('tabula');
|
||||||
|
|
||||||
var errors = require('./errors');
|
var common = require('./common');
|
||||||
|
|
||||||
|
// to be passed as query string args to /my/machines
|
||||||
|
var validFilters = [
|
||||||
|
'name',
|
||||||
|
'image',
|
||||||
|
'state',
|
||||||
|
'memory',
|
||||||
|
'tombstone',
|
||||||
|
'credentials'
|
||||||
|
];
|
||||||
|
|
||||||
|
// valid output fields to be printed
|
||||||
|
var validFields = [
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'type',
|
||||||
|
'state',
|
||||||
|
'dataset',
|
||||||
|
'memory',
|
||||||
|
'disk',
|
||||||
|
'ips',
|
||||||
|
'metadata',
|
||||||
|
'created',
|
||||||
|
'updated',
|
||||||
|
'package',
|
||||||
|
'image'
|
||||||
|
];
|
||||||
|
|
||||||
function do_instances(subcmd, opts, args, callback) {
|
function do_instances(subcmd, opts, args, callback) {
|
||||||
var self = this;
|
|
||||||
if (opts.help) {
|
if (opts.help) {
|
||||||
this.do_help('help', {}, [subcmd], callback);
|
this.do_help('help', {}, [subcmd], callback);
|
||||||
return;
|
return;
|
||||||
} else if (args.length > 1) {
|
} else if (args.length > 1) {
|
||||||
return callback(new Error('too many args: ' + args));
|
callback(new Error('too many args: ' + args));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var machines = [];
|
var columns = opts.o.trim().split(',');
|
||||||
var errs = [];
|
var sort = opts.s.trim().split(',');
|
||||||
var res = this.sdc.listMachines();
|
|
||||||
res.on('data', function (dc, dcMachines) {
|
var listOpts;
|
||||||
for (var i = 0; i < dcMachines.length; i++) {
|
try {
|
||||||
dcMachines[i].dc = dc;
|
listOpts = common.kvToObj(args, validFilters);
|
||||||
machines.push(dcMachines[i]);
|
} catch (e) {
|
||||||
|
callback(e);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.triton.cloudapi.listMachines(listOpts, function (err, machines) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
});
|
|
||||||
res.on('dcError', function (dc, dcErr) {
|
|
||||||
dcErr.dc = dc;
|
|
||||||
errs.push(dcErr);
|
|
||||||
});
|
|
||||||
res.on('end', function () {
|
|
||||||
if (opts.json) {
|
if (opts.json) {
|
||||||
p(JSON.stringify(machines, null, 4));
|
console.log(common.jsonStream(machines));
|
||||||
} else {
|
} else {
|
||||||
/* BEGIN JSSTYLED */
|
tabula(machines, {
|
||||||
// TODO: get short output down to something like
|
skipHeader: opts.H,
|
||||||
// 'us-west-1 e91897cf testforyunong2 linux running 2013-11-08'
|
columns: columns,
|
||||||
// 'us-west-1 e91897cf testforyunong2 ubuntu/13.3.0 running 2013-11-08'
|
sort: sort,
|
||||||
/* END JSSTYLED */
|
validFields: validFields
|
||||||
common.tabulate(machines, {
|
|
||||||
columns: 'dc,id,name,image,state,created',
|
|
||||||
sort: 'created',
|
|
||||||
validFields: 'dc,id,name,type,state,image,package,memory,'
|
|
||||||
+ 'disk,created,updated,compute_node,primaryIp'
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
var err;
|
callback();
|
||||||
if (errs.length === 1) {
|
|
||||||
err = errs[0];
|
|
||||||
} else if (errs.length > 1) {
|
|
||||||
err = new errors.MultiError(errs);
|
|
||||||
}
|
|
||||||
callback(err);
|
|
||||||
});
|
});
|
||||||
};
|
}
|
||||||
|
|
||||||
do_instances.options = [
|
do_instances.options = [
|
||||||
{
|
{
|
||||||
names: ['help', 'h'],
|
names: ['help', 'h'],
|
||||||
type: 'bool',
|
type: 'bool',
|
||||||
help: 'Show this help.'
|
help: 'Show this help.'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
names: ['H'],
|
||||||
|
type: 'bool',
|
||||||
|
help: 'Omit table header row.'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
names: ['o'],
|
||||||
|
type: 'string',
|
||||||
|
default: 'id,name,state,type,image,memory,disk',
|
||||||
|
help: 'Specify fields (columns) to output.',
|
||||||
|
helpArg: 'field1,...'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
names: ['s'],
|
||||||
|
type: 'string',
|
||||||
|
default: 'name',
|
||||||
|
help: 'Sort on the given fields. Default is "name".',
|
||||||
|
helpArg: 'field1,...'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
names: ['json', 'j'],
|
names: ['json', 'j'],
|
||||||
type: 'bool',
|
type: 'bool',
|
||||||
@ -77,7 +113,6 @@ do_instances.help = (
|
|||||||
+ '\n'
|
+ '\n'
|
||||||
+ '{{options}}'
|
+ '{{options}}'
|
||||||
);
|
);
|
||||||
do_instances.aliases = ['insts'];
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = do_instances;
|
module.exports = do_instances;
|
||||||
|
@ -32,6 +32,10 @@ function do_packages (subcmd, opts, args, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.triton.cloudapi.listPackages(listOpts, function (err, packages) {
|
this.triton.cloudapi.listPackages(listOpts, function (err, packages) {
|
||||||
|
if (err) {
|
||||||
|
callback(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (opts.json) {
|
if (opts.json) {
|
||||||
console.log(common.jsonStream(packages));
|
console.log(common.jsonStream(packages));
|
||||||
} else {
|
} else {
|
||||||
|
Reference in New Issue
Block a user