134 lines
3.8 KiB
JavaScript
134 lines
3.8 KiB
JavaScript
const spawn = require('child_process').spawn;
|
|
const execFile = require('child_process').execFile;
|
|
const camelToSnake = require('./util').camelToSnake;
|
|
|
|
const docker = {
|
|
async run(image, commandArgs, options, execOptions) {
|
|
const args = commandArgs
|
|
? [image].concat(commandArgs)
|
|
: image;
|
|
const execMode = options.detach ? 'exec' : 'spawn';
|
|
|
|
const child = await this.command('run',
|
|
args,
|
|
options,
|
|
execMode,
|
|
execOptions
|
|
);
|
|
return options.detach
|
|
? new Container(child.stdout.trim())
|
|
: child;
|
|
},
|
|
|
|
async build(url, options, execOptions) {
|
|
return await this.command('build',
|
|
url,
|
|
options,
|
|
'spawn',
|
|
execOptions
|
|
);
|
|
},
|
|
|
|
async start(id, options) {
|
|
const ct = new Container(id);
|
|
await ct.start(options);
|
|
return ct;
|
|
},
|
|
|
|
async stop(id, options) {
|
|
const ct = new Container(id);
|
|
return await ct.stop(options);
|
|
},
|
|
|
|
async rm(id, options) {
|
|
const ct = new Container(id);
|
|
return await ct.rm(options);
|
|
},
|
|
|
|
async inspect(id, options) {
|
|
const ct = new Container(id);
|
|
return await ct.inspect(options);
|
|
},
|
|
|
|
async command(command, args, options, execMode, execOptions) {
|
|
const execArgs = [command];
|
|
|
|
if (options)
|
|
for (const option in options) {
|
|
execArgs.push(`--${camelToSnake(option)}`);
|
|
if (typeof options[option] !== 'boolean')
|
|
execArgs.push(options[option]);
|
|
}
|
|
|
|
if (Array.isArray(args))
|
|
Array.prototype.push.apply(execArgs, args);
|
|
else if (args)
|
|
execArgs.push(args);
|
|
|
|
return await new Promise((resolve, reject) => {
|
|
if (execMode == 'spawn') {
|
|
if (execOptions === true)
|
|
execOptions = {
|
|
stdio: [
|
|
process.stdin,
|
|
process.stdout,
|
|
process.stderr
|
|
]
|
|
};
|
|
|
|
const child = spawn('docker', execArgs, execOptions || undefined);
|
|
child.on('exit', code => {
|
|
if (code !== 0) {
|
|
const quotedArgs = execArgs
|
|
.map(x => /\s/g.test(x) ? `"${x}"` : x)
|
|
.join(' ');
|
|
reject(new Error(`Docker exit code ${code}: 'docker ${quotedArgs}'`));
|
|
} else
|
|
resolve(code);
|
|
});
|
|
} else {
|
|
execFile('docker', execArgs, (err, stdout, stderr) => {
|
|
if (err)
|
|
reject(err);
|
|
else
|
|
resolve({stdout, stderr});
|
|
});
|
|
}
|
|
});
|
|
}
|
|
};
|
|
|
|
class Container {
|
|
constructor(id) {
|
|
if (!id)
|
|
throw new Error('Container id argument is required');
|
|
this.id = id;
|
|
}
|
|
|
|
async start(options) {
|
|
await docker.command('start', this.id, options);
|
|
}
|
|
|
|
async stop(options) {
|
|
await docker.command('stop', this.id, options);
|
|
}
|
|
|
|
async rm(options) {
|
|
await docker.command('rm', this.id, options);
|
|
}
|
|
|
|
async inspect(options) {
|
|
const child = await docker.command('inspect', this.id, options);
|
|
return JSON.parse(child.stdout);
|
|
}
|
|
|
|
async exec(options, command, commandArgs, execMode, execOptions) {
|
|
let args = [this.id, command];
|
|
if (commandArgs) args = args.concat(commandArgs);
|
|
await docker.command('exec', args, options, execMode, execOptions);
|
|
}
|
|
}
|
|
|
|
module.exports = docker;
|
|
module.exports.Container = Container;
|