firmament-bash
Version:
Firmament module for interpreting commands in JSON files using bash
258 lines • 11.5 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};
Object.defineProperty(exports, "__esModule", { value: true });
const inversify_1 = require("inversify");
const firmament_yargs_1 = require("firmament-yargs");
const _ = require("lodash");
const path = require("path");
const async = require('async');
const chalk = require('chalk');
const textColors = ['green', 'yellow', 'blue', 'magenta', 'cyan', 'white', 'gray'];
const commandCatalogUrl = 'https://raw.githubusercontent.com/jreeme/firmament-bash/master/command-json/commandCatalog.json';
let ProcessCommandJsonImpl = class ProcessCommandJsonImpl extends firmament_yargs_1.ForceErrorImpl {
constructor(commandUtil, remoteCatalogGetter, executionGraphResolver, safeJson, spawn) {
super();
this.commandUtil = commandUtil;
this.remoteCatalogGetter = remoteCatalogGetter;
this.executionGraphResolver = executionGraphResolver;
this.safeJson = safeJson;
this.spawn = spawn;
}
processExecutionGraphJson(json, cb) {
const me = this;
cb = me.checkCallback(cb);
me.safeJson.safeParse(json, (err, executionGraph) => {
if (me.commandUtil.callbackIfError(cb, err)) {
return;
}
me.processExecutionGraph(executionGraph, cb);
});
}
processYargsCommand(argv) {
const me = this;
argv.catalogPath = argv.catalogPath || commandCatalogUrl;
me.processAbsoluteUrl(argv.input, (err) => {
if (err) {
const parsedError = me.safeJson.safeParseSync(err.message);
if (parsedError.err) {
me.remoteCatalogGetter.getCatalogFromUrl(argv.catalogPath, (err, commandCatalog) => {
me.commandUtil.processExitIfError(err);
if (!argv.input) {
me.commandUtil.log('\nAvailable templates:\n');
commandCatalog.entries.forEach(entry => {
me.commandUtil.log('> ' + entry.name);
});
me.commandUtil.processExit();
}
const commandGraph = _.find(commandCatalog.entries, entry => {
return entry.name === argv.input;
});
me.processCatalogEntry(commandGraph, (err) => {
err = err ? new Error(`Invalid execution graph: ${err.message}`) : null;
me.commandUtil.processExitWithError(err);
});
});
}
else {
me.commandUtil.processExitWithError(err);
}
}
else {
me.commandUtil.processExit();
}
});
}
processCatalogEntry(catalogEntry, cb) {
const me = this;
cb = me.checkCallback(cb);
if (me.checkForceError('ProcessCommandJsonImpl.processCatalogEntry', cb)) {
return;
}
me.executionGraphResolver.resolveExecutionGraphFromCatalogEntry(catalogEntry, (err, executionGraph) => {
if (me.commandUtil.callbackIfError(cb, err)) {
return;
}
me.processExecutionGraph(executionGraph, cb);
});
}
processAbsoluteUrl(jsonOrUri, cb) {
const me = this;
cb = me.checkCallback(cb);
if (me.checkForceError('ProcessCommandJsonImpl.processAbsoluteUrl', cb)) {
return;
}
me.executionGraphResolver.resolveExecutionGraph(jsonOrUri, (err, executionGraph) => {
if (me.commandUtil.callbackIfError(cb, err)) {
return;
}
me.processExecutionGraph(executionGraph, cb);
});
}
processExecutionGraph(executionGraph, cb) {
const me = this;
cb = me.checkCallback(cb);
let graphCursor = executionGraph;
const executionGraphs = [];
executionGraphs.unshift(graphCursor);
while (graphCursor = graphCursor.prerequisiteGraph) {
executionGraphs.unshift(graphCursor);
}
me.preProcessExecutionGraphs(executionGraphs, (err, fnArray) => {
if (me.commandUtil.callbackIfError(cb, err)) {
return;
}
async.series(fnArray, cb);
});
}
preProcessExecutionGraphs(executionGraphs, cb) {
const me = this;
cb = me.checkCallback(cb);
let counter = 0;
let useSudo = false;
let sudoPassword = '';
const fnArray = [];
executionGraphs.forEach(executionGraph => {
const eg = executionGraph;
eg.description = eg.description || 'ExecutionGraph +';
eg.options = eg.options || { displayExecutionGraphDescription: true };
eg.prerequisiteGraph = eg.prerequisiteGraph || null;
eg.prerequisiteGraphUri = eg.prerequisiteGraphUri || null;
eg.asynchronousCommands = eg.asynchronousCommands || [];
eg.serialSynchronizedCommands = eg.serialSynchronizedCommands || [];
[eg.asynchronousCommands, eg.serialSynchronizedCommands].forEach(commands => {
commands.forEach(command => {
command.outputColor = command.outputColor || textColors[counter++ % textColors.length];
if (!sudoPassword && command.sudoPassword) {
sudoPassword = command.sudoPassword;
}
if (!useSudo && command.useSudo) {
useSudo = command.useSudo;
}
});
});
fnArray.push(async.apply(me.executeSingleGraph.bind(me), executionGraph));
});
if (useSudo) {
me.spawn.sudoSpawnAsync(['printf', 'unicorn'], { sudoPassword }, () => {
}, (err) => {
if (me.commandUtil.callbackIfError(cb, err)) {
return;
}
cb(null, fnArray);
});
}
else {
cb(null, fnArray);
}
}
executeSingleGraph(executionGraph, cb) {
const me = this;
cb = me.checkCallback(cb);
if (!executionGraph) {
return cb(new Error('Invalid executionGraph'), null);
}
const eg = executionGraph;
if (eg.options.displayExecutionGraphDescription) {
me.commandUtil.log(chalk['green'](`Starting execution graph '${eg.description}'`));
}
const spawnFnArray = [
async.apply(me.executeAsynchronousCommands.bind(me), eg.asynchronousCommands),
async.apply(me.executeSynchronousCommands.bind(me), eg.serialSynchronizedCommands)
];
async.series(spawnFnArray, (err, results) => {
const msg = `Execution graph '${eg.description}' completed.\n`;
if (eg.options.displayExecutionGraphDescription) {
me.commandUtil.log(chalk['green'](msg));
}
cb(err, msg);
});
}
executeAsynchronousCommands(commands, cb) {
async.parallel(this.createSpawnFnArray(commands), cb);
}
executeSynchronousCommands(commands, cb) {
async.series(this.createSpawnFnArray(commands), cb);
}
createSpawnFnArray(commands) {
const me = this;
const spawnFnArray = [];
commands.forEach(command => {
const fnSpawn = command.useSudo
? me.spawn.sudoSpawnAsync.bind(me.spawn)
: me.spawn.spawnShellCommandAsync.bind(me.spawn);
const cmd = command.args.slice(0);
cmd.unshift(command.command);
const spawnOptions = me.buildSpawnOptions(command);
spawnFnArray.push(async.apply(me.spawnWrapper.bind(me), fnSpawn, cmd, spawnOptions, command.outputColor));
});
return spawnFnArray;
}
spawnWrapper(fnSpawn, cmd, spawnOptions, outputColor, cb) {
fnSpawn(cmd, spawnOptions, (err, results) => {
if (err) {
return this.commandUtil.stdoutWrite(chalk['redBright'](err.message));
}
this.commandUtil.stdoutWrite(chalk[outputColor](results));
}, (err, results) => {
err && this.commandUtil.stdoutWrite(chalk['redBright'](err.message));
this.commandUtil.stdoutWrite(chalk[outputColor](`${results}\n`));
cb(err, results);
}, (diagnosticMessage) => {
this.commandUtil.stdoutWrite(chalk[outputColor](diagnosticMessage));
});
}
buildSpawnOptions(command) {
let workingDirectory;
if (command.workingDirectory) {
workingDirectory = command.workingDirectory;
workingDirectory = path.isAbsolute(workingDirectory)
? workingDirectory
: path.resolve(process.cwd(), workingDirectory);
}
return {
preSpawnMessage: command.suppressPreAndPostSpawnMessages
? null
: `Starting task '${command.description}'\n`,
postSpawnMessage: command.suppressPreAndPostSpawnMessages
? null
: `Task '${command.description}' completed\n`,
suppressDiagnostics: command.suppressDiagnostics,
cacheStdErr: true,
cacheStdOut: false,
sudoUser: command.sudoUser,
remoteHost: command.remoteHost,
remoteUser: command.remoteUser,
remotePassword: command.remotePassword,
remoteSshKeyPath: command.remoteSshKeyPath,
remoteSshPort: command.remoteSshPort,
sudoPassword: command.sudoPassword,
suppressResult: command.suppressOutput || false,
suppressStdErr: command.suppressOutput || false,
suppressStdOut: command.suppressOutput || false,
suppressFinalError: command.suppressFinalError || false,
cwd: workingDirectory
};
}
};
ProcessCommandJsonImpl = __decorate([
inversify_1.injectable(),
__param(0, inversify_1.inject('CommandUtil')),
__param(1, inversify_1.inject('RemoteCatalogGetter')),
__param(2, inversify_1.inject('ExecutionGraphResolver')),
__param(3, inversify_1.inject('SafeJson')),
__param(4, inversify_1.inject('Spawn')),
__metadata("design:paramtypes", [Object, Object, Object, Object, Object])
], ProcessCommandJsonImpl);
exports.ProcessCommandJsonImpl = ProcessCommandJsonImpl;
//# sourceMappingURL=process-command-json-impl.js.map