Factor out spinner to prep for using it for 'triton wait'.
Also refactor 'triton wait' for debuggability and to avoid possible multiple calls to the callback.
This commit is contained in:
parent
9241f90ccf
commit
12c9cb64a6
5
TODO.txt
5
TODO.txt
@ -4,7 +4,10 @@ MPL blurb at the start of each file.
|
||||
|
||||
'make check'
|
||||
|
||||
test suite
|
||||
test suite:
|
||||
- all the commands: test/integration/cli-*.test.js
|
||||
- TritonApi testing: test/integration/api-*.test.js
|
||||
- more test/unit/...
|
||||
|
||||
note in README that full UUIDs is much faster in the API
|
||||
|
||||
|
33
lib/distractions.js
Normal file
33
lib/distractions.js
Normal file
@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Joyent Inc. All rights reserved.
|
||||
*
|
||||
* A CLI distraction during a long process (e.g. waiting for
|
||||
* create).
|
||||
*
|
||||
* Usage:
|
||||
* var distractions = require('./distractions');
|
||||
* var distraction = distractions.createDistraction();
|
||||
* setTimeout(function () {
|
||||
* distraction.destroy();
|
||||
* }, 5000);
|
||||
*/
|
||||
|
||||
var bigspinner = require('bigspinner');
|
||||
|
||||
|
||||
function createDistraction() {
|
||||
var BORDER = 10;
|
||||
return bigspinner.createSpinner({
|
||||
delay: 50,
|
||||
positions: 40,
|
||||
stream: process.stderr,
|
||||
height: Math.max(2, process.stdout.rows - 2 - BORDER),
|
||||
width: Math.max(2, process.stdout.columns - 1 - BORDER),
|
||||
hideCursor: true,
|
||||
fontChar: '\u2588' // '\x1b[7m \x1b[m'
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
createDistraction: createDistraction
|
||||
}
|
@ -4,12 +4,12 @@
|
||||
* `triton create ...`
|
||||
*/
|
||||
|
||||
var bigspinner = require('bigspinner');
|
||||
var format = require('util').format;
|
||||
var tabula = require('tabula');
|
||||
var vasync = require('vasync');
|
||||
|
||||
var common = require('./common');
|
||||
var distractions = require('./distractions');
|
||||
var errors = require('./errors');
|
||||
|
||||
|
||||
@ -107,18 +107,9 @@ function do_create_instance(subcmd, opts, args, callback) {
|
||||
return next();
|
||||
}
|
||||
|
||||
var spinner;
|
||||
var distraction;
|
||||
if (!opts.quiet && process.stderr.isTTY) {
|
||||
var BORDER = 10;
|
||||
spinner = bigspinner.createSpinner({
|
||||
delay: 50,
|
||||
positions: 40,
|
||||
stream: process.stderr,
|
||||
height: Math.max(2, process.stdout.rows - 2 - BORDER),
|
||||
width: Math.max(2, process.stdout.columns - 1 - BORDER),
|
||||
hideCursor: true,
|
||||
fontChar: '\u2588' // '\x1b[7m \x1b[m'
|
||||
});
|
||||
distraction = distractions.createDistraction();
|
||||
}
|
||||
|
||||
// Dry-run: fake wait for a few seconds.
|
||||
@ -135,8 +126,8 @@ function do_create_instance(subcmd, opts, args, callback) {
|
||||
id: ctx.inst.id,
|
||||
states: ['running', 'failed']
|
||||
}, function (err, inst) {
|
||||
if (spinner) {
|
||||
spinner.destroy();
|
||||
if (distraction) {
|
||||
distraction.destroy();
|
||||
}
|
||||
if (err) {
|
||||
return next(err);
|
||||
|
@ -5,19 +5,19 @@
|
||||
*/
|
||||
|
||||
var format = require('util').format;
|
||||
var vasync = require('vasync');
|
||||
|
||||
var common = require('./common');
|
||||
var distractions = require('./distractions');
|
||||
var errors = require('./errors');
|
||||
|
||||
|
||||
|
||||
function do_wait_instance(subcmd, opts, args, cb) {
|
||||
var self = this;
|
||||
if (opts.help) {
|
||||
return this.do_help('help', {}, [subcmd], cb);
|
||||
} else if (args.length < 1) {
|
||||
return cb(new errors.UsageError(format(
|
||||
'incorrect number of args (%d): %s', args.length, args.join(' '))));
|
||||
return cb(new errors.UsageError('missing INSTANCE arg(s)'));
|
||||
}
|
||||
var ids = args;
|
||||
var states = [];
|
||||
@ -25,39 +25,80 @@ function do_wait_instance(subcmd, opts, args, cb) {
|
||||
states = states.concat(s.trim().split(/\s*,\s*/g));
|
||||
});
|
||||
|
||||
function log() {
|
||||
if (!opts.quiet)
|
||||
console.log.apply(console, arguments);
|
||||
}
|
||||
|
||||
var distraction;
|
||||
var done = 0;
|
||||
var instFromId = {};
|
||||
|
||||
var machines = {};
|
||||
|
||||
var i = 0;
|
||||
ids.forEach(function (id) {
|
||||
i++;
|
||||
if (common.isUUID(id)) {
|
||||
machines[id] = {};
|
||||
go1();
|
||||
return;
|
||||
}
|
||||
|
||||
self.triton.getInstance(id, function (err, machine) {
|
||||
vasync.pipeline({funcs: [
|
||||
function getInsts(_, next) {
|
||||
vasync.forEachParallel({
|
||||
inputs: ids,
|
||||
func: function getInst(id, nextInst) {
|
||||
self.triton.getInstance(id, function (err, inst) {
|
||||
if (err) {
|
||||
cb(err);
|
||||
return;
|
||||
return nextInst(err);
|
||||
}
|
||||
if (states.indexOf(machine.state) >= 0) {
|
||||
// machine in acceptable state already... skip it
|
||||
log('%d/%d: %s already in acceptable state: %s',
|
||||
++done, ids.length, id, machine.state);
|
||||
if (states.indexOf(inst.state) !== -1) {
|
||||
console.log('%d/%d: Instance %s (%s) already %s',
|
||||
++done, ids.length, inst.name, id, inst.state);
|
||||
} else {
|
||||
machines[machine.id] = machine;
|
||||
instFromId[inst.id] = inst;
|
||||
}
|
||||
go1();
|
||||
nextInst();
|
||||
});
|
||||
},
|
||||
}, next);
|
||||
},
|
||||
|
||||
function waitForInsts(_, next) {
|
||||
var idsToWaitFor = Object.keys(instFromId);
|
||||
if (idsToWaitFor.length === 0) {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (idsToWaitFor.length === 1) {
|
||||
var inst2 = instFromId[idsToWaitFor[0]];
|
||||
console.log(
|
||||
"Waiting for instance %s (%s) to enter state (states: %s)",
|
||||
inst2.name, inst2.id, states.join(', '));
|
||||
} else {
|
||||
console.log(
|
||||
"Waiting for %d instances to enter state (states: %s)",
|
||||
idsToWaitFor.length, states.join(', '));
|
||||
}
|
||||
|
||||
var distraction;
|
||||
if (false /* TODO: need BigSpinner.log first */
|
||||
&& !opts.quiet && process.stderr.isTTY)
|
||||
{
|
||||
distraction = distractions.createDistraction();
|
||||
}
|
||||
|
||||
vasync.forEachParallel({
|
||||
inputs: idsToWaitFor,
|
||||
func: function waitForInst(id, nextInst) {
|
||||
self.triton.cloudapi.waitForMachineStates({
|
||||
id: id,
|
||||
states: states
|
||||
}, function (err, inst, res) {
|
||||
if (err) {
|
||||
return nextInst(err);
|
||||
}
|
||||
console.log('%d/%d: Instance %s (%s) moved to state %s',
|
||||
++done, ids.length, inst.name, inst.id, inst.state);
|
||||
nextInst();
|
||||
});
|
||||
}
|
||||
}, next);
|
||||
}
|
||||
|
||||
]}, function (err) {
|
||||
if (distraction) {
|
||||
distraction.destroy();
|
||||
}
|
||||
cb(err);
|
||||
});
|
||||
|
||||
|
||||
function go1() {
|
||||
if (--i > 0)
|
||||
@ -95,7 +136,7 @@ function do_wait_instance(subcmd, opts, args, cb) {
|
||||
|
||||
do_wait_instance.aliases = ['wait'];
|
||||
do_wait_instance.help = [
|
||||
'Wait on instances moving to given states.',
|
||||
'Wait on instances changing state.',
|
||||
'',
|
||||
'Usage:',
|
||||
' {{name}} wait [-s STATES] INSTANCE [INSTANCE ...]',
|
||||
@ -114,7 +155,7 @@ do_wait_instance.options = [
|
||||
{
|
||||
names: ['quiet', 'q'],
|
||||
type: 'bool',
|
||||
help: 'Disable all output.'
|
||||
help: 'No progress spinner while waiting.'
|
||||
},
|
||||
{
|
||||
names: ['states', 's'],
|
||||
|
Reference in New Issue
Block a user