From 4d7fac4b2a689786d3d591f349119246cabf2987 Mon Sep 17 00:00:00 2001 From: Ignatiev Mikhail Date: Sat, 16 Jun 2018 16:42:43 +0300 Subject: [PATCH] exec and run implementation --- index.js | 59 +++++++++++++++++++++++++++++---------- test/docker-compose-2.yml | 4 +-- test/docker-compose.yml | 5 +++- test/index.js | 38 +++++++++++++++++++++++-- 4 files changed, 86 insertions(+), 20 deletions(-) diff --git a/index.js b/index.js index d0facf8..fb93154 100644 --- a/index.js +++ b/index.js @@ -1,20 +1,16 @@ 'use strict'; const promisify = require('es6-promisify'); -const exec = promisify(require('child_process').exec, { multiArgs: true }); +const execute = promisify(require('child_process').exec, { multiArgs: true }); const logger = require('./lib/log'); -const logStandards = function (standards) { - const stdout = standards.stdout || standards[0]; - - if (stdout && stdout.length > 0) { - logger.info(stdout); +const logStandards = function (std) { + if (std.out && std.out.length > 0) { + logger.info(std.out); } - const stderr = standards.stderr || standards[1]; - - if (stderr) { - logger.warn(stderr); + if (std.err && std.err.length > 0) { + logger.warn(std.err); } }; @@ -46,13 +42,18 @@ const execCompose = (command, options) => new Promise((resolve, reject) => { const cmd = `docker-compose ${configToArgs(options.config)} ${command}`; const cwd = options.cwd; - exec(cmd, { cwd }).then( + execute(cmd, { cwd }).then( standards => { + const std = { + out: standards[0], + err: standards[1] + }; + if (options.log) { - logStandards(standards); + logStandards(std); } - resolve(); + resolve(std); }, error => { logger.error(error.message); @@ -112,4 +113,34 @@ const rm = function (options) { return execCompose('rm -f', options); }; -module.exports = { up, kill, down, stop, rm }; +/** + * Execute command in a running container + * @param {string} contaier container name + * @param {string} command command to execute + * @param {object} options + * @param {string} options.cwd + * @param {boolean} [options.log] + * @param {?(string|string[])} [options.config] + * + * @return {object} std.out / std.err + */ +const exec = function (container, command, options) { + return execCompose(`exec -T ${container} ${command}`, options); +}; + +/** + * Run command + * @param {string} contaier container name + * @param {string} command command to execute + * @param {object} options + * @param {string} options.cwd + * @param {boolean} [options.log] + * @param {?(string|string[])} [options.config] + * + * @return {object} std.out / std.err + */ +const run = function (container, command, options) { + return execCompose(`run -T ${container} ${command}`, options); +}; + +module.exports = { up, kill, down, stop, rm, exec, run }; diff --git a/test/docker-compose-2.yml b/test/docker-compose-2.yml index 6497927..9b5883b 100644 --- a/test/docker-compose-2.yml +++ b/test/docker-compose-2.yml @@ -2,5 +2,5 @@ version: '2' services: db: - image: alpine:3.7 - container_name: compose_test_alpine \ No newline at end of file + image: mongo:3.4 + container_name: compose_test_mongodb_2 \ No newline at end of file diff --git a/test/docker-compose.yml b/test/docker-compose.yml index 25834b4..b56b445 100644 --- a/test/docker-compose.yml +++ b/test/docker-compose.yml @@ -3,4 +3,7 @@ version: '2' services: db: image: mongo:3.4 - container_name: compose_test_mongodb \ No newline at end of file + container_name: compose_test_mongodb + alpine: + image: alpine:3.7 + container_name: compose_test_apline \ No newline at end of file diff --git a/test/index.js b/test/index.js index 231fe56..4f6d7c0 100644 --- a/test/index.js +++ b/test/index.js @@ -57,11 +57,43 @@ test('ensure custom ymls are working', async assert => { const log = true; await compose.up({ cwd, log, config }); - assert.true(await isContainerRunning('/compose_test_alpine')); + assert.true(await isContainerRunning('/compose_test_mongodb_2')); - // config & [config] is the same thing, ensures that multiple configs are handled properly + // config & [config] are the same thing, ensures that multiple configs are handled properly await compose.kill({ cwd, log, config: [ config ]}); - assert.false(await isContainerRunning('/compose_test_alpine')); + assert.false(await isContainerRunning('/compose_test_mongodb_2')); + assert.end(); +}); + +test('ensure run and exec are working', async assert => { + const checkOSID = (out, id) => { + // parse /etc/os-release contents + const re = /([\w,_]+)=(.*)/g; + let match = null; + const os = {}; + + while ((match = re.exec(out)) !== null) { // eslint-disable-line no-cond-assign + os[match[1]] = match[2]; + } + + assert.equals(os.ID, id); + }; + + const opts = { cwd: path.join(__dirname), log: false }; + + await compose.up(opts); + + assert.true(await isContainerRunning('/compose_test_mongodb')); + + let std = await compose.exec('db', 'cat /etc/os-release', opts); + + assert.false(std.err); + checkOSID(std.out, 'debian'); + + std = await compose.run('alpine', 'cat /etc/os-release', opts); + assert.false(std.err); + checkOSID(std.out, 'alpine'); + assert.end(); });