joyent/node-triton#26 triton command crashes with self-signed cert
Refactor do_instances to not call `callback` twice. Also don't assume if a `res` on an error callback from CloudApi._request. Fixes #26.
This commit is contained in:
parent
7aa59f148f
commit
c93b08dd68
@ -342,6 +342,7 @@ CloudApi.prototype.listKeys = function listKeys(opts, cb) {
|
||||
* <http://apidocs.joyent.com/cloudapi/#ListImages>
|
||||
*
|
||||
* @param {Object} options (optional)
|
||||
* XXX be more strict about accepted options
|
||||
* XXX document this, see the api doc above :)
|
||||
* @param {Function} callback of the form `function (err, images, res)`
|
||||
*/
|
||||
@ -553,9 +554,12 @@ function createListMachinesStream(options) {
|
||||
var endpoint = self._path(format('/%s/machines', self.user), options);
|
||||
|
||||
self._request(endpoint, function (err, req, res, body) {
|
||||
if (err) {
|
||||
return donecb(err);
|
||||
}
|
||||
var resourcecount = res.headers['x-resource-count'];
|
||||
var done = once || resourcecount < options.limit;
|
||||
donecb(err, {done: done, results: body});
|
||||
donecb(null, {done: done, results: body});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -10,12 +10,14 @@
|
||||
* `triton instances ...`
|
||||
*/
|
||||
|
||||
var f = require('util').format;
|
||||
|
||||
var format = require('util').format;
|
||||
var tabula = require('tabula');
|
||||
var vasync = require('vasync');
|
||||
|
||||
var common = require('./common');
|
||||
|
||||
|
||||
|
||||
// to be passed as query string args to /my/machines
|
||||
var validFilters = [
|
||||
'name',
|
||||
@ -36,6 +38,7 @@ var columnsDefaultLong = 'id,name,img,package,state,primaryIp,created';
|
||||
var sortDefault = 'created';
|
||||
|
||||
function do_instances(subcmd, opts, args, callback) {
|
||||
var self = this;
|
||||
if (opts.help) {
|
||||
this.do_help('help', {}, [subcmd], callback);
|
||||
return;
|
||||
@ -59,55 +62,64 @@ function do_instances(subcmd, opts, args, callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
var i = 0;
|
||||
|
||||
i++;
|
||||
var images;
|
||||
this.tritonapi.listImages({useCache: true}, function (err, _images) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
var imgs;
|
||||
var insts;
|
||||
|
||||
vasync.parallel({funcs: [
|
||||
function getTheImages(next) {
|
||||
self.tritonapi.listImages({useCache: true}, function (err, _imgs) {
|
||||
if (err) {
|
||||
next(err);
|
||||
} else {
|
||||
imgs = _imgs;
|
||||
next();
|
||||
}
|
||||
});
|
||||
},
|
||||
function getTheMachines(next) {
|
||||
self.tritonapi.cloudapi.listMachines(listOpts,
|
||||
function (err, _insts) {
|
||||
if (err) {
|
||||
next(err);
|
||||
} else {
|
||||
insts = _insts;
|
||||
next();
|
||||
}
|
||||
});
|
||||
}
|
||||
images = _images;
|
||||
done();
|
||||
});
|
||||
|
||||
i++;
|
||||
var machines;
|
||||
this.tritonapi.cloudapi.listMachines(listOpts, function (err, _machines) {
|
||||
]}, function (err, results) {
|
||||
/*
|
||||
* Error handling: vasync.parallel's `err` is always a MultiError. We
|
||||
* want to prefer the `getTheMachines` err, e.g. if both get a
|
||||
* self-signed cert error.
|
||||
*/
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
err = results.operations[1].err || err;
|
||||
return callback(err);
|
||||
}
|
||||
machines = _machines;
|
||||
done();
|
||||
});
|
||||
|
||||
function done() {
|
||||
if (--i > 0)
|
||||
return;
|
||||
|
||||
// map "uuid" => "image_name"
|
||||
var imgmap = {};
|
||||
images.forEach(function (image) {
|
||||
imgmap[image.id] = f('%s@%s', image.name, image.version);
|
||||
imgs.forEach(function (img) {
|
||||
imgmap[img.id] = format('%s@%s', img.name, img.version);
|
||||
});
|
||||
|
||||
// Add extra fields for nice output.
|
||||
// XXX FWIW, the "extra fields" for images and packages are not added
|
||||
// for `opts.json`. Thoughts? We should be consistent there. --TM
|
||||
var now = new Date();
|
||||
machines.forEach(function (machine) {
|
||||
var created = new Date(machine.created);
|
||||
machine.ago = common.longAgo(created, now);
|
||||
machine.img = imgmap[machine.image] || machine.image;
|
||||
machine.shortid = machine.id.split('-', 1)[0];
|
||||
insts.forEach(function (inst) {
|
||||
var created = new Date(inst.created);
|
||||
inst.ago = common.longAgo(created, now);
|
||||
inst.img = imgmap[inst.image] || inst.image;
|
||||
inst.shortid = inst.id.split('-', 1)[0];
|
||||
});
|
||||
|
||||
if (opts.json) {
|
||||
common.jsonStream(machines);
|
||||
common.jsonStream(insts);
|
||||
} else {
|
||||
tabula(machines, {
|
||||
tabula(insts, {
|
||||
skipHeader: opts.H,
|
||||
columns: columns,
|
||||
sort: sort,
|
||||
@ -115,7 +127,7 @@ function do_instances(subcmd, opts, args, callback) {
|
||||
});
|
||||
}
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
do_instances.options = [
|
||||
|
Reference in New Issue
Block a user