Socket
Socket
Sign inDemoInstall

@nikitajs/docker

Package Overview
Dependencies
179
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.9.7 to 1.0.0-alpha.0

CHANGELOG.md

485

lib/build.js

@@ -5,3 +5,3 @@ // Generated by CoffeeScript 2.5.1

// Build docker repository from Dockerfile, from content or from current working
// directory (exclusive options).
// directory.

@@ -16,31 +16,4 @@ // The user can choose whether the build is local or on the remote.

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `image` (string)
// Name of the image, required.
// * `tag` (string)
// Tag of the image.
// * `machine` (string)
// Name of the docker-machine, required if using docker-machine.
// * `file`
// Path to Dockerfile.
// * `content` (string | [string])
// Use this text to build the repository.
// * `quiet` (boolean)
// Suppress the verbose output generated by the containers. Default to false
// * `rm` (boolean)
// Remove intermediate containers after build, default to true.
// * `force_rm` (boolean)
// Always remove intermediate containers during build, default to false.
// * `no_cache` (boolean)
// Do not use cache when building the repository, default to false.
// * `build_arg` ("k=v" | [])
// Send arguments to the build (Must match an ARG command).
// * `cwd` (string)
// change the working directory for the build.
// ## Callback parameters
// * `err`

@@ -57,17 +30,13 @@ // Error object if any.

// ## Examples
// ## Builds a repository from dockerfile without any resourcess
// ### Builds a repository from dockerfile without any resourcess
// ```javascript
// require('nikita')
// .docker.build({
// ```js
// const {status} = await nikita.docker.build({
// image: 'ryba/targe-build',
// source: '/home/ryba/Dockerfile'
// }, function(err, {status}){
// console.log( err ? err.message : 'Container built: ' + status);
// });
// })
// console.info(`Container was built: ${status}`)
// ```
// ### Builds an repository from dockerfile with external resources
// ## Builds a repository from dockerfile with external resources

@@ -92,243 +61,271 @@ // In this case nikita download all the external files into a resources directory in the same location

