-
Notifications
You must be signed in to change notification settings - Fork 1
/
docker.js
135 lines (117 loc) · 3.58 KB
/
docker.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
const _ = require("lodash");
const {
generateRandomEnvironmentVariableName,
generateRandomTemporaryPath,
} = require("./helpers");
function createVolumeDefinition(path) {
if (!path) {
throw new Error("Path is required to create Volume Definition.");
}
if (!_.isString(path)) {
throw new Error("Path parameter must be a string.");
}
const pathEnvironmentVariableName = generateRandomEnvironmentVariableName();
const mountPointEnvironmentVariableName = generateRandomEnvironmentVariableName();
const mountPoint = generateRandomTemporaryPath();
return {
path: {
name: pathEnvironmentVariableName,
value: path,
},
mountPoint: {
name: mountPointEnvironmentVariableName,
value: mountPoint,
},
};
}
function sanitizeCommand(command, commandPrefix) {
if (!command || !_.isString(command)) {
throw new Error("Command parameter must be a string.");
}
let commandWithPrefix = command;
if (commandPrefix) {
commandWithPrefix = command.startsWith(`${commandPrefix} `) ? command : `${commandPrefix} ${command}`;
}
return `sh -c ${JSON.stringify(commandWithPrefix)}`;
}
function buildDockerCommand({
command,
image,
environmentVariables = {},
volumeDefinitionsArray = [],
additionalArguments = [],
workingDirectory,
user,
}) {
if (!image) {
throw new Error("No Docker image provided.");
}
if (!command) {
throw new Error("No command provided for Docker container.");
}
if (
additionalArguments && (
!_.isArray(additionalArguments)
|| _.some(additionalArguments, (additionalArgument) => !_.isString(additionalArgument))
)
) {
throw new Error("Additional Arguments must be an array of strings.");
}
const environmentVariableArguments = buildEnvironmentVariableArguments(environmentVariables);
const volumeArguments = buildMountVolumeArguments(volumeDefinitionsArray);
const dockerArguments = ["docker", "run", "--rm"];
dockerArguments.push(...environmentVariableArguments);
dockerArguments.push(...volumeArguments);
dockerArguments.push(...additionalArguments);
if (user) {
dockerArguments.push("--user", user);
}
if (workingDirectory) {
dockerArguments.push("-w", workingDirectory);
}
dockerArguments.push(image, command);
return dockerArguments.join(" ");
}
function buildEnvironmentVariableArguments(environmentVariables) {
if (
!environmentVariables
|| !_.isObject(environmentVariables)
|| _.isArray(environmentVariables)
) {
throw new Error("environmentVariables parameter must be an object.");
}
return Object.entries(environmentVariables)
.map(([name]) => ["-e", name])
.flat();
}
function buildMountVolumeArguments(volumeDefinitions) {
if (!volumeDefinitions || !_.isArray(volumeDefinitions)) {
throw new Error("volumeDefinitions parameter must be an array of objects.");
}
return volumeDefinitions
.map((definition) => {
assertVolumeConfigPropertiesExistence(definition, [
"path.value",
"mountPoint.value",
]);
return [
"-v",
`$${definition.path.name}:$${definition.mountPoint.name}`,
];
})
.flat();
}
function assertVolumeConfigPropertiesExistence(volumeConfig = {}, propertyPaths = []) {
propertyPaths.forEach((propertyPath) => {
if (!_.has(volumeConfig, propertyPath)) {
throw new Error(`Volume Config property "${propertyPath}" is missing on: ${JSON.stringify(volumeConfig)}`);
}
});
}
module.exports = {
buildDockerCommand,
createVolumeDefinition,
sanitizeCommand,
buildEnvironmentVariableArguments,
buildMountVolumeArguments,
};