UNPKG

firmament-bash

Version:

Firmament module for interpreting commands in JSON files using bash

258 lines 11.5 kB
"use strict"; 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