// ```javascript
// require('nikita')
// .docker.build({
// ```js
// const {status} = await nikita.docker.build({
// tag: 'ryba/target-build',
// source: '/home/ryba/Dockerfile',
// resources: ['http://url.com/package.tar.gz/','/home/configuration.sh']
// }, function(err, {status}){
// console.log( err ? err.message : 'Container built: ' + status);
// });
// })
// console.info(`Container was built: ${status}`)
// ```
// ### Builds an repository from stdin
// ## Builds a repository from stdin
// ```javascript
// require('nikita')
// .docker.build({
// ```js
// const {status} = await nikita.docker.build({
// ssh: ssh,
// tag: 'ryba/target-build'
// content: "FROM ubuntu\nRUN echo 'helloworld'"
// }, function(err, {status}){
// console.log( err ? err.message : 'Container built: ' + status);
// });
// })
// console.info(`Container was built: ${status}`)
// ```
// ## Source Code
var docker, path, string, util,
// ## Hooks
var errors, handler, on_action, path, schema, utils,
indexOf = [].indexOf;
module.exports = function({options}, callback) {
var cmd, dockerfile_cmds, i, j, k, l, len, len1, len2, number_of_step, opt, ref, ref1, ref2, ref3, source, ssh, userargs, v;
this.log({
message: "Entering Docker build",
level: 'DEBUG',
module: 'nikita/lib/docker/build'
});
// SSH connection
ssh = this.ssh(options.ssh);
// Global options
if (options.docker == null) {
options.docker = {};
on_action = function({config}) {
if ((config.content != null) && (config.file != null)) {
throw errors.NIKITA_DOCKER_BUILD_CONTENT_FILE_REQUIRED();
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
};
// ## Schema
schema = {
type: 'object',
properties: {
'build_arg': {
oneOf: [
{
type: 'string'
},
{
type: 'object',
patternProperties: {
'.*': {
typeof: 'string'
}
}
}
],
description: `Send arguments to the build, match the Docker native ARG command.`
},
'content': {
type: 'string',
description: `Content of the Docker file, required unless \`file\` is provided.`
},
'cwd': {
type: 'string',
description: `Change the build working directory.`
},
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'file': {
type: 'string',
description: `Path to Dockerfile, required unless \`content\` is provided.`
},
'force_rm': {
type: 'boolean',
default: false,
description: `Always remove intermediate containers during build.`
},
'image': {
type: 'string',
description: `Name of the Docker image present in the registry.`
},
'quiet': {
type: 'boolean',
default: false,
description: `Suppress the verbose output generated by the containers.`
},
'rm': {
type: 'boolean',
default: true,
description: `Remove intermediate containers after a successful build.`
},
'no_cache': {
type: 'boolean',
default: false,
description: `Do not use cache when building the repository.`
},
'tag': {
type: 'string',
description: `Tag of the Docker image, default to latest.`
}
}
if (options.image == null) {
// Validation
return callback(Error('Required option "image"'));
}
if ((options.content != null) && (options.file != null)) {
return callback(Error('Can not build from Dockerfile and content'));
}
if (options.rm == null) {
options.rm = true;
}
cmd = 'build';
},
required: ['image']
};
// ## Handler
handler = async function({
config,
tools: {log}
}) {
var dockerfile_commands, i, image_id, k, len, line, lines, number_of_cache, number_of_step, ref, ref1, ref2, source, stderr, stdout, userargs;
number_of_step = 0;
userargs = [];
// status unmodified if final tag already exists
dockerfile_cmds = ['CMD', 'LABEL', 'EXPOSE', 'ENV', 'ADD', 'COPY', 'ENTRYPOINT', 'VOLUME', 'USER', 'WORKDIR', 'ARG', 'ONBUILD', 'RUN', 'STOPSIGNAL', 'MAINTAINER'];
source = null;
if (options.file) {
source = options.file;
} else if (options.cwd) {
source = `${options.cwd}/Dockerfile`;
dockerfile_commands = ['CMD', 'LABEL', 'EXPOSE', 'ENV', 'ADD', 'COPY', 'ENTRYPOINT', 'VOLUME', 'USER', 'WORKDIR', 'ARG', 'ONBUILD', 'RUN', 'STOPSIGNAL', 'MAINTAINER'];
source = void 0;
if (config.file) {
source = config.file;
} else if (config.cwd) {
source = `${config.cwd}/Dockerfile`;
}
if (options.file) {
if (options.cwd == null) {
options.cwd = path.dirname(options.file);
if (config.file) {
if (config.cwd == null) {
config.cwd = path.dirname(config.file);
}
}
ref1 = ['force_rm', 'quiet', 'no_cache'];
// Apply search and replace to content
// options.write ?= []
// if options.from? or options.to? or options.match? or options.replace? or options.before?
// options.write.push
// from: options.from
// to: options.to
// match: options.match
// replace: options.replace
// append: options.append
// before: options.before
// options.append = false
// Build cmd
for (i = 0, len = ref1.length; i < len; i++) {
opt = ref1[i];
if (options[opt]) {
cmd += ` --${opt.replace('_', '-')}`;
if (config.cwd) {
if (config.file == null) {
config.file = path.resolve(config.cwd, 'Dockerfile');
}
}
ref2 = ['build_arg'];
for (j = 0, len1 = ref2.length; j < len1; j++) {
opt = ref2[j];
if (options[opt] != null) {
if (Array.isArray(options[opt])) {
ref3 = options[opt];
for (l = 0, len2 = ref3.length; l < len2; l++) {
k = ref3[l];
cmd += ` --${opt.replace('_', '-')} ${k}`;
// Make sure the Dockerfile exists
if (!config.content) {
await this.fs.assert(config.file);
}
// Build the image
({stdout, stderr} = (await this.docker.tools.execute({
command: [
'build',
...(['force_rm',
'quiet',
'no_cache'].filter(function(opt) {
return config[opt];
}).map(function(opt) {
return `--${opt.replace('_',
'-')}`;
})),
...(utils.array.flatten(['build_arg']).filter(function(opt) {
return config[opt];
}).map(function(opt) {
var i,
k,
len,
ref,
results;
if (Array.isArray(config[opt])) {
ref = config[opt];
results = [];
for (i = 0, len = ref.length; i < len; i++) {
k = ref[i];
results.push(`--${opt.replace('_',
'-')} ${k}`);
}
return results;
} else {
return `--${opt.replace('_',
'-')} ${config[opt]}`;
}
} else {
cmd += ` --${opt.replace('_', '-')} ${options[opt]}`;
}
}
}
cmd += ` --rm=${options.rm ? 'true' : 'false'}`;
cmd += ` -t \"${options.image}${options.tag ? `:${options.tag}` : ''}\"`;
if (options.cwd) {
// custom command for content option0
if (options.file == null) {
options.file = path.resolve(options.cwd, 'Dockerfile');
}
}
if (options.content != null) {
this.log({
message: "Building from text: Docker won't have a context. ADD/COPY not working",
level: 'WARN',
module: 'nikita/docker/build'
})),
'--rm=' + (config.rm ? 'true' : 'false'),
'-t ' + utils.string.escapeshellarg(config.image + (config.tag ? `:${config.tag}` : '')),
(config.content != null ? (log({
message: "Building from text: Docker won't have a context. ADD/COPY not working",
level: 'WARN'
}),
config.content != null ? `- <<DOCKERFILE\n${config.content}\nDOCKERFILE` : void 0) : config.file != null ? (log({
message: `Building from Dockerfile: \"${config.file}\"`,
level: 'INFO'
}),
`-f ${config.file} ${config.cwd}`) : (log({
message: "Building from CWD",
level: 'INFO'
}),
'.'))
].join(' '),
cwd: config.cwd
})));
// Get the content of the Dockerfile
if (config.content) {
await this.file({
content: config.content,
source: source,
target: function({content}) {
return config.content = content;
},
from: config.from,
to: config.to,
match: config.match,
replace: config.replace,
append: config.append,
before: config.before,
write: config.write
});
if (options.content != null) {
cmd += ` - <<DOCKERFILE\n${options.content}\nDOCKERFILE`;
}
} else if (options.file != null) {
this.log({
message: `Building from Dockerfile: \"${options.file}\"`,
level: 'INFO',
module: 'nikita/docker/build'
});
cmd += ` -f ${options.file} ${options.cwd}`;
} else {
this.log({
message: "Building from CWD",
level: 'INFO',
module: 'nikita/docker/build'
// Read Dockerfile if necessary to count steps
log({
message: `Reading Dockerfile from : ${config.file}`,
level: 'INFO'
});
cmd += ' .';
({
data: config.content
} = (await this.fs.base.readFile({
target: config.file,
encoding: 'utf8'
})));
}
this.file({
if: options.content,
content: options.content,
source: source,
target: function(content) {
return options.content = content;
},
from: options.from,
to: options.to,
match: options.match,
replace: options.replace,
append: options.append,
before: options.before,
write: options.write
});
this.call({ // Read Dockerfile if necessary to count steps
unless: options.content
}, function(_, callback) {
this.log({
message: `Reading Dockerfile from : ${options.file}`,
level: 'INFO',
module: 'nikita/lib/build'
});
return this.fs.readFile({
ssh: options.ssh,
target: options.file,
encoding: 'utf8'
}, function(err, {data}) {
if (err) {
return callback(err);
}
options.content = data;
return callback();
});
});
this.call(function() { // Count steps
var len3, line, m, ref4, ref5, ref6, results;
ref4 = string.lines(options.content);
results = [];
for (m = 0, len3 = ref4.length; m < len3; m++) {
line = ref4[m];
if (ref5 = (ref6 = /^(.*?)\s/.exec(line)) != null ? ref6[1] : void 0, indexOf.call(dockerfile_cmds, ref5) >= 0) {
results.push(number_of_step++);
} else {
results.push(void 0);
}
ref = utils.string.lines(config.content);
// Count steps
for (i = 0, len = ref.length; i < len; i++) {
line = ref[i];
if (ref1 = (ref2 = /^(.*?)\s/.exec(line)) != null ? ref2[1] : void 0, indexOf.call(dockerfile_commands, ref1) >= 0) {
number_of_step++;
}
return results;
});
this.system.execute({
cmd: docker.wrap(options, cmd),
cwd: options.cwd
}, function(err, {stdout, stderr}) {
var image_id, line, lines, number_of_cache;
if (err) {
throw err;
}
image_id = null;
// Count cache
lines = utils.string.lines(stdout);
number_of_cache = 0;
for (k in lines) {
line = lines[k];
if (line.indexOf('Using cache') !== -1) {
number_of_cache = number_of_cache + 1;
}
image_id = null;
// lines = string.lines stderr
lines = string.lines(stdout);
number_of_cache = 0;
for (k in lines) {
line = lines[k];
if (line.indexOf('Using cache') !== -1) {
number_of_cache = number_of_cache + 1;
}
if (line.indexOf('Successfully built') !== -1) {
image_id = line.split(' ').pop().toString();
}
if (line.indexOf('Successfully built') !== -1) {
image_id = line.split(' ').pop().toString();
}
return userargs = {
status: number_of_step !== number_of_cache,
image: image_id,
stdout: stdout,
stderr: stderr
};
}
userargs = {
status: number_of_step !== number_of_cache,
image: image_id,
stdout: stdout,
stderr: stderr
};
log(userargs.status ? {
message: `New image id ${userargs[1]}`,
level: 'INFO',
module: 'nikita/lib/docker/build'
} : {
message: `Identical image id ${userargs[1]}`,
level: 'INFO',
module: 'nikita/lib/docker/build'
});
return this.next(function(err) {
if (err) {
return callback(err);
}
this.log(userargs.status ? {
message: `New image id ${userargs[1]}`,
level: 'INFO',
module: 'nikita/lib/docker/build'
} : {
message: `Identical image id ${userargs[1]}`,
level: 'INFO',
module: 'nikita/lib/docker/build'
});
return callback(null, userargs);
});
return userargs;
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
},
hooks: {
on_action: on_action
}
};
string = require('@nikitajs/core/lib/misc/string');
// ## Errors
errors = {
NIKITA_DOCKER_BUILD_CONTENT_FILE_REQUIRED: function() {
return utils.error('NIKITA_DOCKER_BUILD_CONTENT_FILE_REQUIRED', ['could not build the container,', 'one of the `content` or `file` config property must be provided']);
}
};
// ## Dependencies
utils = require('./utils');
path = require('path');
util = require('util');

@@ -7,34 +7,4 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `machine` (string)
// Name of the docker-machine, required if using docker-machine.
// * `content` (string)
// The content of the docker-compose.yml to write if not exist.
// * `eof` (string)
// Inherited from nikita.file use when writing docker-compose.yml file.
// * `backup` (string|boolean)
// Create a backup, append a provided string to the filename extension or a
// timestamp if value is not a string, only apply if the target file exists and
// is modified.
// * `detached` (boolean)
// Run Containers in detached mode. Default to true.
// * `force` (boolean)
// Force to re-create the containers if the config and image have not changed
// Default to false
// * `services` (string|array)
// Specify specific services to create.
// * `target` (string)
// The docker-compose.yml absolute's file's path, required if no content is
// specified.
// * `code` (int|array)
// Expected code(s) returned by the command, int or array of int, default to 0.
// * `code_skipped`
// Expected code(s) returned by the command if it has no effect, executed will
// not be incremented, int or array of int.
// ## Callback parameters
// * `err`

@@ -49,121 +19,159 @@ // Error object if any.

// ## Source Code
var docker, path;
// ## Schema
var handler, path, schema, utils;
module.exports = function({options}) {
var clean_target, cmd, cmd_ps, cmd_up, k, ref, services, source_dir, v;
this.log({
message: "Entering Docker Compose",
level: 'DEBUG',
module: 'nikita/lib/docker/compose/up'
});
// Global options
if (options.docker == null) {
options.docker = {};
schema = {
type: 'object',
properties: {
'content': {
type: 'object',
description: `The content of the docker-compose.yml to write if not exist.`
},
'eof': {
type: 'boolean',
default: true,
description: `Inherited from nikita.file use when writing docker-compose.yml file.`
},
'backup': {
oneOf: [
{
type: 'string'
},
{
type: 'boolean'
}
],
default: false,
description: `Create a backup, append a provided string to the filename extension or
a timestamp if value is not a string, only apply if the target file
exists and is modified.`
},
'detached': {
type: 'boolean',
default: true,
description: `Run containers in detached mode.`
},
'force': {
type: 'boolean',
default: false,
description: `Force to re-create the containers if the config and image have not
changed.`
},
'services': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Specify specific services to create.`
},
'target': {
type: 'string',
description: `The docker-compose.yml absolute's file's path, required if no content
is specified.`
}
}
ref = options.docker;
};
// ## Handler
handler = async function({
config,
tools: {find, log}
}) {
var clean_target, containers, k, ref, status, stdout, v;
// Global config
config.docker = (await find(function({
config: {docker}
}) {
return docker;
}));
ref = config.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
if (config[k] == null) {
config[k] = v;
}
}
if ((options.target == null) && (options.content == null)) {
if ((config.target == null) && (config.content == null)) {
// Validate parameters
throw Error('Missing docker-compose content or target');
}
if (options.content && (options.target == null)) {
if (options.target == null) {
options.target = `/tmp/nikita_docker_compose_${Date.now()}/docker-compose.yml`;
if (config.content && (config.target == null)) {
if (config.target == null) {
config.target = `/tmp/nikita_docker_compose_${Date.now()}/docker-compose.yml`;
}
clean_target = true;
}
if (options.detached == null) {
options.detached = true;
if (config.recreate == null) {
config.recreate = false; // TODO: move to schema
}
if (options.force == null) {
options.force = false;
if (config.services == null) {
config.services = [];
}
if (options.recreate == null) {
options.recreate = false;
if (!Array.isArray(config.services)) {
config.services = [config.services];
}
if (options.services == null) {
options.services = [];
// services = config.services.join ' '
await this.file.yaml({
if: config.content != null,
eof: config.eof,
backup: config.backup,
target: config.target,
content: config.content
});
({status, stdout} = (await this.docker.tools.execute({
command: `--file ${config.target} ps -q | xargs docker ${utils.opts(config)} inspect`,
compose: true,
cwd: config.cwd,
uid: config.uid,
code_skipped: 123,
stdout_log: false,
metadata: {
shy: true
}
})));
if (!status) {
status = true;
} else {
containers = JSON.parse(stdout);
status = containers.some(function(container) {
return !container.State.Running;
});
if (status) {
log("Docker created, need start");
}
}
if (!Array.isArray(options.services)) {
options.services = [options.services];
try {
return (await this.docker.tools.execute({
if: config.force || status,
command: [`--file ${config.target} up`, config.detached ? '-d' : void 0, config.force ? '--force-recreate' : void 0, ...config.services].join(' '),
compose: true,
cwd: path.dirname(config.target),
uid: config.uid
}));
} finally {
await this.fs.remove({
if: clean_target,
target: config.target
});
}
services = options.services.join(' ');
// Construct exec command
cmd = ` --file ${options.target}`;
cmd_ps = `${cmd} ps -q | xargs docker ${docker.opts(options)} inspect`;
cmd_up = `${cmd} up`;
if (options.detached) {
cmd_up += ' -d ';
};
// ## Exports
module.exports = {
handler: handler,
metadata: {
schema: schema
}
if (options.force) {
cmd_up += ' --force-recreate ';
}
cmd_up += ` ${services}`;
source_dir = `${path.dirname(options.target)}`;
if (options.eof == null) {
options.eof = true;
}
if (options.backup == null) {
options.backup = false;
}
options.compose = true;
this.call(function() {
return this.file.yaml({
if: options.content != null,
eof: options.eof,
backup: options.backup,
target: options.target,
content: options.content
});
});
this.call(function(_, callback) {
return this.system.execute({
cmd: docker.wrap(options, cmd_ps),
cwd: options.cwd,
uid: options.uid,
code_skipped: 123,
stdout_log: false
}, function(err, {status, stdout}) {
var containers;
if (err) {
return callback(err);
}
if (!status) {
return callback(null, true);
}
containers = JSON.parse(stdout);
status = containers.some(function(container) {
return !container.State.Running;
});
if (status) {
this.log("Docker created, need start");
}
return callback(null, status);
});
});
this.system.execute({
if: function() {
return options.force || this.status();
},
cwd: source_dir,
uid: options.uid,
cmd: docker.wrap(options, cmd_up)
}, docker.callback);
return this.system.remove({
if: clean_target,
target: options.target,
always: true // Not yet implemented
});
};
// ## Dependencies
utils = require('../utils');
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
path = require('path');

@@ -16,23 +16,10 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `machine` (string)
// Name of the docker-machine, required if using docker-machine or boot2docker.
// * `source` (string)
// The path to upload or the container followed by the path to download.
// * `target` (string)
// The path to download or the container followed by the path to upload.
// ## Uploading a file
// ```javascript
// require('nikita')
// .docker({
// ```js
// const {status} = await nikita.docker.cp({
// source: readable_stream or '/path/to/source'
// target: 'my_container:/path/to/target'
// }, function(err, {status}){
// console.log( err ? err.message : 'Container copied' + status)
// )
// })
// console.info(`Container was copied: ${status}`)
// ```

@@ -42,49 +29,41 @@

// ```javascript
// require('nikita')
// .docker({
// ```js
// const {status} = await nikita.docker.cp({
// source: 'my_container:/path/to/source',
// target: writable_stream or '/path/to/target'
// }, function(err, status){
// console.log( err ? err.message : 'Container copied: ' + status);
// });
// })
// console.info(`Container was copied: ${status}`)
// ```
// ## Source Code
var docker, misc, path;
// ## Schema
var handler, path, schema, utils;
module.exports = function({options}) {
var _, k, ref, source_container, source_mkdir, source_path, ssh, target_container, target_mkdir, target_path, v;
this.log({
message: "Entering Docker cp",
level: 'DEBUG',
module: 'nikita/lib/docker/cp'
});
// SSH connection
ssh = this.ssh(options.ssh);
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'source': {
type: 'string',
description: `The path to upload or the container followed by the path to download.`
},
'target': {
type: 'string',
description: `The path to download or the container followed by the path to upload.`
}
}
if (!options.source) {
// Validate parameters
throw Error('Missing option "source"');
}
if (!options.target) {
throw Error('Missing option "target"');
}
[_, source_container, source_path] = /(.*:)?(.*)/.exec(options.source);
[_, target_container, target_path] = /(.*:)?(.*)/.exec(options.target);
},
required: ['source', 'target']
};
// ## Handler
handler = async function({config}) {
var _, err, source_container, source_mkdir, source_path, stats, target_container, target_mkdir, target_path;
[_, source_container, source_path] = /(.*:)?(.*)/.exec(config.source);
[_, target_container, target_path] = /(.*:)?(.*)/.exec(config.target);
if (source_container && target_container) {
throw Error('Incompatible source and target options');
throw Error('Incompatible source and target config');
}
if (!source_container && !target_container) {
throw Error('Incompatible source and target options');
throw Error('Incompatible source and target config');
}

@@ -94,74 +73,68 @@ source_mkdir = false;

// Source is on the host, normalize path
this.call(function({}, callback) {
if (source_container) {
return callback();
}
if (!source_container) {
if (/\/$/.test(source_path)) {
source_path = `${source_path}/${path.basename(target_path)}`;
return callback();
}
return this.fs.stat({
ssh: options.ssh,
target: source_path
}, function(err, {stats}) {
if (err && err.code !== 'ENOENT') {
return callback(err);
try {
({stats} = (await this.fs.base.stat({
ssh: config.ssh,
target: source_path
})));
if (utils.stats.isDirectory(stats.mode)) {
source_path = `${source_path}/${path.basename(target_path)}`;
}
if ((err != null ? err.code : void 0) === 'ENOENT') {
// TODO wdavidw: seems like a mistake to me, we shall have source_mkdir instead
return target_mkdir = true && callback();
} catch (error) {
err = error;
if (err.code !== 'NIKITA_FS_STAT_TARGET_ENOENT') {
throw err;
}
if (misc.stats.isDirectory(stats.mode)) {
source_path = `${source_path}/${path.basename(target_path)}`;
}
return callback();
});
});
this.system.mkdir({
// TODO wdavidw: seems like a mistake to me, we shall have source_mkdir instead
target_mkdir = true;
}
}
await this.fs.mkdir({
target: source_path,
if: function() {
return source_mkdir;
}
if: source_mkdir
});
// Destination is on the host
this.call(function({}, callback) {
if (target_container) {
return callback();
}
if (!target_container) {
if (/\/$/.test(target_path)) {
target_path = `${target_path}/${path.basename(target_path)}`;
return callback();
}
return this.fs.stat({
ssh: options.ssh,
target: target_path
}, function(err, {stats}) {
if (err && err.code !== 'ENOENT') {
return callback(err);
try {
({stats} = (await this.fs.base.stat({
target: target_path
})));
if (utils.stats.isDirectory(stats.mode)) {
target_path = `${target_path}/${path.basename(target_path)}`;
}
if ((err != null ? err.code : void 0) === 'ENOENT') {
return target_mkdir = true && callback();
} catch (error) {
err = error;
if (err.code !== 'NIKITA_FS_STAT_TARGET_ENOENT') {
throw err;
}
if (misc.stats.isDirectory(stats.mode)) {
target_path = `${target_path}/${path.basename(target_path)}`;
}
return callback();
});
});
this.system.mkdir({
target_mkdir = true;
}
}
await this.fs.base.mkdir({
target: target_path,
if: function() {
return target_mkdir;
}
if: target_mkdir
});
return this.system.execute({
cmd: docker.wrap(options, `cp ${options.source} ${options.target}`)
}, docker.callback);
return (await this.docker.tools.execute({
command: `cp ${config.source} ${config.target}`
}));
};
// ## Modules Dependencies
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
};
// ## Dependencies
path = require('path');
docker = require('@nikitajs/core/lib/misc/docker');
misc = require('@nikitajs/core/lib/misc');
utils = require('./utils');

@@ -6,21 +6,4 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `container` (string)
// Name/ID of the container, required.
// * `code_skipped` (int | array)
// The exit code(s) to skip.
// * `machine` (string)
// Name of the docker-machine, required using docker-machine.
// * `service` (boolean)
// if true, run container as a service, else run as a command, true by default.
// * `uid` (name | uid)
// Username or uid.
// * `gid` (name | gid)
// Groupname or gid.
// ## Callback parameters
// * `err`

@@ -37,76 +20,106 @@ // Error object if any.

// ```javascript
// require('nikita')
// .docker.exec({
// ```js
// const {status} = await nikita.docker.exec({
// container: 'myContainer',
// cmd: '/bin/bash -c "echo toto"'
// }, function(err, {status}){
// console.log( err ? err.message : 'Command executed: ' + status);
// });
// command: '/bin/bash -c "echo toto"'
// })
// console.info(`Command was executed: ${status}`)
// ```
// ## Source Code
var docker;
// ## Schema
var handler, schema;
module.exports = function({options}, callback) {
var cmd, k, ref, v;
this.log({
message: "Entering Docker exec",
level: 'DEBUG',
module: 'nikita/lib/docker/exec'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'container': {
type: 'string',
description: `Name/ID of the container`
},
'code_skipped': {
oneOf: [
{
type: 'integer'
},
{
type: 'array',
items: {
type: 'integer'
}
}
],
description: `The exit code(s) to skip.`
},
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'service': {
type: 'boolean',
default: false,
description: `If true, run container as a service, else run as a command, true by
default.`
},
'uid': {
oneOf: [
{
type: 'integer'
},
{
type: 'string'
}
],
description: `Username or uid.`
},
'gid': {
oneOf: [
{
type: 'integer'
},
{
type: 'string'
}
],
description: `Groupname or gid.`
}
},
required: ['container', 'command']
};
// ## Handler
handler = async function({
config,
tools: {log}
}) {
var command;
if (config.service == null) {
config.service = false;
}
if (options.container == null) {
// Validate parameters
throw Error('Missing container');
}
if (options.cmd == null) {
throw Error('Missing cmd');
}
if (options.service == null) {
options.service = false;
}
// Construct exec command
cmd = 'exec';
if (options.uid != null) {
cmd += ` -u ${options.uid}`;
if (options.gid != null) {
cmd += `:${options.gid}`;
command = 'exec';
if (config.uid != null) {
command += ` -u ${config.uid}`;
if (config.gid != null) {
command += `:${config.gid}`;
}
} else if (options.gid != null) {
this.log({
message: 'options.gid ignored unless options.uid is provided',
level: 'WARN',
module: 'nikita/lib/docker/exec'
} else if (config.gid != null) {
log({
message: 'config.gid ignored unless config.uid is provided',
level: 'WARN'
});
}
cmd += ` ${options.container} ${options.cmd}`;
delete options.cmd;
return this.system.execute({
cmd: docker.wrap(options, cmd),
code_skipped: options.code_skipped
}, function() { // Note: There is no way to pass additionnal arguments in sync mode without
// a callback, or we would have ', docker.callback' as next line
var e;
try {
docker.callback.call(null, ...arguments);
} catch (error) {
e = error;
arguments[0] = e;
}
return callback(...arguments);
});
command += ` ${config.container} ${config.command}`;
// delete config.command
return (await this.docker.tools.execute({
command: command,
code_skipped: config.code_skipped
}));
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
};

@@ -9,15 +9,4 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `container` (string)
// Name/ID of the container, required.
// * `machine` (string)
// Name of the docker-machine, required if using docker-machine.
// * `signal` (int|string)
// Use a specified signal. SIGKILL by default.
// ## Callback parameters
// * `err`

@@ -30,55 +19,60 @@ // Error object if any.

// ```javascript
// require('nikita')
// .docker.kill({
// ```js
// const {status} = await nikita.docker.kill({
// container: 'toto',
// signal: 9
// }, function(err, status){
// console.log( err ? err.message : 'Container killed: ' + status);
// })
// console.info(`Container was killed: ${status}`)
// ```
// ## Source Code
var docker;
// ## Schema
var handler, schema;
module.exports = function({options}) {
var cmd, k, ref, v;
this.log({
message: "Entering Docker kill",
level: 'DEBUG',
module: 'nikita/lib/docker/kill'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'container': {
type: 'string',
description: `Name/ID of the container.`
},
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'signal': {
oneOf: [
{
type: 'integer'
},
{
type: 'string'
}
],
description: `Use a specified signal. SIGKILL by default.`
}
}
if (options.container == null) {
// Validate parameters
return callback(Error('Missing container parameter'));
}
cmd = 'kill';
if (options.signal != null) {
cmd += ` -s ${options.signal}`;
}
cmd += ` ${options.container}`;
this.system.execute({
cmd: docker.wrap(options, `ps | grep '${options.container}' | grep 'Up'`),
},
required: ['container']
};
// ## Handler
handler = async function({config}) {
var status;
({status} = (await this.docker.tools.execute({
command: `ps | egrep ' ${config.container}$' | grep 'Up'`,
code_skipped: 1
}, docker.callback);
return this.system.execute({
})));
return (await this.docker.tools.execute({
if: function() {
return this.status(-1);
return status;
},
cmd: docker.wrap(options, cmd)
}, docker.callback);
command: ['kill', config.signal != null ? `-s ${config.signal}` : void 0, `${config.container}`].join(' ')
}));
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
};

@@ -6,18 +6,4 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `machine` (string)
// Name of the docker-machine, required if using docker-machine.
// * `input` (string)
// TAR archive file to read from.
// * `source` (string)
// Alias for the "input" option.
// * `checksum` (string)
// If provided, will check if attached input archive to checksum already exist,
// not native to docker but implemented to get better performance.
// ## Callback parameters
// * `err`

@@ -34,42 +20,50 @@ // Error object if any.

// ```javascript
// require('nikita')
// .docker.load({
// ```js
// const {status} = await nikita.docker.load({
// image: 'nikita/load_test:latest',
// machine: machine,
// source: source + "/nikita_load.tar"
// }, function(err, {status}) {
// console.log( err ? err.message : 'Container loaded: ' + status);
// })
// console.info(`Image was loaded: ${status}`);
// ```
// ## Source Code
var docker, string, util;
// ## Schema
var handler, schema, utils;
module.exports = function({options}, callback) {
var cmd, images, k, ref, v;
this.log({
message: "Entering Docker load",
level: 'DEBUG',
module: 'nikita/lib/docker/load'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'checksum': {
type: 'string',
description: `If provided, will check if attached input archive to checksum already
exist, not native to docker but implemented to get better performance.`
},
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'input': {
type: 'string',
description: `TAR archive file to read from.`
},
'source': {
type: 'string',
description: `Alias for the "input" option.`
}
}
};
// ## Handler
handler = async function({
config,
tools: {log}
}) {
var command, i, image, images, infos, j, k, len, len1, new_image, new_images, new_k, ref, ref1, status, stderr, stdout;
// Validate parameters
if (options.input == null) {
options.input = options.source;
if (config.input == null) {
config.input = config.source;
}
if (options.input == null) {
return callback(Error('Missing input parameter'));
if (config.input == null) {
throw Error('Missing input parameter');
}
cmd = `load -i ${options.input}`;
command = `load -i ${config.input}`;
// need to records the list of image to see if status is modified or not after load

@@ -79,122 +73,111 @@ // for this we print the existing images as REPOSITORY:TAG:IMAGE

images = {};
delete options.cmd;
this.log({
delete config.command;
log({
message: 'Storing previous state of image',
level: 'INFO',
module: 'nikita/lib/docker/load'
level: 'INFO'
});
if (options.checksum == null) {
this.log({
if (config.checksum == null) {
log({
message: 'No checksum provided',
level: 'INFO',
module: 'nikita/lib/docker/load'
level: 'INFO'
});
}
if (options.checksum) {
this.log({
message: `Checksum provided :${options.checksum}`,
level: 'INFO',
module: 'nikita/lib/docker/load'
if (config.checksum) {
log({
message: `Checksum provided :${config.checksum}`,
level: 'INFO'
});
}
if (options.checksum == null) {
options.checksum = '';
if (config.checksum == null) {
config.checksum = '';
}
return this.system.execute({
cmd: docker.wrap(options, " images | grep -v '<none>' | awk '{ print $1\":\"$2\":\"$3 }'")
}, (err, {stdout}) => {
var i, image, infos, len, ref1;
if (err) {
return callback(err);
}
// skip header line, wi skip it here instead of in the grep to have
// an array with at least one not empty line
if (string.lines(stdout).length > 1) {
ref1 = string.lines(stdout);
for (i = 0, len = ref1.length; i < len; i++) {
image = ref1[i];
image = image.trim();
if (image !== '') {
infos = image.split(':');
if (infos[2] === options.checksum) {
// if image is here we skip
this.log({
message: `Image already exist checksum :${options.checksum}, repo:tag ${`${infos[0]}:${infos[1]}`}`,
level: 'INFO',
module: 'nikita/lib/docker/load'
});
}
if (infos[2] === options.checksum) {
return callback(null, false);
}
images[`${infos[0]}:${infos[1]}`] = `${infos[2]}`;
({stdout} = (await this.docker.tools.execute({
command: "images | grep -v '<none>' | awk '{ print $1\":\"$2\":\"$3 }'"
})));
// skip header line, wi skip it here instead of in the grep to have
// an array with at least one not empty line
if (utils.string.lines(stdout).length > 1) {
ref = utils.string.lines(stdout);
for (i = 0, len = ref.length; i < len; i++) {
image = ref[i];
image = image.trim();
if (image !== '') {
infos = image.split(':');
if (infos[2] === config.checksum) {
// if image is here we skip
log({
message: `Image already exist checksum :${config.checksum}, repo:tag \"${infos[0]}:${infos[1]}\"`,
level: 'INFO'
});
}
if (infos[2] === config.checksum) {
return false;
}
images[`${infos[0]}:${infos[1]}`] = `${infos[2]}`;
}
}
this.log({
message: `Start Loading ${options.input} `,
level: 'INFO',
module: 'nikita/lib/docker/load'
});
this.system.execute({
cmd: docker.wrap(options, cmd)
});
return this.system.execute({
cmd: docker.wrap(options, 'images | grep -v \'<none>\' | awk \'{ print $1":"$2":"$3 }\'')
}, function(err, {stdout, stderr}) {
var j, len1, new_image, new_images, new_k, ref2, status;
if (err) {
return callback(err);
}
log({
message: `Start Loading ${config.input} `,
level: 'INFO'
});
await this.docker.tools.execute({
command: command
});
({stdout, stderr} = (await this.docker.tools.execute({
command: 'images | grep -v \'<none>\' | awk \'{ print $1":"$2":"$3 }\''
})));
new_images = {};
status = false;
log({
message: 'Comparing new images',
level: 'INFO'
});
if (utils.string.lines(stdout).length > 1) {
ref1 = utils.string.lines(stdout.toString());
for (j = 0, len1 = ref1.length; j < len1; j++) {
image = ref1[j];
if (image !== '') {
infos = image.split(':');
new_images[`${infos[0]}:${infos[1]}`] = `${infos[2]}`;
}
new_images = {};
status = false;
this.log({
message: 'Comparing new images',
level: 'INFO',
module: 'nikita/lib/docker/load'
});
if (string.lines(stdout).length > 1) {
ref2 = string.lines(stdout.toString());
for (j = 0, len1 = ref2.length; j < len1; j++) {
image = ref2[j];
if (image !== '') {
infos = image.split(':');
new_images[`${infos[0]}:${infos[1]}`] = `${infos[2]}`;
}
}
}
for (new_k in new_images) {
new_image = new_images[new_k];
if (images[new_k] == null) {
}
}
for (new_k in new_images) {
new_image = new_images[new_k];
if (images[new_k] == null) {
status = true;
break;
} else {
for (k in images) {
image = images[k];
if (image !== new_image && new_k === k) {
status = true;
log({
message: 'Identical images',
level: 'INFO'
});
break;
} else {
for (k in images) {
image = images[k];
if (image !== new_image && new_k === k) {
status = true;
this.log({
message: 'Identical images',
level: 'INFO',
module: 'nikita/lib/docker/load'
});
break;
}
}
}
}
return callback(err, {
status: status,
stdout: stdout,
stderr: stderr
});
});
});
}
}
return {
status: status,
stdout: stdout,
stderr: stderr
};
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
string = require('@nikitajs/core/lib/misc/string');
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
};
util = require('util');
// ## Dependencies
utils = require('./utils');

@@ -6,79 +6,64 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `registry` (string)
// Address of the registry server. "https://index.docker.io/v1/" by default
// * `machine` (string)
// Name of the docker-machine, require if using docker-machine
// * `email` (string)
// Email
// * `user` (string)
// Username
// * `password` (string)
// Remove intermediate containers after build. Default to false
// * `cwd` (string)
// change the working directory for the build.
// ## Callback parameters
// * `err`
// Error object if any.
// * `status`
// True when the command was executed successfully.
// True when the command was executed successfully.
// * `stdout`
// Stdout value(s) unless `stdout` option is provided.
// Stdout value(s) unless `stdout` option is provided.
// * `stderr`
// Stderr value(s) unless `stderr` option is provided.
// Stderr value(s) unless `stderr` option is provided.
// ## Source Code
var docker, path, util;
// ## Schema
var handler, schema, utils;
module.exports = function({options}, callback) {
var cmd, i, k, len, opt, ref, ref1, v;
this.log({
message: "Entering Docker login",
level: 'DEBUG',
module: 'nikita/lib/docker/login'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'email': {
type: 'string',
description: `User email.`
},
'password': {
type: 'string',
description: `User password.`
},
'user': {
type: 'string',
description: `Username of the user.`
}
}
if (options.image == null) {
// Validate parameters and madatory conditions
return callback(Error('Missing image parameter'));
}
if ((options.content != null) && (options.dockerfile != null)) {
return callback(Error('Can not build from Dockerfile and content'));
}
cmd = 'login';
ref1 = ['email', 'user', 'password'];
for (i = 0, len = ref1.length; i < len; i++) {
opt = ref1[i];
if (options[opt] != null) {
cmd += ` -${opt.charAt(0)} ${options[opt]}`;
}
}
if (options.registry != null) {
cmd += ` \"${options.registry}\"`;
}
return this.system.execute({
cmd: docker.wrap(options, cmd)
}, docker.callback);
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
// ## Handler
handler = async function({config}) {
return (await this.docker.tools.execute({
command: [
'login',
...(['email',
'user',
'password'].filter(function(opt) {
return config[opt] != null;
}).map(function(opt) {
return `-${opt.charAt(0)} ${config[opt]}`;
})),
config.registry != null ? `${utils.string.escapeshellarg(config.registry)}` : void 0
].join(' ')
}));
};
path = require('path');
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
};
util = require('util');
// ## Dependencies
utils = require('./utils');

@@ -6,18 +6,4 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `registry` (string)
// Address of the registry server, default to "https://index.docker.io/v1/".
// * `machine` (string)
// Name of the docker-machine, required if using docker-machine.
// * `code` (int|array)
// Expected code(s) returned by the command, int or array of int, default to 0.
// * `code_skipped`
// Expected code(s) returned by the command if it has no effect, executed will
// not be incremented, int or array of int.
// ## Callback parameters
// * `err`

@@ -28,40 +14,45 @@ // Error object if any.

// ## Source Code
var docker, util;
// ## Schema
var handler, schema, utils;
module.exports = function({options}, callback) {
var cmd, k, ref, v;
this.log({
message: "Entering Docker logout",
level: 'DEBUG',
module: 'nikita/lib/docker/logout'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'registry': {
type: 'string',
description: `Address of the registry server, default to "https://index.docker.io/v1/".`
}
}
if (options.container == null) {
};
// ## Handler
handler = async function({config}) {
var command;
if (config.container == null) {
// Validate parameters
return callback(Error('Missing container parameter'));
}
// rm is false by default only if options.service is true
cmd = 'logout';
if (options.registry != null) {
cmd += ` \"${options.registry}\"`;
// rm is false by default only if config.service is true
command = 'logout';
if (config.registry != null) {
command += ` \"${config.registry}\"`;
}
return this.system.execute({
cmd: docker.wrap(options, cmd)
}, docker.callback);
return (await this.execute({
command: utils.wrap(config, command)
}, docker.callback));
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
};
util = require('util');
// ## Dependencies
utils = require('./utils');

@@ -6,18 +6,4 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `container` (string)
// Name/ID of the container, required.
// * `machine` (string)
// Name of the docker-machine, required.
// * `code` (int|array)
// Expected code(s) returned by the command, int or array of int, default to 0.
// * `code_skipped`
// Expected code(s) returned by the command if it has no effect, executed will
// not be incremented, int or array of int.
// ## Callback parameters
// * `err`

@@ -30,44 +16,40 @@ // Error object if any.

// ```javascript
// require('nikita')
// .docker.pause({
// ```js
// const {status} = await nikita.docker.pause({
// container: 'toto'
// }, function(err, {status}){
// console.log( err ? err.message : 'Container paused: ' + status);
// })
// console.info(`Container was paused: ${status}`)
// ```
// ## Source Code
var docker, util;
// ## Schema
var handler, schema;
module.exports = function({options}, callback) {
var k, ref, v;
this.log({
message: "Entering Docker pause",
level: 'DEBUG',
module: 'nikita/lib/docker/pause'
});
// Global parameters
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'container': {
type: 'string',
description: `Name/ID of the container.`
},
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
}
}
if (options.container == null) {
// Validate parameters
return callback(Error('Missing container parameter'));
}
return this.system.execute({
cmd: docker.wrap(options, `pause ${options.container}`)
}, docker.callback);
},
required: ['container']
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
// ## Handler
handler = async function({config}) {
return (await this.docker.tools.execute({
command: `pause ${config.container}`
}));
};
util = require('util');
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
};
// Generated by CoffeeScript 2.5.1
// # `nikita.docker.pull`
// Pull a container
// Pull an image or a repository from a registry.
// ## Options
// ## Output
// * `tag` (string)
// Name of the tag to pull.
// * `version` (string)
// Version of the tag to control. Default to `latest`.
// * `code_skipped` (string)
// The exit code to skip if different from 0.
// * `all` (Boolean)
// Download all tagged images in the repository. Default to false.
// ## Callback parameters
// * `err`

@@ -30,67 +19,69 @@ // Error object if any.

// 1- builds an image from dockerfile without any resourcess
// ```javascript
// require('nikita')
// .docker.pull({
// tag: 'postgresql'
// }, function(err, {status}){
// console.log( err ? err.message : 'Container pulled: ' + status);
// ```js
// const {status} = await nikita.docker.pull({
// image: 'postgresql'
// })
// console.info(`Image was pulled: ${status}`)
// ```
// ## Source Code
var docker, util;
// ## Schema
var handler, schema;
module.exports = function({options}, callback) {
var cmd, cmd_images, k, ref, v, version;
this.log({
message: "Entering Docker pull",
level: 'DEBUG',
module: 'nikita/lib/docker/pull'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'all': {
type: 'boolean',
default: false,
description: `Pull all tagged images in the repository.`
},
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'image': {
type: 'string',
description: `Name of an image or a repository to pull. It can contain \`tag\`.`
},
'tag': {
type: 'string',
description: `Specific image tag within a repository to pull. Default to \`latest\`.`
}
}
// Validate parameters
version = options.version || options.tag.split(':')[1] || 'latest';
delete options.version; // present in misc.docker.options, will probably disappear at some point
if (options.all == null) {
options.all = false;
};
// ## Handler
handler = async function({config}) {
var name, status, tag;
// Validate
[name, tag] = config.image.split(':');
config.image = name;
if (tag && config.tag) {
// it can be later changed to give a preference instead of error
throw Error('Tag must be specified either in the image or in the tag config');
}
cmd_images = 'images';
cmd_images += ` | grep '${options.tag}'`;
if (!options.all) {
cmd_images += ` | grep '${version}'`;
if (config.tag == null) {
config.tag = tag || 'latest';
}
if (options.tag == null) {
throw Error('Missing Tag Name');
}
// rm is false by default only if options.service is true
cmd = 'pull';
cmd += options.all ? ` -a ${options.tag}` : ` ${options.tag}:${version}`;
this.system.execute({
cmd: docker.wrap(options, cmd_images),
// Check if exist
({status} = (await this.docker.tools.execute({
// avoid checking when all config is true,
// because there is no native way to list all existing tags on the registry
unless: config.all,
command: ['images', `| grep '${config.image}'`, `| grep '${config.tag}'`].join(' '),
code_skipped: 1
});
return this.system.execute({
unless: function() {
return this.status(-1);
},
cmd: docker.wrap(options, cmd),
code_skipped: options.code_skipped
}, callback);
})));
// Pull image
return (await this.docker.tools.execute({
unless: status,
command: ['pull', config.all ? `-a ${config.image}` : `${config.image}:${config.tag}`].join(' ')
}));
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
util = require('util');
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
};
// Generated by CoffeeScript 2.5.1
// Registration of `nikita.docker` actions
var registry;
//# Dependency
var register;
require('@nikitajs/file/lib/register');
({register} = require('@nikitajs/core/lib/registry'));
// require '@nikitajs/network/lib/register'
registry = require('@nikitajs/core/lib/registry');
//# Action registration
register(module.exports = {
module.exports = {
docker: {
build: '@nikitajs/docker/lib/build',
checksum: '@nikitajs/docker/lib/checksum',
compose: {

@@ -20,2 +19,3 @@ '': '@nikitajs/docker/lib/compose',

exec: '@nikitajs/docker/lib/exec',
inspect: '@nikitajs/docker/lib/inspect',
kill: '@nikitajs/docker/lib/kill',

@@ -30,7 +30,12 @@ load: '@nikitajs/docker/lib/load',

save: '@nikitajs/docker/lib/save',
service: '@nikitajs/docker/lib/service',
// service: '@nikitajs/docker/lib/service'
start: '@nikitajs/docker/lib/start',
status: '@nikitajs/docker/lib/status',
stop: '@nikitajs/docker/lib/stop',
unpause: '@nikitajs/docker/lib/unpause',
tools: {
checksum: '@nikitajs/docker/lib/tools/checksum',
execute: '@nikitajs/docker/lib/tools/execute',
service: '@nikitajs/docker/lib/tools/service',
status: '@nikitajs/docker/lib/tools/status'
},
// unpause: '@nikitajs/docker/lib/unpause'
volume_create: '@nikitajs/docker/lib/volume_create',

@@ -40,2 +45,13 @@ volume_rm: '@nikitajs/docker/lib/volume_rm',

}
});
};
(async function() {
var err;
try {
return (await registry.register(module.exports));
} catch (error) {
err = error;
console.error(err.stack);
return process.exit(1);
}
})();
// Generated by CoffeeScript 2.5.1
// # `nikita.docker.start`
// # `nikita.docker.restart`
// Start stopped containers or restart (stop + starts) a started container.
// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `container` (string)
// Name/ID of the container, required.
// * `machine` (string)
// Name of the docker-machine, required if using docker-machine
// * `timeout` (int)
// Seconds to wait for stop before killing it
// * `code` (int|array)
// Expected code(s) returned by the command, int or array of int, default to 0.
// * `code_skipped`
// Expected code(s) returned by the command if it has no effect, executed will
// not be incremented, int or array of int.
// ## Callback parameters
// * `err`

@@ -31,49 +15,44 @@ // Error object if any.

// ```javascript
// require('nikita')
// .docker.restart({
// ```js
// const {status} = await nikita.docker.restart({
// container: 'toto'
// }, function(err, {status}){
// console.log( err ? err.message : 'Container restarted: ' + status);
// })
// console.info(`Container was started or restarted: ${status}`)
// ```
// ## Source Code
var docker, util;
// ## Schema
var handler, schema;
module.exports = function({options}, callback) {
var cmd, k, ref, v;
this.log({
message: "Entering Docker restart",
level: 'DEBUG',
module: 'nikita/lib/docker/restart'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'container': {
type: 'string',
description: `Name/ID of the container.`
},
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'timeout': {
type: 'integer',
description: `Seconds to wait for stop before killing it.`
}
}
if (options.container == null) {
// Validate parameters
return callback(Error('Missing container parameter'));
}
cmd = 'restart';
if (options.timeout != null) {
cmd += ` -t ${options.timeout}`;
}
cmd += ` ${options.container}`;
return this.system.execute({
cmd: docker.wrap(options, cmd)
}, docker.callback);
},
required: ['container']
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
// ## Handler
handler = async function({config}) {
return (await this.docker.tools.execute({
command: ['restart', config.timeout != null ? `-t ${config.timeout}` : void 0, `${config.container}`].join(' ')
}));
};
util = require('util');
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
};

@@ -7,19 +7,4 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `container` (string)
// Name/ID of the container, required.
// * `machine` (string)
// Name of the docker-machine, required if docker-machine installed.
// * `link` (boolean)
// Remove the specified link.
// * `volumes` (boolean)
// Remove the volumes associated with the container.
// * `force` (boolean)
// Force the removal of a running container (uses SIGKILL).
// ## Callback parameters
// * `err`

@@ -32,72 +17,80 @@ // Error object if any.

// ```javascript
// require('nikita')
// .docker.rm({
// ```js
// const {status} = await nikita.docker.rm({
// container: 'toto'
// }, function(err, status){
// console.log( err ? err.message : 'Container removed: ' + status);
// })
// console.info(`Container was removed: ${status}`)
// ```
// ## Source Code
var docker;
// ## Schema
var handler, schema;
module.exports = function({options}) {
var cmd, k, opt, ref, v;
this.log({
message: "Entering Docker rm",
level: 'DEBUG',
module: 'nikita/lib/docker/rm'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'container': {
type: 'string',
description: `Name/ID of the container.`
},
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'link': {
type: 'boolean',
description: `Remove the specified link.`
},
'volumes': {
type: 'boolean',
description: `Remove the volumes associated with the container.`
},
'force': {
type: 'boolean',
description: `Force the removal of a running container (uses SIGKILL).`
}
},
required: ['container']
};
// ## Handler
handler = async function({config}) {
var exists, running;
({
status: exists,
data: running
} = (await this.docker.tools.execute({
metadata: {
templated: false
},
command: `inspect ${config.container} --format '{{ json .State.Running }}'`,
code_skipped: 1,
format: 'json'
})));
if (!exists) {
return false;
}
if (options.container == null) {
// Validate parameters and madatory conditions
return callback(Error('Missing container parameter'));
if (running && !config.force) {
throw Error('Container must be stopped to be removed without force');
}
cmd = (function() {
var i, len, ref1, results;
ref1 = ['link', 'volumes', 'force'];
results = [];
for (i = 0, len = ref1.length; i < len; i++) {
opt = ref1[i];
if (options[opt]) {
results.push(`-${opt.charAt(0)}`);
} else {
results.push(void 0);
}
}
return results;
})();
cmd = `rm ${cmd.join(' ')} ${options.container}`;
this.system.execute({
cmd: docker.wrap(options, `ps | grep '${options.container}'`),
code_skipped: 1
}, (err, {status}) => {
if (status && !options.force) {
throw Error('Container must be stopped to be removed without force', null);
}
});
this.system.execute({
cmd: docker.wrap(options, `ps -a | grep '${options.container}'`),
code_skipped: 1
}, docker.callback);
return this.system.execute({
cmd: docker.wrap(options, cmd),
if: function() {
return this.status(-1);
}
}, docker.callback);
return (await this.docker.tools.execute({
command: [
'rm',
...(['link',
'volumes',
'force'].filter(function(opt) {
return config[opt];
}).map(function(opt) {
return `-${opt.charAt(0)}`;
})),
config.container
].join(' ')
}));
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
};

@@ -7,15 +7,4 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `image` (string)
// Name of the image, required.
// * `machine` (string)
// Name of the docker-machine, required if docker-machine installed.
// * `no_prune` (boolean)
// Do not delete untagged parents.
// ## Callback parameters
// * `err`

@@ -26,59 +15,74 @@ // Error object if any.

// ## Source Code
var docker, util;
// ## Hook
var handler, on_action, schema;
module.exports = function({options}) {
var cmd_images, cmd_rmi, i, k, len, opt, ref, ref1, v;
this.log({
message: "Entering Docker rmi",
level: 'DEBUG',
module: 'nikita/lib/docker/rmi'
});
// Global options
if (options.docker == null) {
options.docker = {};
on_action = function({config, metadata}) {
if (metadata.argument != null) {
return config.image = metadata.argument;
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
};
// ## Schema
schema = {
type: 'object',
properties: {
// ...docker.wrap_schema
'cwd': {
type: 'string',
description: `Change the build working directory.`
},
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'image': {
type: 'string',
description: `Name of the Docker image present in the registry.`
},
'no_prune': {
type: 'boolean',
description: `Do not delete untagged parents.`
},
'tag': {
type: 'string',
description: `Tag of the Docker image, default to latest.`
}
}
if (options.image == null) {
// Validate parameters and madatory conditions
throw Error('Missing image parameter');
}
cmd_images = 'images';
cmd_images += ` | grep '${options.image} '`;
if (options.tag != null) {
cmd_images += ` | grep ' ${options.tag} '`;
}
cmd_rmi = 'rmi';
ref1 = ['force', 'no_prune'];
for (i = 0, len = ref1.length; i < len; i++) {
opt = ref1[i];
if (options[opt] != null) {
cmd_rmi += ` --${opt.replace('_', '-')}`;
},
required: ['image']
};
// ## Handler
handler = async function({config}) {
await this.docker.tools.execute({
command: ['images', `| grep '${config.image} '`, config.tag != null ? `| grep ' ${config.tag} '` : void 0].join(' '),
code_skipped: [1]
});
return (await this.docker.tools.execute({
command: [
'rmi',
['force',
'no_prune'].filter(function(opt) {
return config[opt] != null;
}).map(function(opt) {
return ` --${opt.replace('_',
'-')}`;
}),
` ${config.image}`,
config.tag != null ? `:${config.tag}` : void 0
].join(''),
if: function({parent}) {
return parent.parent.tools.status(-1);
}
}));
};
// ## Exports
module.exports = {
handler: handler,
hooks: {
on_action: on_action
},
metadata: {
global: 'docker',
schema: schema
}
cmd_rmi += ` ${options.image}`;
if (options.tag != null) {
cmd_rmi += `:${options.tag}`;
}
this.system.execute({
cmd: docker.wrap(options, cmd_images),
code_skipped: 1
}, docker.callback);
return this.system.execute({
cmd: docker.wrap(options, cmd_rmi),
if: function() {
return this.status(-1);
}
}, docker.callback);
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
util = require('util');

@@ -6,83 +6,4 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `container` (string)
// Alias of name.
// * `name` (string)
// Assign a name to the container to run.
// * `image` (string)
// Name/ID of base image, required.
// * `machine` (string)
// Name of the docker-machine, required if using docker-machine.
// * `cmd` (string)
// Overwrite the default ENTRYPOINT of the image, equivalent to
// `--entrypoint docker parameter`
// * `hostname` (string)
// Hostname in the docker container.
// * `port` ( 'int:int' | [] )
// Port mapping.
// * `volume` ( 'path:path' | [] )
// Path mapping.
// * `device` ('path' | [] )
// Send host device(s) to container.
// * `dns` (ip-address | [] )
// Set custom DNS server(s).
// * `dns_search` (ip-address | [] )
// Set custom DNS search domain(s).
// * `expose` ( int | string | [] )
// Export port(s).
// * `link` ( containerName | containerID | [] )
// Link to other container(s).
// * `label` (string | [] )
// Set meta data on a container.
// * `label_file` (path)
// Read in a line delimited file of labels.
// * `add_host` ('host:ip' | [] )
// Add a custom host-to-IP mapping (host:ip).
// * `cap_add` ( | [] )
// Add Linux Capabilities.
// * `cap_drop` ( | [] )
// Drop Linux Capabilities.
// * `blkio_weight` (int)
// Block IO (relative weight), between 10 and 1000.
// * `cgroup_parent`
// Optional parent cgroup for the container.
// * `cid_file` ( path )
// Write the container ID to the file.
// * `cpuset_cpus` (string)
// CPUs in which to allow execution (ex: 0-3 0,1 ...).
// * `entrypoint` ()
// Overwrite the default ENTRYPOINT of the image.
// * `ipc` ()
// IPC namespace to use.
// * `ulimit` ( | [] )
// Ulimit options.
// * `volumes_from` (containerName | containerID | [] )
// Mount volumes from the specified container(s).
// * `detach` (boolean)
// if true, run container in background.
// * `env` ('VAR=value' | [] )
// Environment variables for the container..
// * `env_file` ( path | [] )
// Read in a file of environment variables.
// * `rm` (boolean)
// Delete the container when it ends. True by default.
// * `cwd` (path)
// Working directory of container.
// * `net` (string)
// Set the Network mode for the container.
// * `pid` (string)
// PID namespace to use.
// * `publish_all` (boolean)
// Publish all exposed ports to random ports.
// * `code` (int|array)
// Expected code(s) returned by the command, int or array of int, default to 0..
// * `code_skipped`
// Expected code(s) returned by the command if it has no effect, executed will
// not be incremented, int or array of int.
// ## Callback parameters
// * `err`

@@ -99,5 +20,4 @@ // Error object if any.

// ```javascript
// require('nikita')
// .docker({
// ```js
// const {status} = await nikita.docker.run({
// ssh: ssh

@@ -108,48 +28,338 @@ // name: 'myContainer'

// entrypoint: '/bin/true'
// }, function(err, status, stdout, stderr){
// console.log( err ? err.message : 'Container state changed to running: ' + status);
// })
// console.info(`Container was run: ${status}`)
// ```
// ## Source Code
var docker;
// ## Hooks
var handler, on_action, schema;
module.exports = function({options}, callback) {
var cmd, flag, i, k, len, opt, p, ref, ref1, ref2, ref3, ref4, ref5, v;
this.log({
message: "Entering Docker run",
level: 'DEBUG',
module: 'nikita/lib/docker/run'
});
// Global options
if (options.docker == null) {
options.docker = {};
on_action = function({config}) {
// throw Error 'Property "container" no longer exists' if config.container
// config.name = config.container if not config.name? and config.container?
if (config.name == null) {
config.name = config.container;
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
if (typeof config.expose === 'string') {
return config.expose = parseInt(config.expose);
}
};
// ## Schema
schema = {
type: 'object',
properties: {
'add_host': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Add a custom host-to-IP mapping (host:ip) in the form of \`host:ip\`.`
},
'blkio_weight': {
type: 'integer',
description: `Block IO (relative weight), between 10 and 1000.`
},
'cap_add': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Add Linux Capabilities.`
},
'cap_drop': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Drop Linux Capabilities.`
},
'cgroup_parent': {
type: 'string',
description: `Optional parent cgroup for the container.`
},
'cid_file': {
type: 'string',
description: `Write the container ID to the file.`
},
'container': {
type: 'string',
description: `Alias of name.`
},
'cpuset_cpus': {
type: 'string',
description: `CPUs in which to allow execution (ex: 0-3 0,1 ...).`
},
'cwd': {
type: 'string',
description: `Working directory of container.`
},
'detach': {
type: 'boolean',
description: `if true, run container in background.`
},
'device': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Send host device(s) to container.`
},
'dns': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Set custom DNS server(s).`
},
'dns_search': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Set custom DNS search domain(s).`
},
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'entrypoint': {
type: 'string',
description: `Overwrite the default ENTRYPOINT of the image, equivalent to
\`--entrypoint docker parameter\``
},
'env': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Environment variables for the container in the form of \`VAR=value\`.`
},
'env_file': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Read in a file of environment variables.`
},
'expose': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Export port(s).`
},
'hostname': {
type: 'string',
description: `Hostname in the docker container.`
},
'image': {
type: 'string',
description: `Name/ID of base image.`
},
'ipc': {
type: 'string',
description: `IPC namespace to use.`
},
'label': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Set meta data on a container.`
},
'label_file': {
type: 'string',
description: `Path to read in a line delimited file of labels.`
},
'link': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Link to other container(s) in the form of a container name or a
container ID.`
},
'name': {
type: 'string',
description: `Assign a name to the container to run.`
},
'net': {
type: 'string',
description: `Set the Network mode for the container.`
},
'port': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Port mapping in the form of \`int:int\`.`
},
'pid': {
type: 'string',
description: `PID namespace to use.`
},
'publish_all': {
type: 'boolean',
description: `Publish all exposed ports to random ports.`
},
'rm': {
type: 'boolean',
default: true,
description: `Delete the container when it ends. True by default.`
},
'ulimit': {
oneOf: [
{
type: 'string'
},
{
type: 'integer'
},
{
type: 'array',
items: {
oneOf: [
{
type: 'string'
},
{
type: 'integer'
}
]
}
}
],
description: `Ulimit options.`
},
'volume': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Volume mapping, in the form of \`path:path\`.`
},
'volumes_from': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Mount volumes from the specified container(s).`
}
}
if (options.image == null) {
},
required: ['image']
};
// ## Handler
handler = async function({
config,
tools: {log}
}) {
var command, flag, i, len, opt, p, ref, ref1, ref2, ref3, ref4, result, status;
if (!((config.name != null) || config.rm)) {
// Validate parameters
return callback(Error('Missing image'));
}
if (options.rm == null) {
options.rm = true;
}
if (options.name == null) {
options.name = options.container;
}
if (!((options.name != null) || options.rm)) {
this.log({
log({
message: "Should specify a container name if rm is false",
level: 'WARN',
module: 'nikita/docker/run'
level: 'WARN'
});
}
// Construct exec command
cmd = 'run';
ref1 = {
command = 'run';
ref = {
name: '--name',

@@ -172,13 +382,13 @@ hostname: '-h',

};
// Classic options
for (opt in ref1) {
flag = ref1[opt];
if (options[opt] != null) {
cmd += ` ${flag} ${options[opt]}`;
// Classic config
for (opt in ref) {
flag = ref[opt];
if (config[opt] != null) {
command += ` ${flag} ${config[opt]}`;
}
}
if (options.detach) { // else ' -t'
cmd += ' -d';
if (config.detach) { // else ' -t'
command += ' -d';
}
ref2 = {
ref1 = {
rm: '--rm',

@@ -189,10 +399,10 @@ publish_all: '-P',

};
// Flag options
for (opt in ref2) {
flag = ref2[opt];
if (options[opt]) {
cmd += ` ${flag}`;
// Flag config
for (opt in ref1) {
flag = ref1[opt];
if (config[opt]) {
command += ` ${flag}`;
}
}
ref3 = {
ref2 = {
port: '-p',

@@ -214,14 +424,14 @@ volume: '-v',

};
// Arrays Options
for (opt in ref3) {
flag = ref3[opt];
if (options[opt] != null) {
if (typeof options[opt] === 'string' || typeof options[opt] === 'number') {
cmd += ` ${flag} ${options[opt]}`;
} else if (Array.isArray(options[opt])) {
ref4 = options[opt];
for (i = 0, len = ref4.length; i < len; i++) {
p = ref4[i];
if ((ref5 = typeof p) === 'string' || ref5 === 'number') {
cmd += ` ${flag} ${p}`;
// Arrays config
for (opt in ref2) {
flag = ref2[opt];
if (config[opt] != null) {
if (typeof config[opt] === 'string' || typeof config[opt] === 'number') {
command += ` ${flag} ${config[opt]}`;
} else if (Array.isArray(config[opt])) {
ref3 = config[opt];
for (i = 0, len = ref3.length; i < len; i++) {
p = ref3[i];
if ((ref4 = typeof p) === 'string' || ref4 === 'number') {
command += ` ${flag} ${p}`;
} else {

@@ -236,42 +446,47 @@ callback(Error(`Invalid parameter, '${opt}' array should only contains string or number`));

}
cmd += ` ${options.image}`;
if (options.cmd) {
cmd += ` ${options.cmd}`;
command += ` ${config.image}`;
if (config.command) {
command += ` ${config.command}`;
}
// need to delete the cmd options or it will be used in docker.exec
delete options.cmd;
this.system.execute({
if: options.name != null,
cmd: docker.wrap(options, `ps -a | grep '${options.name}'`),
// need to delete the command config or it will be used in docker.exec
// delete config.command
({status} = (await this.docker.tools.execute({
if: config.name != null,
command: `ps -a | egrep ' ${config.name}$'`,
code_skipped: 1,
shy: true
}, function(err, {status}) {
docker.callback(...arguments);
if (status) {
return this.log({
message: "Container already running. Skipping",
level: 'INFO',
module: 'nikita/docker/run'
});
metadata: {
shy: true
}
});
return this.system.execute({
cmd: docker.wrap(options, cmd),
})));
if (status) {
log({
message: "Container already running. Skipping",
level: 'INFO'
});
}
result = (await this.docker.tools.execute({
command: command,
if: function() {
return (options.name == null) || this.status(-1) === false;
return (config.name == null) || status === false;
}
}, function(err, {status}) {
docker.callback(...arguments);
if (status) {
this.log({
message: "Container now running",
level: 'WARN',
module: 'nikita/docker/run'
});
}
return callback(...arguments);
});
}));
if (result.status) {
log({
message: "Container now running",
level: 'WARN'
});
}
return result;
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
// ## Exports
module.exports = {
handler: handler,
hooks: {
on_action: on_action
},
metadata: {
global: 'docker',
schema: schema
}
};

@@ -6,24 +6,4 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `image` (string)
// Name/ID of base image, required.
// * `tag` (string)
// Tag of the image.
// * `machine` (string)
// Name of the docker-machine, required if using docker-machine.
// * `output` (string).
// TAR archive output path, required.
// * `target` (string).
// Shortcut for "output" option, required.
// * `code` (int | array)
// Expected code(s) returned by the command, int or array of int, default to 0.
// * `code_skipped`
// Expected code(s) returned by the command if it has no effect, executed will
// not be incremented, int or array of int.
// ## Callback parameters
// * `err`

@@ -40,63 +20,69 @@ // Error object if any.

// ```javascript
// nikita.docker({
// ssh: ssh
// output: 'test-image.tar'
// image: 'test-image'
// compression: 'gzip'
// entrypoint: '/bin/true'
// }, function(err, {status}){
// console.log( err ? err.message : 'Container saved: ' + status);
// ```js
// const {status} = await nikita.docker.save({
// image: 'nikita/load_test:latest',
// output: `${scratch}/nikita_saved.tar`,
// })
// console.info(`Container was saved: ${status}`)
// ```
// ## Source Code
var docker, util;
// ## Hooks
var handler, on_action, schema;
module.exports = function({options}) {
var cmd, k, ref, v;
this.log({
message: "Entering Docker save",
level: 'DEBUG',
module: 'nikita/lib/docker/save'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
on_action = function({config}) {
return config.output != null ? config.output : config.output = config.target;
};
// ## Schema
schema = {
type: 'object',
properties: {
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'image': {
type: 'string',
description: `Name/ID of base image.`
},
'tag': {
type: 'string',
description: `Tag of the image.`
},
'output': {
type: 'string',
description: `TAR archive output path.`
},
'target': {
type: 'string',
description: `Shortcut for "output" option, required.`
}
}
if (options.image == null) {
// Validate parameters
throw Error('Missing image parameter');
}
if (options.output == null) {
options.output = options.target;
}
if (options.output == null) {
throw Error('Missing output parameter');
}
},
required: ['image', 'output']
};
// ## Handler
handler = async function({
config,
tools: {log}
}) {
// Saves image to local tmp path, than copy it
cmd = `save -o ${options.output} ${options.image}`;
if (options.tag != null) {
cmd += `:${options.tag}`;
}
this.log({
message: `Extracting image ${options.output} to file:${options.image}`,
level: 'INFO',
module: 'nikita/lib/docker/save'
log({
message: `Extracting image ${config.output} to file:${config.image}`,
level: 'INFO'
});
return this.system.execute({
cmd: docker.wrap(options, cmd)
}, docker.callback);
return (await this.docker.tools.execute({
command: [`save -o ${config.output} ${config.image}`, config.tag != null ? `:${config.tag}` : void 0].join('')
}));
};
// ## Modules Dependencies
util = require('util');
docker = require('@nikitajs/core/lib/misc/docker');
// ## Exports
module.exports = {
handler: handler,
hooks: {
on_action: on_action
},
metadata: {
global: 'docker',
schema: schema
}
};
// Generated by CoffeeScript 2.5.1
// # `nikita.docker.restart`
// # `nikita.docker.start`
// Start a container.
// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `container` (string)
// Name/ID of the container, required.
// * `machine` (string)
// Name of the docker-machine, required if using docker-machine.
// * `attach` (boolean)
// attach STDOUT/STDERR, default to false.
// * `code` (int|array)
// Expected code(s) returned by the command, int or array of int, default to 0.
// * `code_skipped`
// Expected code(s) returned by the command if it has no effect, executed will
// not be incremented, int or array of int.
// ## Callback parameters
// * `err`

@@ -35,76 +19,69 @@ // Error object if any.

// 1- builds an image from dockerfile without any resourcess
// ```javascript
// require('nikita')
// .docker.start({
// ```js
// const {status} = await nikita.docker.start({
// container: 'toto',
// attach: true
// }, function(err, is_true, stdout, stderr){
// console.log( err ? err.message : 'Container state changed to started: ' + status);
// })
// console.info(`Container was started: ${status}`)
// ```
// ## Source Code
var docker, util;
// ## Schema
var handler, schema;
module.exports = function({options}) {
var cmd, k, ref, v;
this.log({
message: "Entering Docker start",
level: 'DEBUG',
module: 'nikita/lib/docker/start'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'attach': {
type: 'boolean',
default: false,
description: `Attach STDOUT/STDERR.`
},
'container': {
type: 'string',
description: `Name/ID of the container, required.`
},
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
}
},
required: ['container']
};
// ## Handler
handler = async function({
config,
tools: {log}
}) {
var status;
({status} = (await this.docker.tools.status(config, {
metadata: {
shy: true
}
})));
if (status) {
log({
message: `Container already started ${config.container} (Skipping)`,
level: 'INFO',
module: 'nikita/lib/docker/start'
});
} else {
log({
message: `Starting container ${config.container}`,
level: 'INFO',
module: 'nikita/lib/docker/start'
});
}
if (options.container == null) {
// Validation
throw Error('Missing container parameter');
return (await this.docker.tools.execute({
unless: status,
command: ['start', config.attach ? '-a' : void 0, `${config.container}`].join(' ')
}));
};
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
// rm is false by default only if options.service is true
cmd = 'start';
if (options.attach) {
cmd += ' -a';
}
cmd += ` ${options.container}`;
this.docker.status({
shy: true
}, options, function(err, {status}) {
if (err) {
throw err;
}
if (status) {
this.log({
message: `Container already started ${options.container} (Skipping)`,
level: 'INFO',
module: 'nikita/lib/docker/start'
});
} else {
this.log({
message: `Starting container ${options.container}`,
level: 'INFO',
module: 'nikita/lib/docker/start'
});
}
if (status) {
return this.end();
}
});
return this.system.execute({
cmd: docker.wrap(options, cmd)
}, docker.callback);
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
util = require('util');

@@ -6,15 +6,4 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `container` (string)
// Name/ID of the container, required.
// * `machine` (string)
// Name of the docker-machine, required if using docker-machine.
// * `timeout` (int)
// Seconds to wait for stop before killing it
// ## Callback parameters
// * `err`

@@ -27,73 +16,69 @@ // Error object if any.

// ```javascript
// require('nikita')
// .docker.stop({
// ```js
// const {status} = await nikita.docker.stop({
// container: 'toto'
// }, function(err, {status}){
// console.log( err ? err.message : 'Container state changed to stopped: ' + status);
// })
// console.info(`Container was stopped: ${status}`)
// ```
// ## Source Code
var docker, util;
// ## Schema
var handler, schema;
module.exports = function({options}) {
var cmd, k, ref, v;
this.log({
message: "Entering Docker stop",
level: 'DEBUG',
module: 'nikita/lib/docker/stop'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'container': {
type: 'string',
description: `Name/ID of the container.`
},
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'timeout': {
type: 'integer',
description: `Seconds to wait for stop before killing the container (Docker default
is 10).`
}
},
required: ['container']
};
// ## Handler
handler = async function({
config,
tools: {log}
}) {
var status;
// rm is false by default only if config.service is true
({status} = (await this.docker.tools.status(config, {
metadata: {
shy: true
}
})));
if (status) {
log({
message: `Stopping container ${config.container}`,
level: 'INFO',
module: 'nikita/lib/docker/stop'
});
} else {
log({
message: `Container already stopped ${config.container} (Skipping)`,
level: 'INFO',
module: 'nikita/lib/docker/stop'
});
}
if (options.container == null) {
// Validate parameters
throw Error('Missing container parameter');
return (await this.docker.tools.execute({
if: status,
command: ['stop', config.timeout != null ? `-t ${config.timeout}` : void 0, `${config.container}`].join(' ')
}));
};
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
// rm is false by default only if options.service is true
cmd = 'stop';
if (options.timeout != null) {
cmd += ` -t ${options.timeout}`;
}
cmd += ` ${options.container}`;
this.docker.status({
shy: true
}, options, function(err, {status}) {
if (err) {
throw err;
}
if (status) {
this.log({
message: `Stopping container ${options.container}`,
level: 'INFO',
module: 'nikita/lib/docker/stop'
});
} else {
this.log({
message: `Container already stopped ${options.container} (Skipping)`,
level: 'INFO',
module: 'nikita/lib/docker/stop'
});
}
if (!status) {
return this.end();
}
});
return this.system.execute({
cmd: docker.wrap(options, cmd)
}, docker.callback);
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
util = require('util');

@@ -6,13 +6,4 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `container` (string)
// Name/ID of the container, required.
// * `machine` (string)
// Name of the docker-machine, required if using docker-machine.
// ## Callback parameters
// * `err`

@@ -25,46 +16,50 @@ // Error object if any.

// ```javascript
// require('nikita')
// .docker.pause({
// ```js
// const {status} = await nikita.docker.unpause({
// container: 'toto'
// }, function(err, {status}){
// console.log( err ? err.message : 'Container was unpaused: ' + status);
// })
// console.info(`Container was unpaused: ${status}`)
// ```
// ## Source Code
var docker, util;
// ## Schema
var handler, schema;
module.exports = function({options}, callback) {
var k, ref, v;
this.log({
message: "Entering Docker unpause",
level: 'DEBUG',
module: 'nikita/lib/docker/unpause'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'boot2docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/boot2docker'
},
'container': {
type: 'string',
description: `Name/ID of the container`
},
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
}
}
if (options.container == null) {
},
required: ['container']
};
// ## Handler
handler = async function({
config,
tools: {log}
}) {
if (config.container == null) {
// Validation
throw Error('Missing container parameter');
}
return this.system.execute({
cmd: docker.wrap(options, `unpause ${options.container}`)
}, function() {
return docker.callback(callback, ...arguments);
});
return (await this.docker.tools.execute({
command: `unpause ${config.container}`
}));
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
util = require('util');
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
};
// Generated by CoffeeScript 2.5.1
// # `nikita.volume_create`
// # `nikita.docker.volume_create`
// Create a volume.
// Create a volume.
// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `driver` (string)
// Specify volume driver name.
// * `label` (string|array)
// Set metadata for a volume.
// * `machine` (string)
// Name of the docker-machine, required if using docker-machine.
// * `name` (string)
// Specify volume name.
// * `opt` (string|array)
// Set driver specific options.
// ## Callback parameters
// * `err`

@@ -30,70 +15,91 @@ // Error object if any.

// ```javascript
// require('nikita')
// .docker.pause({
// ```js
// const {status} = await nikita.docker.volume_create({
// name: 'my_volume'
// }, function(err, status){
// console.log( err ? err.message : 'Volume created: ' + status);
// })
// console.info(`Volume was created: ${status}`)
// ```
// ## Source Code
var docker;
// ## Schema
var handler, schema;
module.exports = function({options}) {
var cmd, k, ref, v;
this.log({
message: "Entering Docker volume_create",
level: 'DEBUG',
module: 'nikita/lib/docker/volume_create'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'driver': {
type: 'string',
description: `Specify volume driver name.`
},
'label': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Set metadata for a volume.`
},
'name': {
type: 'string',
description: `Specify volume name.`
},
'opt': {
oneOf: [
{
type: 'string'
},
{
type: 'array',
items: {
type: 'string'
}
}
],
description: `Set driver specific options.`
}
}
if (typeof options.label === 'string') {
// Normalize options
options.label = [options.label];
};
// ## Handler
handler = async function({config}) {
var status;
if (typeof config.label === 'string') {
// Normalize config
config.label = [config.label];
}
if (typeof options.opt === 'string') {
options.opt = [options.opt];
if (typeof config.opt === 'string') {
config.opt = [config.opt];
}
// Build the docker command arguments
cmd = ["volume create"];
if (options.driver) {
cmd.push(`--driver ${options.driver}`);
}
if (options.label) {
cmd.push(`--label ${options.label.join(',')}`);
}
if (options.name) {
cmd.push(`--name ${options.name}`);
}
if (options.opt) {
cmd.push(`--opt ${options.opt.join(',')}`);
}
cmd = cmd.join(' ');
this.system.execute({
if: options.name,
cmd: docker.wrap(options, `volume inspect ${options.name}`),
({status} = (await this.docker.tools.execute({
if: config.name,
command: `volume inspect ${config.name}`,
code: 1,
code_skipped: 0,
shy: true
});
return this.system.execute({
metadata: {
shy: true
}
})));
return (await this.docker.tools.execute({
if: function() {
return !options.name || this.status(-1);
return !config.name || status;
},
cmd: docker.wrap(options, cmd)
});
command: ["volume create", config.driver ? `--driver ${config.driver}` : void 0, config.label ? `--label ${config.label.join(',')}` : void 0, config.name ? `--name ${config.name}` : void 0, config.opt ? `--opt ${config.opt.join(',')}` : void 0].join(' ')
}));
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
};
// Generated by CoffeeScript 2.5.1
// # `nikita.volume_rm`
// # `nikita.docker.volume_rm`
// Remove a volume.
// Remove a volume.
// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `container` (string|array).
// Name or Id of the container, required.
// * `machine` (string)
// Name of the docker-machine, required if using docker-machine.
// * `name` (string)
// Specify volume name.
// ## Callback parameters
// * `err`

@@ -26,43 +15,45 @@ // Error object if any.

// ```javascript
// nikita.docker.volume_rm({
// ```js
// const {status} = await nikita.docker.volume_rm({
// name: 'my_volume'
// }, function(err, status){
// console.log( err ? err.message : 'Volume removed: ' + status);
// })
// console.info(`Volume was removed: ${status}`)
// ```
// ## Source Code
var docker;
// ## Schema
var handler, schema;
module.exports = function({options}) {
var k, ref, v;
this.log({
message: "Entering Docker volume_rm",
level: 'DEBUG',
module: 'nikita/lib/docker/volume_rm'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
},
'name': {
type: 'string',
description: `Specify volume name.`
}
}
if (!options.name) {
};
// ## Handler
handler = async function({config}) {
if (!config.name) {
// Validation
throw Error("Missing required option name");
}
return this.system.execute({
cmd: docker.wrap(options, `volume rm ${options.name}`),
return (await this.docker.tools.execute({
command: `volume rm ${config.name}`,
code: 0,
code_skipped: 1
});
}));
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
};

@@ -6,18 +6,4 @@ // Generated by CoffeeScript 2.5.1

// ## Options
// ## Output
// * `boot2docker` (boolean)
// Whether to use boot2docker or not, default to false.
// * `container` (string)
// Name/ID of the container, optional.
// * `machine` (string)
// Name of the docker-machine, optional if using docker-machine.
// * `code` (int|array)
// Expected code(s) returned by the command, int or array of int, default to 0.
// * `code_skipped`
// Expected code(s) returned by the command if it has no effect, executed will
// not be incremented, int or array of int.
// ## Callback parameters
// * `err`

@@ -30,46 +16,39 @@ // Error object if any.

// ```javascript
// nikita.docker.wait({
// ```js
// const {status} = await nikita.docker.wait({
// container: 'toto'
// }, function(err, status){
// console.log( err ? err.message : 'Did we really had to wait: ' + status);
// })
// console.info(`Did we really had to wait: ${status}`)
// ```
// ## Source Code
var docker, util;
// ## Schema
var handler, schema;
module.exports = function({options}, callback) {
var cmd, k, ref, v;
this.log({
message: "Entering Docker wait",
level: 'DEBUG',
module: 'nikita/lib/docker/wait'
});
// Global options
if (options.docker == null) {
options.docker = {};
}
ref = options.docker;
for (k in ref) {
v = ref[k];
if (options[k] == null) {
options[k] = v;
schema = {
type: 'object',
properties: {
'container': {
type: 'string',
description: `Name/ID of the container.`
},
'docker': {
$ref: 'module://@nikitajs/docker/lib/tools/execute#/properties/docker'
}
}
if (options.container == null) {
// Validation
return callback(Error('Missing container parameter'));
}
// rm is false by default only if options.service is true
cmd = `wait ${options.container} | read r; return $r`;
// Construct other exec parameter
return this.system.execute({
cmd: docker.wrap(options, cmd)
}, docker.callback);
},
required: ['container']
};
// ## Modules Dependencies
docker = require('@nikitajs/core/lib/misc/docker');
// ## Handler
handler = async function({config}) {
// Old implementation was `wait {container} | read r; return $r`
return (await this.docker.tools.execute(`wait ${config.container}`));
};
util = require('util');
// ## Exports
module.exports = {
handler: handler,
metadata: {
global: 'docker',
schema: schema
}
};

@@ -5,2 +5,3 @@ {

"keywords": [
"nikita",
"build",

@@ -16,3 +17,3 @@ "cli",

],
"version": "0.9.7",
"version": "1.0.0-alpha.0",
"author": "David Worms <david@adaltas.com>",

@@ -41,10 +42,14 @@ "bugs": {

],
"dependencies": {
"@nikitajs/file": "^1.0.0-alpha.0"
},
"peerDependencies": {
"@nikitajs/core": "^0.9.5"
"@nikitajs/core": "^0.9.7"
},
"devDependencies": {
"@nikitajs/network": "^1.0.0-alpha.0",
"coffeescript": "^2.5.1",
"mocha": "7.1.1",
"should": "~13.2.3",
"ssh2-they": "^2.0.4"
"mocha": "^8.2.1",
"mocha-they": "^0.1.2",
"should": "^13.2.3"
},

@@ -57,2 +62,15 @@ "engines": {

],
"mocha": {
"throw-deprecation": true,
"require": [
"should",
"coffeescript/register",
"@nikitajs/docker/src/register",
"@nikitajs/network/src/register"
],
"inline-diffs": true,
"timeout": 40000,
"reporter": "spec",
"recursive": true
},
"publishConfig": {

@@ -69,7 +87,8 @@ "access": "public"

"scripts": {
"build": "coffee -b -o lib src && sed -i -e 's/src/lib/g' lib/register.js",
"build": "coffee -b -o lib src && find lib -type f | xargs sed -i -e 's/@nikitajs\\/docker\\/src/@nikitajs\\/docker\\/lib/g'",
"pretest": "npm run build",
"test": "mocha 'test/**/*.coffee'"
"test": "mocha 'test/**/*.coffee'",
"testall": "mocha 'test/**/*.coffee' && env/run.sh"
},
"gitHead": "60b27a97d345e810697619dabe7379984b640aee"
"gitHead": "c5ee53354302fd36836e269ceac5639381efadd2"
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc