Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

dockerode-compose

Package Overview
Dependencies
Maintainers
1
Versions
13
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

dockerode-compose - npm Package Compare versions

Comparing version 1.2.2 to 1.3.1

.github/workflows/node.js.yml

23

compose.js

@@ -30,2 +30,19 @@ const yaml = require('js-yaml');

async down(options) {
var output = {};
try {
output.file = this.file;
output.services = await services.down(this.docker, this.projectName, this.recipe, output, options);
output.networks = await networks.down(this.docker, this.projectName, this.recipe, output);
if (options !== undefined) {
if (options.volumes) {
output.volumes = await volumes.down(this.docker, this.projectName, this.recipe, output);
}
}
return output;
} catch (e) {
throw e;
}
}
async up(options) {

@@ -36,6 +53,6 @@ var output = {};

output.secrets = await secrets(this.docker, this.projectName, this.recipe, output);
output.volumes = await volumes(this.docker, this.projectName, this.recipe, output);
output.volumes = await volumes.up(this.docker, this.projectName, this.recipe, output);
output.configs = await configs(this.docker, this.projectName, this.recipe, output);
output.networks = await networks(this.docker, this.projectName, this.recipe, output);
output.services = await services(this.docker, this.projectName, this.recipe, output, options);
output.networks = await networks.up(this.docker, this.projectName, this.recipe, output);
output.services = await services.up(this.docker, this.projectName, this.recipe, output, options);
return output;

@@ -42,0 +59,0 @@ } catch (e) {

@@ -5,6 +5,19 @@ var Dockerode = require('dockerode');

var docker = new Dockerode();
var compose = new DockerodeCompose(docker, './test/assets/wordpress.yml', 'wordpress');
var yamlFile = './test/assets/wordpress_original.yml'
var projectName = 'wordpress'
if (process.argv.length > 2) {
if (process.argv[2] !== undefined) {
yamlFile = process.argv[2]
}
if (process.argv[3] !== undefined) {
projectName = process.argv[3]
}
}
var compose = new DockerodeCompose(docker, yamlFile, projectName);
(async () => {
console.log(await compose.pull());
})();

@@ -5,4 +5,17 @@ var Dockerode = require('dockerode');

var docker = new Dockerode();
var compose = new DockerodeCompose(docker, './test/assets/wordpress_original.yml', 'wordpress');
var yamlFile = './test/assets/wordpress_original.yml'
var projectName = 'wordpress'
if (process.argv.length > 2) {
if (process.argv[2] !== undefined) {
yamlFile = process.argv[2]
}
if (process.argv[3] !== undefined) {
projectName = process.argv[3]
}
}
var compose = new DockerodeCompose(docker, yamlFile, projectName);
(async () => {

@@ -9,0 +22,0 @@ var state = await compose.up();

107

lib/networks.js

@@ -1,3 +0,18 @@

module.exports = async function (docker, projectName, recipe, output) {
async function down(docker, projectName, recipe) {
var networks = [];
var networkNames = Object.keys(recipe.networks || { default: null });
for (var networkName of networkNames) {
try {
var network = await docker.getNetwork(projectName + '_' + networkName);
} catch (e) {}
try {
await network.remove();
} catch (e) {}
}
return networks;
}
async function up(docker, projectName, recipe, output) {
var networks = [];
var networkNames = Object.keys(recipe.networks || []);

@@ -8,7 +23,21 @@ for (var networkName of networkNames) {

try {
networks.push({ 'name': projectName + '_' + networkName, 'network': await docker.createNetwork({ 'Name': projectName + '_' + networkName, 'CheckDuplicate': true }) });
networks.push({
name: projectName + '_' + networkName,
network: await docker.createNetwork({
Name: projectName + '_' + networkName,
CheckDuplicate: true,
}),
});
} catch (err) {
if (err.statusCode == 409 && err.json.message.includes('already exists')) {
let returnedNetwork = await docker.listNetworks({ 'filters': { 'name': [projectName + '_' + networkName] } });
networks.push({ 'name': projectName + '_' + networkName, 'network': await docker.getNetwork(returnedNetwork[0].Id) });
if (
err.statusCode == 409 &&
err.json.message.includes('already exists')
) {
let returnedNetwork = await docker.listNetworks({
filters: { name: [projectName + '_' + networkName] },
});
networks.push({
name: projectName + '_' + networkName,
network: await docker.getNetwork(returnedNetwork[0].Id),
});
} else {

@@ -18,14 +47,20 @@ throw err;

}
continue
continue;
}
if (network.external === true) continue;
var opts = {
'Name': projectName + '_' + networkName,
'Driver': network.driver,
'DriverOpts': network.driver_opts,
'Labels': network.labels,
'Attachable': network.attachable,
'EnableIPv6': network.enable_ipv6,
'Internal': network.internal,
'CheckDuplicate': true
Name: projectName + '_' + networkName,
Driver: network.driver,
DriverOpts: network.driver_opts,
Labels: {
...network.labels,
...{
'com.docker.compose.network': 'default',
'com.docker.compose.project': projectName,
},
},
Attachable: network.attachable,
EnableIPv6: network.enable_ipv6,
Internal: network.internal,
CheckDuplicate: true,
};

@@ -37,11 +72,11 @@ if (network.name !== undefined) {

opts.IPAM = {
'Driver': network.ipam.driver,
'Options': network.ipam.options
Driver: network.ipam.driver,
Options: network.ipam.options,
};
if (network.ipam.config !== undefined) {
opts.IPAM['Config'] = {
'Subnet': network.ipam.config.subnet,
'IPRange': network.ipam.config.ip_range,
'Gateway': network.ipam.config.gateway,
'AuxAddress': network.ipam.config.aux_addresses
Subnet: network.ipam.config.subnet,
IPRange: network.ipam.config.ip_range,
Gateway: network.ipam.config.gateway,
AuxAddress: network.ipam.config.aux_addresses,
};

@@ -51,3 +86,6 @@ }

//if exists we have to compare with the existing network
networks.push({ 'name': projectName + '_' + networkName, 'network': await docker.createNetwork(opts) });
networks.push({
name: projectName + '_' + networkName,
network: await docker.createNetwork(opts),
});
}

@@ -57,7 +95,21 @@

try {
networks.push({ 'name': projectName + '_default', 'network': await docker.createNetwork({ 'Name': projectName + '_default', 'CheckDuplicate': true }) });
networks.push({
name: projectName + '_default',
network: await docker.createNetwork({
Name: projectName + '_default',
CheckDuplicate: true,
}),
});
} catch (err) {
if (err.statusCode == 409 && err.json.message.includes('already exists')) {
let returnedNetwork = await docker.listNetworks({ 'filters': { 'name': [projectName + '_default'] } });
networks.push({ 'name': projectName + '_' + networkName, 'network': await docker.getNetwork(returnedNetwork[0].Id) });
if (
err.statusCode == 409 &&
err.json.message.includes('already exists')
) {
let returnedNetwork = await docker.listNetworks({
filters: { name: [projectName + '_default'] },
});
networks.push({
name: projectName + '_' + networkName,
network: await docker.getNetwork(returnedNetwork[0].Id),
});
} else {

@@ -70,1 +122,6 @@ throw err;

}
module.exports = {
down,
up,
};

@@ -7,6 +7,23 @@ const tools = require('./tools');

module.exports = async function (docker, projectName, recipe, output, options) {
async function down(docker, projectName, recipe, output, options) {
var services = [];
var serviceNames = tools.sortServices(recipe);
for (var serviceName of serviceNames) {
let container = docker.getContainer(projectName + '_' + serviceName + '_1');
try {
await container.stop();
} catch (e) {}
try {
await container.remove();
} catch (e) {}
}
return services;
}
async function up(docker, projectName, recipe, output, options) {
var services = [];
var serviceNames = tools.sortServices(recipe);
for (var serviceName of serviceNames) {
var pathScope = {};

@@ -18,7 +35,6 @@ pathScope.file = output.file;

if (service.extends.service !== undefined) {
service = extendsServices(service, recipe, pathScope)
service = extendsServices(service, recipe, pathScope);
} else {
throw new Error('Service key in extends is required!');
}
}

@@ -39,5 +55,6 @@

if (service.build.context !== undefined) {
var buildContextPath = path.resolve(path.join(absolutePath, service.build.context));
var buildContextPath = path.resolve(
path.join(absolutePath, service.build.context)
);
if (fs.existsSync(buildContextPath)) {
if (service.build.args !== undefined) {

@@ -47,3 +64,3 @@ var out = {};

for (let arg_line of service.build.args) {
var arg = arg_line.split("=");
var arg = arg_line.split('=');
out[arg[0]] = arg[1];

@@ -86,3 +103,5 @@ }

// RE ARRAGE the function "convertSizeStringToByteValue" to a generic one
obj['shmsize'] = servicesTools.convertSizeStringToByteValue([{ 'path': '', 'rate': service.build.shm_size }]).Rate;
obj['shmsize'] = servicesTools.convertSizeStringToByteValue([
{ path: '', rate: service.build.shm_size },
]).Rate;
}

@@ -95,8 +114,22 @@

if (service.build.dockerfile === undefined) {
await servicesTools.buildDockerImage(docker, buildContextPath, obj, null, options);
await servicesTools.buildDockerImage(
docker,
buildContextPath,
obj,
null,
options
);
} else {
await servicesTools.buildDockerImage(docker, buildContextPath, obj, service.build.dockerfile, options);
await servicesTools.buildDockerImage(
docker,
buildContextPath,
obj,
service.build.dockerfile,
options
);
}
} else {
throw new Error(`build path ${buildContextPath} either does not exist, is not accessible, or is not a valid URL.`);
throw new Error(
`build path ${buildContextPath} either does not exist, is not accessible, or is not a valid URL.`
);
}

@@ -107,7 +140,17 @@ } else {

} else {
var dockerFilePath = path.resolve(path.join(absolutePath, service.build));
var dockerFilePath = path.resolve(
path.join(absolutePath, service.build)
);
if (fs.existsSync(dockerFilePath)) {
await servicesTools.buildDockerImage(docker, dockerFilePath, obj, null, options);
await servicesTools.buildDockerImage(
docker,
dockerFilePath,
obj,
null,
options
);
} else {
throw new Error(`build path ${dockerFilePath} either does not exist, is not accessible, or is not a valid URL.`);
throw new Error(
`build path ${dockerFilePath} either does not exist, is not accessible, or is not a valid URL.`
);
}

@@ -118,10 +161,13 @@ }

var opts = {
'name': projectName + '_' + serviceName,
'Image': service.image,
'HostConfig': servicesTools.buildHostConfig(service, recipe),
'Env': servicesTools.buildEnvVars(service),
'NetworkingConfig': {
'EndpointsConfig': {
}
}
name: projectName + '_' + serviceName + '_1',
Image: service.image,
HostConfig: servicesTools.buildHostConfig(projectName, service, recipe),
Env: servicesTools.buildEnvVars(service),
NetworkingConfig: {
EndpointsConfig: {},
},
Labels: {
'com.docker.compose.project': projectName,
'com.docker.compose.service': serviceName,
},
};

@@ -132,8 +178,7 @@

} else {
opts.HostConfig.NetworkMode = projectName + '_default'
opts.NetworkingConfig.EndpointsConfig[projectName + '_default'] = {
'IPAMConfig': {},
'Links': [],
'Aliases': [
serviceName,
]
IPAMConfig: null,
Links: null,
Aliases: [serviceName],
};

@@ -173,8 +218,24 @@ }

opts.StopTimeout = service.stop_grace_period;
} else if (service.stop_grace_period.includes('m') && service.stop_grace_period.includes('s')) {
let minutes = parseInt(service.stop_grace_period.substring(0, service.stop_grace_period.indexOf('m')));
let seconds = parseInt(service.stop_grace_period.substring(service.stop_grace_period.indexOf('m') + 1, service.stop_grace_period.indexOf('s')));
opts.StopTimeout = (minutes * 60) + seconds;
} else if (
service.stop_grace_period.includes('m') &&
service.stop_grace_period.includes('s')
) {
let minutes = parseInt(
service.stop_grace_period.substring(
0,
service.stop_grace_period.indexOf('m')
)
);
let seconds = parseInt(
service.stop_grace_period.substring(
service.stop_grace_period.indexOf('m') + 1,
service.stop_grace_period.indexOf('s')
)
);
opts.StopTimeout = minutes * 60 + seconds;
} else {
opts.StopTimeout = service.stop_grace_period.substring(0, service.stop_grace_period.length - 2);
opts.StopTimeout = service.stop_grace_period.substring(
0,
service.stop_grace_period.length - 2
);
}

@@ -219,6 +280,12 @@ }

healthcheck.Test = service.healthcheck.test;
healthcheck.Interval = convertFancyDurationToMs(service.healthcheck.interval);
healthcheck.Timeout = convertFancyDurationToMs(service.healthcheck.timeout);
healthcheck.Interval = convertFancyDurationToMs(
service.healthcheck.interval
);
healthcheck.Timeout = convertFancyDurationToMs(
service.healthcheck.timeout
);
healthcheck.Retries = service.healthcheck.retries;
healthcheck.StartPeriod = convertFancyDurationToMs(service.healthcheck.start_period);
healthcheck.StartPeriod = convertFancyDurationToMs(
service.healthcheck.start_period
);
opts.Healthcheck = healthcheck;

@@ -242,9 +309,13 @@ }

let networkNames = Object.keys(networksToAttach[0]);
await findNetwork(output, networkNames[0]).disconnect({ 'Container': container.id });
await findNetwork(output, networkNames[0]).disconnect({
Container: container.id,
});
let networksToAttachSorted = tools.sortNetworksToAttach(networksToAttach);
for (var networkToAttach of networksToAttachSorted) {
let networkName = Object.keys(networkToAttach);
await findNetwork(output, networkName).connect({ 'Container': container.id, 'EndpointConfig': networkToAttach[networkName] });
await findNetwork(output, networkName).connect({
Container: container.id,
EndpointConfig: networkToAttach[networkName],
});
}
}

@@ -257,9 +328,7 @@ await container.start();

var findNetwork = function (output, name) {
for (var network of output.networks) {
if (network.name == name)
return network.network;
if (network.name == name) return network.network;
}
}
};

@@ -272,10 +341,11 @@ var convertFancyDurationToMs = function (value) {

let minutes = parseInt(value.substring(0, value.indexOf('m')));
let seconds = parseInt(value.substring(value.indexOf('m') + 1, value.indexOf('s')));
return ((minutes * 60) + seconds) * 1000 * 1000000;
let seconds = parseInt(
value.substring(value.indexOf('m') + 1, value.indexOf('s'))
);
return (minutes * 60 + seconds) * 1000 * 1000000;
} else {
return parseInt(value.substring(0, value.length - 2)) * 1000 * 1000000;
}
}
};
// https://github.com/compose-spec/compose-spec/blob/master/spec.md#extends

@@ -286,12 +356,32 @@ var extendsServices = function (service, recipe, pathScope) {

// EXTENDS OF THE SAME RECIPE
return buildExtendsService(service, service.extends.service, recipe, pathScope);
return buildExtendsService(
service,
service.extends.service,
recipe,
pathScope
);
} else {
// EXTENDS OF ANOTHER RECIPE
var absolutePath = path.dirname(pathScope.file);
var extendsRecipe = yaml.load(fs.readFileSync(path.resolve(path.join(absolutePath, service.extends.file)), 'utf8'));
return buildExtendsService(service, service.extends.service, extendsRecipe, pathScope);
var extendsRecipe = yaml.load(
fs.readFileSync(
path.resolve(path.join(absolutePath, service.extends.file)),
'utf8'
)
);
return buildExtendsService(
service,
service.extends.service,
extendsRecipe,
pathScope
);
}
}
};
var buildExtendsService = function (service, extendsServiceName, recipe, pathScope) {
var buildExtendsService = function (
service,
extendsServiceName,
recipe,
pathScope
) {
var extend = false;

@@ -316,3 +406,3 @@ var extendsRecipeServiceNames = Object.keys(recipe.services);

if (key != 'extends') {
mergingService(key, service, oldService)
mergingService(key, service, oldService);
}

@@ -322,6 +412,7 @@ }

var absolutePath = path.dirname(pathScope.file);
pathScope.file = path.resolve(path.join(absolutePath, oldService.extends.file))
pathScope.file = path.resolve(
path.join(absolutePath, oldService.extends.file)
);
}
if (extend)
service = extendsServices(service, recipe, pathScope);
if (extend) service = extendsServices(service, recipe, pathScope);

@@ -332,3 +423,3 @@ return service;

throw new Error('Extends service not found');
}
};

