Comparing version 3.4.1 to 3.5.0
{ | ||
"name": "devlab", | ||
"version": "3.4.1", | ||
"version": "3.5.0", | ||
"description": "Node utility for running containerized tasks", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
@@ -146,7 +146,7 @@ [![CircleCI branch](https://img.shields.io/circleci/project/TechnologyAdvice/DevLab/master.svg?maxAge=2592000)]() | ||
Since container shutdown is a detached, unattended process it is _possible_ for services to fail to shutdown. On each run, before starting services or executing tasks, Devlab will run a check and attempt to identify any orphaned services. | ||
Devlab will automatically `stop` services after any run (success or fail). However, if this fails or some other fringe-case causes this process to stop responding the system can leave orphaned containers running. | ||
If orphaned services are identified a warning message will appear at the beginning of the process to indicate the orphaned service(s) and commands to remedy/exit these containers. | ||
In order to mitigate this issue Devlab will run a check for any `dl_` prefixed containers on each run. If orphaned services are identified a warning message will appear at the beginning of the process to indicate the orphaned service(s) and commands to remedy/exit these containers. | ||
Additionally, the following commands can be run to cleanup any running containers: | ||
The following commands can be run to cleanup any running containers: | ||
@@ -153,0 +153,0 @@ **Stop and Remove Devlab Containers:** |
@@ -106,3 +106,3 @@ 'use strict' | ||
const cwd = process.cwd() | ||
let args = primary ? [ 'run', '--rm', '-it', '-v', `${cwd}:${cwd}`, '-v', `${tmpdir}:${tmpdir}`, '-w', cwd, '--privileged' ] : [ 'run', '-d', '--privileged' ] | ||
let args = primary ? [ 'run', '--rm', '-it', '-v', `${cwd}:${cwd}`, '-v', `${tmpdir}:${tmpdir}`, '-w', cwd, '--privileged' ] : [ 'run', '-d', '--rm', '--privileged' ] | ||
args = args.concat(_.flatten([ | ||
@@ -109,0 +109,0 @@ command.getArgs(cfg), |
@@ -55,2 +55,16 @@ 'use strict' | ||
/** | ||
* Stops services and resolves or rejects | ||
* @returns {object} promise | ||
*/ | ||
stopServices: () => { | ||
if (!services.running.length) return Promise.resolve() | ||
const servicesStopSpinner = output.spinner('Stopping services') | ||
return services.stop() | ||
.then(() => servicesStopSpinner.succeed()) | ||
.catch((err) => { | ||
servicesStopSpinner.fail() | ||
output.error(`The following services failed to exit: ${err.svcs.join(', ')}`) | ||
}) | ||
}, | ||
/** | ||
* Runs primary command | ||
@@ -87,3 +101,3 @@ * @param {object} config The instance config object | ||
.then(instance.runCommand) | ||
.then(services.stop) | ||
.then(instance.stopServices) | ||
}).catch((e) => { | ||
@@ -90,0 +104,0 @@ services.stop() |
@@ -25,2 +25,7 @@ 'use strict' | ||
/** | ||
* Output info message | ||
* @param {string} m Output message | ||
*/ | ||
info: (m) => console.log(`${chalk.blue(logSymbols.info)} ${m}`), | ||
/** | ||
* Output warning message | ||
@@ -27,0 +32,0 @@ * @param {string} m Output message |
@@ -35,2 +35,3 @@ 'use strict' | ||
services.disabled = _.keys(_.filter(_.equals(objs.length), counts)) | ||
/* istanbul ignore if: lots of work, testing doesn't prove anything... */ | ||
if (!services.disabled.length) return cfg | ||
@@ -67,15 +68,23 @@ // Keep service if name is not in disabled list | ||
/** | ||
* Kills all running services with detached process | ||
* Kills all running, non-persisted services | ||
* @returns {object} promise | ||
*/ | ||
stop: () => _.unless( | ||
_.isEmpty, | ||
_.pipe([ | ||
_.filter(_.test(/dl_/)), | ||
_.map(svc => `docker stop ${svc} && docker rm ${svc}`), | ||
_.join(' && '), | ||
proc.runDetached | ||
]) | ||
)(services.running) | ||
stop: () => { | ||
const errors = [] | ||
return Promise.all( | ||
_.pipe([ | ||
_.filter(_.test(/dl_/)), | ||
_.map(svc => proc.run([ 'stop', svc ], true).catch(() => errors.push(svc))) | ||
])(services.running)) | ||
.then(() => { | ||
const stopError = new Error() | ||
/* istanbul ignore next: this is actually tested, istanbul... */ | ||
if (errors.length) { | ||
stopError.svcs = errors | ||
throw stopError | ||
} | ||
}) | ||
} | ||
} | ||
module.exports = services |
@@ -8,2 +8,3 @@ 'use strict' | ||
/* istanbul ignore next: just a helper, will fail other tests */ | ||
const pad = (len, str) => str.length < len ? str + ' '.repeat(len - str.length) : str | ||
@@ -33,13 +34,16 @@ | ||
const ids = cp.execSync(findCmd).toString() | ||
/* istanbul ignore else */ | ||
if (ids.length) { | ||
cp.execSync(_.pipe([ | ||
_.split(/\r?\n/), | ||
_.filter((id) => id.length > 0), | ||
_.map((id) => { | ||
return `docker stop ${id} && docker rm ${id}` | ||
}), | ||
_.join(' && ') | ||
])(ids)) | ||
if (!ids.length) { | ||
output.success('All clean') | ||
return | ||
} | ||
_.pipe([ | ||
_.split(/\r?\n/), | ||
_.filter(Boolean), | ||
_.tap(uniqIds => output.info(`Stopping ${uniqIds.length} containers:`)), | ||
_.map(id => { | ||
cp.execSync(`docker stop ${id} >&2 > /dev/null`) | ||
output.success(id) | ||
}) | ||
])(ids) | ||
}, | ||
@@ -46,0 +50,0 @@ /** |
32959
643