'use strict'; var child_process = require('child_process'); /** * This is a DockerCmd representing "docker" command line * @constructor */ function DockerCmd() { } /** * @callback DockerCmd~callback * @param {number} dockerProcessExitCode - the docker process exit code (0 if all was OK) */ /** * Execute the given commandName with the given dockerOptions and commandOptions. * @param {string} commandName * @param {Options} commandOptions * @param {Object} dockerOptions * @param {DockerCmd~callback} callback */ DockerCmd.prototype.executeCommand = function(commandName, commandOptions, dockerOptions, callback) { // put all options in an array to give to "spawn" later var cmdOptions = ['docker']; // first the docker options to pass before the docker command appendOptions(cmdOptions, dockerOptions); // then the docker command cmdOptions.push(commandName); // and finally the command options with potentially final args (using the '_' field) appendOptions(cmdOptions, commandOptions); var dockerProcess = child_process.spawn('/usr/bin/env', cmdOptions, {stdio: 'inherit'}); dockerProcess.on('close', callback); }; /** * @param {string} commandName * @return {function(this:DockerCmd, Options, Object, DockerCmd~callback)} * @private */ DockerCmd.prototype._createDefaultCommand = function(commandName) { var self = this; /** * @param {Options} commandOptions * @param {Object} dockerOptions * @param {DockerCmd~callback} callback */ return function(commandOptions, dockerOptions, callback) { self.executeCommand(commandName, commandOptions, dockerOptions, callback); } }; /// Declare all the docker commands [ 'attach', 'build', 'commit', 'cp', 'diff', 'events', 'export', 'history', 'images', 'import', 'info', 'inspect', 'kill', 'load', 'login', 'logout', 'logs', 'port', 'pause', 'ps', 'pull', 'push', 'restart', 'rm', 'run', 'save', 'search', 'start', 'stop', 'tag', 'top', 'unpause', 'version', 'wait' ].forEach(function (commandName) { DockerCmd.prototype[commandName] = DockerCmd.prototype._createDefaultCommand(commandName); }); /** * Append each option from the given fromOptions to the given * options array, flattening them to pass them later as parameters to a * sub call process. * @param {string[]} options * @param {Options} fromOptions */ function appendOptions(options, fromOptions) { function pushOption(optionName, optionValue) { var valueDefined = optionValue !== null && optionValue !== undefined; if (optionName.length === 1) { // simple letter option options.push('-' + optionName); if (valueDefined) { options.push(optionValue); } } else { // full option name options.push('--' + optionName + (valueDefined ? '=' + optionValue : '')); } } for (var optionName in fromOptions) { if (fromOptions.hasOwnProperty(optionName) && optionName !== '_') { var optionValue = fromOptions[optionName]; if (Array.isArray(optionValue)) { // we have multiple values for the same option, let's iterate on each optionValue.forEach(function (iOptionValue) { pushOption(optionName, iOptionValue); }); } else { pushOption(optionName, optionValue); } } } // now append the "_" which are not "options" but args if (fromOptions && fromOptions._) { [].concat(fromOptions._).forEach(function(arg) { options.push(arg); }); } } module.exports = DockerCmd;