@@ -349,3 +440,3 @@ // https://github.com/compose-spec/compose-spec/blob/master/spec.md#restrictions

}
}
};

@@ -360,10 +451,21 @@ // https://github.com/compose-spec/compose-spec/blob/master/spec.md#merging-service-definitions

'extra_hosts',
'ulimits'
'ulimits',
];
var objectMappings = {
'build': { 'args': '', 'labels': '', 'extra_hosts': '', },
'deploy': { 'labels': '', 'update_config': '', 'rollback_config': '', 'restart_policy': '', 'resources': { 'limits': '' } },
'blkio_config': { 'device_read_bps': '', 'device_read_iops': '', 'device_write_bps': '', 'device_write_iops': '' },
'logging': { 'options': '' }
}
build: { args: '', labels: '', extra_hosts: '' },
deploy: {
labels: '',
update_config: '',
rollback_config: '',
restart_policy: '',
resources: { limits: '' },
},
blkio_config: {
device_read_bps: '',
device_read_iops: '',
device_write_bps: '',
device_write_iops: '',
},
logging: { options: '' },
};
var sequences = [

@@ -378,13 +480,18 @@ 'cap_add',

//'secrets', // not fully implemented yet
'security_opt'
]
'security_opt',
];
var objectSequences = {
'deploy': {
'placement': { 'constraints': '', 'preferences': '' },
'reservations': { 'generic_resources': '' }
}
}
deploy: {
placement: { constraints: '', preferences: '' },
reservations: { generic_resources: '' },
},
};
// https://github.com/compose-spec/compose-spec/blob/master/spec.md#mappings - MAPPINGS
if (key == 'build' || key == 'deploy' || key == 'blkio_config' || key == 'logging') {
if (
key == 'build' ||
key == 'deploy' ||
key == 'blkio_config' ||
key == 'logging'
) {
// one object level missing in deploy resources

@@ -418,4 +525,11 @@ var objectMappingsKeys = Object.keys(objectMappings[key]);

for (let serviceLine of service[key]) {
if (serviceLine.split('=')[0] == oldServiceLine.split('=')[0] || serviceLine.split(':')[0] == oldServiceLine.split(':')[0]) {
service[key].splice(service[key].indexOf(serviceLine), 1, oldServiceLine)
if (
serviceLine.split('=')[0] == oldServiceLine.split('=')[0] ||
serviceLine.split(':')[0] == oldServiceLine.split(':')[0]
) {
service[key].splice(
service[key].indexOf(serviceLine),
1,
oldServiceLine
);
}

@@ -431,3 +545,8 @@ }

// https://github.com/compose-spec/compose-spec/blob/master/spec.md#sequences - SEQUENCES
} else if (key == 'dns' || key == 'dns_search' || key == 'env_file' || key == 'tmpfs') {
} else if (
key == 'dns' ||
key == 'dns_search' ||
key == 'env_file' ||
key == 'tmpfs'
) {
if (Array.isArray(oldService[key]) || Array.isArray(service[key])) {

@@ -447,3 +566,3 @@ if (!Array.isArray(service[key])) {

service[key] = [];
service[key].push(service[key])
service[key].push(service[key]);
service[key].push(oldService[key]);

@@ -470,2 +589,7 @@ }

}
}
};
module.exports = {
down,
up,
};

@@ -7,3 +7,3 @@ const fs = require('fs');

module.exports = {
'buildPorts': function (servicePorts, output) {
buildPorts: function (servicePorts, output) {
var ports = {};

@@ -14,3 +14,5 @@ if (typeof servicePorts[0] === 'object') {

for (let port of servicePorts) {
ports[port.target + '/' + port.protocol] = [{ 'HostPort': port.published.toString() }];
ports[port.target + '/' + port.protocol] = [
{ HostPort: port.published.toString() },
];
}

@@ -30,12 +32,19 @@ output['PortBindings'] = ports;

let split_port_split0_array = [];
split_port_split0_array = fillPortArray(parseInt(split_port_split0[0]), parseInt(split_port_split0[1]));
split_port_split0_array = fillPortArray(
parseInt(split_port_split0[0]),
parseInt(split_port_split0[1])
);
let split_port_split1 = port_split[1].split('-');
let split_port_split1_array = [];
split_port_split1_array = fillPortArray(parseInt(split_port_split1[0]), parseInt(split_port_split1[1]));
split_port_split1_array = fillPortArray(
parseInt(split_port_split1[0]),
parseInt(split_port_split1[1])
);
for (let index in split_port_split0_array) {
ports[split_port_split1_array[index] + '/tcp'] = [{ 'HostPort': split_port_split0_array[index].toString() }];
ports[split_port_split1_array[index] + '/tcp'] = [
{ HostPort: split_port_split0_array[index].toString() },
];
}
} else if (port_split[0].includes('-')) {

@@ -46,15 +55,11 @@ // "3000-3005"

for (let i = split_port_split[0]; i <= split_port_split[1]; i++) {
ports[port_split[1] + '/tcp'].push({ 'HostPort': i.toString() });
ports[port_split[1] + '/tcp'].push({ HostPort: i.toString() });
}
} else if (port_split[1].includes('/')) {
// "6060:6060/udp"
ports[port_split[1]] = [{ 'HostPort': port_split[0] }];
ports[port_split[1]] = [{ HostPort: port_split[0] }];
} else {
// "8000:8000"
ports[port_split[1] + '/tcp'] = [{ 'HostPort': port_split[0] }];
ports[port_split[1] + '/tcp'] = [{ HostPort: port_split[0] }];
}
} else if (port_split.length == 3) {

@@ -66,22 +71,33 @@ // "x.x.x.x:xxxx:xxxx"

let split_port_split1_array = [];
split_port_split1_array = fillPortArray(parseInt(split_port_split1[0]), parseInt(split_port_split1[1]));
split_port_split1_array = fillPortArray(
parseInt(split_port_split1[0]),
parseInt(split_port_split1[1])
);
let split_port_split2 = port_split[2].split('-');
let split_port_split2_array = [];
split_port_split2_array = fillPortArray(parseInt(split_port_split2[0]), parseInt(split_port_split2[1]));
split_port_split2_array = fillPortArray(
parseInt(split_port_split2[0]),
parseInt(split_port_split2[1])
);
for (let index in split_port_split1_array) {
ports[split_port_split2_array[index] + '/tcp'] = [{ 'HostPort': split_port_split1_array[index].toString(), 'HostIp': port_split[0] }];
ports[split_port_split2_array[index] + '/tcp'] = [
{
HostPort: split_port_split1_array[index].toString(),
HostIp: port_split[0],
},
];
}
} else if (port_split[1] == '') {
// "127.0.0.1::5000
ports[port_split[2] + '/tcp'] = [{ 'HostPort': port_split[2], 'HostIp': port_split[0] }];
ports[port_split[2] + '/tcp'] = [
{ HostPort: port_split[2], HostIp: port_split[0] },
];
} else {
// "127.0.0.1:8001:8001"
ports[port_split[2] + '/tcp'] = [{ 'HostPort': port_split[1], 'HostIp': port_split[0] }];
ports[port_split[2] + '/tcp'] = [
{ HostPort: port_split[1], HostIp: port_split[0] },
];
}
} else {

@@ -93,9 +109,7 @@ // "xxxx"

for (let i = split_port_split[0]; i <= split_port_split[1]; i++) {
ports[i + '/tcp'] = [{ 'HostPort': i.toString() }];
ports[i + '/tcp'] = [{ HostPort: i.toString() }];
}
} else {
// "3000"
ports[port + '/tcp'] = [{ 'HostPort': port }];
ports[port + '/tcp'] = [{ HostPort: port }];
}

@@ -109,5 +123,5 @@ }

//ToDo: complete the compose specification
'buildHostConfig': function (service, recipe) {
buildHostConfig: function (projectName, service, recipe) {
var output = {
'RestartPolicy': { 'Name': service.restart }
RestartPolicy: { Name: service.restart },
};

@@ -119,3 +133,3 @@

var svf = recipe.services[vf[0]];
this.buildVolumesHostconfig(svf.volumes, output, vf[1]);
this.buildVolumesHostconfig(projectName, svf.volumes, output, vf[1]);
}

@@ -125,3 +139,3 @@ }

if (service.volumes !== undefined) {
this.buildVolumesHostconfig(service.volumes, output);
this.buildVolumesHostconfig(projectName, service.volumes, output);
}

@@ -292,21 +306,30 @@

weight_device[0]['Path'] = service.blkio_config.weight_device[0].path;
weight_device[0]['Weight'] = service.blkio_config.weight_device[0].weight;
weight_device[0]['Weight'] =
service.blkio_config.weight_device[0].weight;
output.BlkioWeightDevice = weight_device;
}
if (service.blkio_config.device_read_bps !== undefined) {
output.BlkioDeviceReadBps = convertSizeStringToByteValue(service.blkio_config.device_read_bps);
output.BlkioDeviceReadBps = convertSizeStringToByteValue(
service.blkio_config.device_read_bps
);
}
if (service.blkio_config.device_read_iops !== undefined) {
let device_read_iops = [{}];
device_read_iops[0]['Path'] = service.blkio_config.device_read_iops[0].path;
device_read_iops[0]['Rate'] = service.blkio_config.device_read_iops[0].rate;
device_read_iops[0]['Path'] =
service.blkio_config.device_read_iops[0].path;
device_read_iops[0]['Rate'] =
service.blkio_config.device_read_iops[0].rate;
output.BlkioDeviceReadIOps = device_read_iops;
}
if (service.blkio_config.device_write_bps !== undefined) {
output.BlkioDeviceWriteBps = convertSizeStringToByteValue(service.blkio_config.device_write_bps);
output.BlkioDeviceWriteBps = convertSizeStringToByteValue(
service.blkio_config.device_write_bps
);
}
if (service.blkio_config.device_write_iops !== undefined) {
let device_write_iops = [{}];
device_write_iops[0]['Path'] = service.blkio_config.device_write_iops[0].path;
device_write_iops[0]['Rate'] = service.blkio_config.device_write_iops[0].rate;
device_write_iops[0]['Path'] =
service.blkio_config.device_write_iops[0].path;
device_write_iops[0]['Rate'] =
service.blkio_config.device_write_iops[0].rate;
output.BlkioDeviceWriteIOps = device_write_iops;

@@ -324,3 +347,3 @@ }

'buildVolumesHostconfig': function (volumes, output, type) {
buildVolumesHostconfig: function (projectName, volumes, output, type) {
if (output['Binds'] === undefined) {

@@ -331,3 +354,3 @@ output['Binds'] = [];

if (typeof volume === 'string' || volume instanceof String) {
var aux = volume;
var aux = projectName + '_' + volume;
if (type == 'ro') {

@@ -340,3 +363,4 @@ aux += ':ro';

if (volume.source && volume.target) {
volumestr += volume.source + ':' + volume.target + ':';
volumestr +=
projectName + '_' + volume.source + ':' + volume.target + ':';
}

@@ -358,3 +382,3 @@ if (volume.read_only || type == 'ro') {

'buildVolumes': function (volumes, opts) {
buildVolumes: function (volumes, opts) {
if (opts['Volumes'] === undefined) {

@@ -375,3 +399,3 @@ opts['Volumes'] = {};

'buildEnvVars': function (service) {
buildEnvVars: function (service) {
var output = [];

@@ -404,3 +428,3 @@

'buildNetworks': function (serviceNetworks, networksToAttach) {
buildNetworks: function (serviceNetworks, networksToAttach) {
if (Array.isArray(serviceNetworks)) {

@@ -410,11 +434,13 @@ for (let index = 0; index < serviceNetworks.length; index++) {

let networkTemplate = {
'NetworkingConfig': {
'EndpointsConfig': {
}
}
NetworkingConfig: {
EndpointsConfig: {},
},
};
networkTemplate.NetworkingConfig.EndpointsConfig[networkName] = {};
networkTemplate.NetworkingConfig.EndpointsConfig[networkName]['Aliases'] = [serviceName];
networkTemplate.NetworkingConfig.EndpointsConfig[networkName][
'Aliases'
] = [serviceName];
if (index === 0)
opts.NetworkingConfig.EndpointsConfig = networkTemplate.NetworkingConfig.EndpointsConfig;
opts.NetworkingConfig.EndpointsConfig =
networkTemplate.NetworkingConfig.EndpointsConfig;

@@ -429,28 +455,42 @@ networksToAttach.push(networkTemplate.NetworkingConfig.EndpointsConfig);

let networkTemplate = {
'NetworkingConfig': {
'EndpointsConfig': {
}
}
NetworkingConfig: {
EndpointsConfig: {},
},
};
networkTemplate.NetworkingConfig.EndpointsConfig[networkName] = {};
networkTemplate.NetworkingConfig.EndpointsConfig[networkName]['IPAMConfig'] = {};
networkTemplate.NetworkingConfig.EndpointsConfig[networkName][
'IPAMConfig'
] = {};
if (network.aliases !== undefined) {
networkTemplate.NetworkingConfig.EndpointsConfig[networkName]['Aliases'] = network.aliases;
networkTemplate.NetworkingConfig.EndpointsConfig[networkName][
'Aliases'
] = network.aliases;
}
if (network.ipv4_address !== undefined) {
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].IPAMConfig['IPv4Address'] = network.ipv4_address;
networkTemplate.NetworkingConfig.EndpointsConfig[
networkName
].IPAMConfig['IPv4Address'] = network.ipv4_address;
}
if (network.ipv6_address !== undefined) {
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].IPAMConfig['IPv6Address'] = network.ipv6_address;
networkTemplate.NetworkingConfig.EndpointsConfig[
networkName
].IPAMConfig['IPv6Address'] = network.ipv6_address;
}
if (network.link_local_ips !== undefined) {
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].IPAMConfig['LinkLocalIPs'] = network.link_local_ips;
networkTemplate.NetworkingConfig.EndpointsConfig[
networkName
].IPAMConfig['LinkLocalIPs'] = network.link_local_ips;
}
if (network.priority !== undefined) {
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].priority = network.priority;
networkTemplate.NetworkingConfig.EndpointsConfig[
networkName
].priority = network.priority;
} else {
networkTemplate.NetworkingConfig.EndpointsConfig[networkName].priority = 0;
networkTemplate.NetworkingConfig.EndpointsConfig[
networkName
].priority = 0;
}
if (index === 0) {
opts.NetworkingConfig.EndpointsConfig = networkTemplate.NetworkingConfig.EndpointsConfig;
opts.NetworkingConfig.EndpointsConfig =
networkTemplate.NetworkingConfig.EndpointsConfig;
}

@@ -463,3 +503,3 @@ networksToAttach.push(networkTemplate.NetworkingConfig.EndpointsConfig);

// TODO: OPTIMIZE!
'convertSizeStringToByteValue': function (obj) {
convertSizeStringToByteValue: function (obj) {
let rate = obj[0].rate.toLowerCase();

@@ -497,5 +537,8 @@ let new_obj = [{}];

'buildEnvVarsFromFile': function (env_file_path, output) {
buildEnvVarsFromFile: function (env_file_path, output) {
// Each line in an env file MUST be in `VAR=VAL` format.
let env_file = fs.readFileSync(env_file_path, 'utf8').toString().split('\n');
let env_file = fs
.readFileSync(env_file_path, 'utf8')
.toString()
.split('\n');
for (let env_line of env_file) {

@@ -513,14 +556,25 @@ // Lines beginning with `#` MUST be ignored. Blank lines MUST also be ignored.

'fillPortArray': function (start, end) {
return Array(end - start + 1).fill().map((_, idx) => start + idx);
fillPortArray: function (start, end) {
return Array(end - start + 1)
.fill()
.map((_, idx) => start + idx);
},
'buildDockerImage': async function (docker, buildPath, obj, dockerfile, options) {
buildDockerImage: async function (
docker,
buildPath,
obj,
dockerfile,
options
) {
options = options || {};
if (dockerfile !== null) {
obj['dockerfile'] = path.basename(dockerfile);
let streami = await docker.buildImage({
context: buildPath,
src: [dockerfile]
}, obj);
let streami = await docker.buildImage(
{
context: buildPath,
src: [dockerfile],
},
obj
);
if (options.verbose === true) {

@@ -531,3 +585,3 @@ streami.pipe(process.stdout);

}
await new Promise(fulfill => streami.once('end', fulfill));
await new Promise((fulfill) => streami.once('end', fulfill));
} else {

@@ -541,5 +595,5 @@ var tarStream = tar.pack(buildPath);

}
await new Promise(fulfill => streami.once('end', fulfill));
await new Promise((fulfill) => streami.once('end', fulfill));
}
}
}
},
};

@@ -20,3 +20,9 @@ module.exports = {

if (order.indexOf(serviceName) === -1) {
insertService(serviceName, recipe.services[serviceName].depends_on || [], order);
let depends_on = recipe.services[serviceName].depends_on;
if (typeof depends_on === "object" && !Array.isArray(depends_on)) {
// if we are using Long Syntax https://github.com/compose-spec/compose-spec/blob/master/spec.md#long-syntax-1
// we will need to get keys from object and use them as dependencies
depends_on = Object.keys(depends_on)
}
insertService(serviceName, depends_on || [], order);
}

@@ -23,0 +29,0 @@ }

@@ -1,5 +0,20 @@

module.exports = async function (docker, projectName, recipe, output) {
async function down(docker, projectName, recipe, output) {
var volumes = [];
var volumeNames = Object.keys(recipe.volumes || []);
for (var volumeName of volumeNames) {
try {
var volume = await docker.getVolume(projectName + '_' + volumeName);
} catch (e) {}
try {
await volume.remove();
} catch (e) {}
}
return volumes;
}
async function up(docker, projectName, recipe, output) {
var volumes = [];
var volumeNames = Object.keys(recipe.volumes || []);
for (var volumeName of volumeNames) {
var volume = recipe.volumes[volumeName];

@@ -9,6 +24,12 @@ if (volume === null) volume = {};

var opts = {
'Name': projectName + '_' + volumeName,
'Driver': volume.driver,
'DriverOpts': volume.driver_opts,
'Labels': volume.labels
Name: projectName + '_' + volumeName,
Driver: volume.driver,
DriverOpts: volume.driver_opts,
Labels: {
...volume.labels,
...{
'com.docker.compose.project': projectName,
'com.docker.compose.volume': volumeName,
},
},
};

@@ -21,2 +42,7 @@ if (volume.name !== undefined) {

return volumes;
}
}
module.exports = {
down,
up,
};
{
"name": "dockerode-compose",
"version": "1.2.2",
"version": "1.3.1",
"description": "docker-compose in nodejs using dockerode",

@@ -24,3 +24,3 @@ "main": "./compose.js",

"dependencies": {
"dockerode": "^3.2.1",
"dockerode": "^3.3.1",
"js-yaml": "^4.0.0",

@@ -27,0 +27,0 @@ "tar-fs": "^2.1.1"

@@ -44,17 +44,38 @@ const expect = require('chai').expect,

expect(report.services).to.be.ok;
await new Promise(r => setTimeout(r, 2000));
let listContainers = await docker.listContainers({ 'all': true });
for (var containerInfo of listContainers) {
if (containerInfo.Names[0].includes("dockerodec_wordpress")) {
let container = docker.getContainer(containerInfo.Id);
if (containerInfo.State == 'running')
await container.stop();
await container.remove();
}
}
done();
})();
});
afterEach('clean up', function (done) {
this.timeout(60000);
(async () => {
await compose.down({ volumes: true });
done();
})();
});
});
describe('#down', function () {
beforeEach('bring up', function (done) {
this.timeout(20000);
(async () => {
await compose.up();
done();
})();
});
it("should do compose down", function (done) {
this.timeout(60000);
(async () => {
await compose.down({volumes: true});
let listContainers = await docker.listContainers({ 'all': true, 'filters': {"label":[`com.docker.compose.project=${compose.projectName}`]}});
expect(listContainers).to.be.empty
let listVolumes = await docker.listVolumes({ 'filters': {"label":[`com.docker.compose.project=${compose.projectName}`]}})
expect(listVolumes.Volumes).to.be.empty
expect(listVolumes.Warnings).to.be.null
let listNetworks = await docker.listNetworks({ 'filters': {"label":[`com.docker.compose.project=${compose.projectName}`]}})
expect(listNetworks).to.be.empty
done();
})();
});
});
describe('#up_complex', function () {

@@ -66,17 +87,38 @@ it("should do compose up complex example with extends and build", function (done) {

expect(report.services).to.be.ok;
await new Promise(r => setTimeout(r, 5000));
let listContainers = await docker.listContainers({ 'all': true });
for (var containerInfo of listContainers) {
if (containerInfo.Names[0].includes("dockerodec_complex")) {
let container = docker.getContainer(containerInfo.Id);
if (containerInfo.State == 'running')
await container.stop();
await container.remove();
}
}
done();
})();
});
afterEach('clean up', function (done) {
this.timeout(60000);
(async () => {
await compose_complex.down({ volumes: true });
done();
})();
});
});
describe('#down_complex', function () {
beforeEach('bring up', function (done) {
this.timeout(300000);
(async () => {
await compose_complex.up();
done();
})();
});
it("should do compose down complex example with extends and build", function (done) {
this.timeout(60000);
(async () => {
await compose_complex.down({volumes: true});
let listContainers = await docker.listContainers({ 'all': true, 'filters': {"label":[`com.docker.compose.project=${compose.projectName}`]}});
expect(listContainers).to.be.empty
let listVolumes = await docker.listVolumes({ 'filters': {"label":[`com.docker.compose.project=${compose.projectName}`]}})
expect(listVolumes.Volumes).to.be.empty
expect(listVolumes.Warnings).to.be.null
let listNetworks = await docker.listNetworks({ 'filters': {"label":[`com.docker.compose.project=${compose.projectName}`]}})
expect(listNetworks).to.be.empty
done();
})();
});
});
describe('#up_build', function () {

@@ -88,12 +130,2 @@ it("should do compose up example with build", function (done) {

expect(report.services).to.be.ok;
await new Promise(r => setTimeout(r, 5000));
let listContainers = await docker.listContainers({ 'all': true });
for (var containerInfo of listContainers) {
if (containerInfo.Names[0].includes("dockerodec_build")) {
let container = docker.getContainer(containerInfo.Id);
if (containerInfo.State == 'running')
await container.stop();
await container.remove();
}
}
done();

@@ -107,17 +139,38 @@ })();

expect(report.services).to.be.ok;
await new Promise(r => setTimeout(r, 5000));
let listContainers = await docker.listContainers({ 'all': true });
for (var containerInfo of listContainers) {
if (containerInfo.Names[0].includes("dockerodec_build")) {
let container = docker.getContainer(containerInfo.Id);
if (containerInfo.State == 'running')
await container.stop();
await container.remove();
}
}
done();
})();
});
afterEach('clean up', function (done) {
this.timeout(60000);
(async () => {
await compose_build.down({ volumes: true });
done();
})();
});
});
describe('#down_build', function () {
beforeEach('bring up', function (done) {
this.timeout(300000);
(async () => {
await compose_build.up();
done();
})();
});
it("should do compose down example with build", function (done) {
this.timeout(60000);
(async () => {
await compose_build.down({volumes: true});
let listContainers = await docker.listContainers({ 'all': true, 'filters': {"label":[`com.docker.compose.project=${compose.projectName}`]}});
expect(listContainers).to.be.empty
let listVolumes = await docker.listVolumes({ 'filters': {"label":[`com.docker.compose.project=${compose.projectName}`]}})
expect(listVolumes.Volumes).to.be.empty
expect(listVolumes.Warnings).to.be.null
let listNetworks = await docker.listNetworks({ 'filters': {"label":[`com.docker.compose.project=${compose.projectName}`]}})
expect(listNetworks).to.be.empty
done();
})();
});
});
});

@@ -17,2 +17,3 @@ const expect = require('chai').expect;

'wordpress2',
'wordpress6',
'wordpress4',

@@ -19,0 +20,0 @@ 'wordpress5'

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc