|
@@ -12,10 +12,13 @@ const _ = require('lodash')
|
|
|
const ONE_HOUR_IN_MS = 60 * 60 * 1000
|
|
const ONE_HOUR_IN_MS = 60 * 60 * 1000
|
|
|
logger.info('using docker runner')
|
|
logger.info('using docker runner')
|
|
|
|
|
|
|
|
-const usingSiblingContainers = () =>
|
|
|
|
|
- Settings != null &&
|
|
|
|
|
- Settings.path != null &&
|
|
|
|
|
- Settings.path.sandboxedCompilesHostDir != null
|
|
|
|
|
|
|
+function usingSiblingContainers() {
|
|
|
|
|
+ return (
|
|
|
|
|
+ Settings != null &&
|
|
|
|
|
+ Settings.path != null &&
|
|
|
|
|
+ Settings.path.sandboxedCompilesHostDir != null
|
|
|
|
|
+ )
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
let containerMonitorTimeout
|
|
let containerMonitorTimeout
|
|
|
let containerMonitorInterval
|
|
let containerMonitorInterval
|
|
@@ -83,30 +86,32 @@ const DockerRunner = {
|
|
|
// logOptions = _.clone(options)
|
|
// logOptions = _.clone(options)
|
|
|
// logOptions?.HostConfig?.SecurityOpt = "secomp used, removed in logging"
|
|
// logOptions?.HostConfig?.SecurityOpt = "secomp used, removed in logging"
|
|
|
logger.log({ projectId }, 'running docker container')
|
|
logger.log({ projectId }, 'running docker container')
|
|
|
- DockerRunner._runAndWaitForContainer(options, volumes, timeout, function (
|
|
|
|
|
- error,
|
|
|
|
|
- output
|
|
|
|
|
- ) {
|
|
|
|
|
- if (error && error.statusCode === 500) {
|
|
|
|
|
- logger.log(
|
|
|
|
|
- { err: error, projectId },
|
|
|
|
|
- 'error running container so destroying and retrying'
|
|
|
|
|
- )
|
|
|
|
|
- DockerRunner.destroyContainer(name, null, true, function (error) {
|
|
|
|
|
- if (error != null) {
|
|
|
|
|
- return callback(error)
|
|
|
|
|
- }
|
|
|
|
|
- DockerRunner._runAndWaitForContainer(
|
|
|
|
|
- options,
|
|
|
|
|
- volumes,
|
|
|
|
|
- timeout,
|
|
|
|
|
- callback
|
|
|
|
|
|
|
+ DockerRunner._runAndWaitForContainer(
|
|
|
|
|
+ options,
|
|
|
|
|
+ volumes,
|
|
|
|
|
+ timeout,
|
|
|
|
|
+ (error, output) => {
|
|
|
|
|
+ if (error && error.statusCode === 500) {
|
|
|
|
|
+ logger.log(
|
|
|
|
|
+ { err: error, projectId },
|
|
|
|
|
+ 'error running container so destroying and retrying'
|
|
|
)
|
|
)
|
|
|
- })
|
|
|
|
|
- } else {
|
|
|
|
|
- callback(error, output)
|
|
|
|
|
|
|
+ DockerRunner.destroyContainer(name, null, true, (error) => {
|
|
|
|
|
+ if (error != null) {
|
|
|
|
|
+ return callback(error)
|
|
|
|
|
+ }
|
|
|
|
|
+ DockerRunner._runAndWaitForContainer(
|
|
|
|
|
+ options,
|
|
|
|
|
+ volumes,
|
|
|
|
|
+ timeout,
|
|
|
|
|
+ callback
|
|
|
|
|
+ )
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ callback(error, output)
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- })
|
|
|
|
|
|
|
+ )
|
|
|
|
|
|
|
|
// pass back the container name to allow it to be killed
|
|
// pass back the container name to allow it to be killed
|
|
|
return name
|
|
return name
|
|
@@ -115,7 +120,7 @@ const DockerRunner = {
|
|
|
kill(containerId, callback) {
|
|
kill(containerId, callback) {
|
|
|
logger.log({ containerId }, 'sending kill signal to container')
|
|
logger.log({ containerId }, 'sending kill signal to container')
|
|
|
const container = dockerode.getContainer(containerId)
|
|
const container = dockerode.getContainer(containerId)
|
|
|
- container.kill(function (error) {
|
|
|
|
|
|
|
+ container.kill((error) => {
|
|
|
if (
|
|
if (
|
|
|
error != null &&
|
|
error != null &&
|
|
|
error.message != null &&
|
|
error.message != null &&
|
|
@@ -144,13 +149,13 @@ const DockerRunner = {
|
|
|
let containerReturned = false
|
|
let containerReturned = false
|
|
|
let output = {}
|
|
let output = {}
|
|
|
|
|
|
|
|
- const callbackIfFinished = function () {
|
|
|
|
|
|
|
+ function callbackIfFinished() {
|
|
|
if (streamEnded && containerReturned) {
|
|
if (streamEnded && containerReturned) {
|
|
|
callback(null, output)
|
|
callback(null, output)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- const attachStreamHandler = function (error, _output) {
|
|
|
|
|
|
|
+ function attachStreamHandler(error, _output) {
|
|
|
if (error != null) {
|
|
if (error != null) {
|
|
|
return callback(error)
|
|
return callback(error)
|
|
|
}
|
|
}
|
|
@@ -163,15 +168,12 @@ const DockerRunner = {
|
|
|
options,
|
|
options,
|
|
|
volumes,
|
|
volumes,
|
|
|
attachStreamHandler,
|
|
attachStreamHandler,
|
|
|
- function (error, containerId) {
|
|
|
|
|
|
|
+ (error, containerId) => {
|
|
|
if (error != null) {
|
|
if (error != null) {
|
|
|
return callback(error)
|
|
return callback(error)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- DockerRunner.waitForContainer(name, timeout, function (
|
|
|
|
|
- error,
|
|
|
|
|
- exitCode
|
|
|
|
|
- ) {
|
|
|
|
|
|
|
+ DockerRunner.waitForContainer(name, timeout, (error, exitCode) => {
|
|
|
if (error != null) {
|
|
if (error != null) {
|
|
|
return callback(error)
|
|
return callback(error)
|
|
|
}
|
|
}
|
|
@@ -305,7 +307,7 @@ const DockerRunner = {
|
|
|
// When a container is started with volume pointing to a
|
|
// When a container is started with volume pointing to a
|
|
|
// non-existent directory then docker creates the directory but
|
|
// non-existent directory then docker creates the directory but
|
|
|
// with root ownership.
|
|
// with root ownership.
|
|
|
- DockerRunner._checkVolumes(options, volumes, function (err) {
|
|
|
|
|
|
|
+ DockerRunner._checkVolumes(options, volumes, (err) => {
|
|
|
if (err != null) {
|
|
if (err != null) {
|
|
|
return releaseLock(err)
|
|
return releaseLock(err)
|
|
|
}
|
|
}
|
|
@@ -329,7 +331,7 @@ const DockerRunner = {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const checkVolume = (path, cb) =>
|
|
const checkVolume = (path, cb) =>
|
|
|
- fs.stat(path, function (err, stats) {
|
|
|
|
|
|
|
+ fs.stat(path, (err, stats) => {
|
|
|
if (err != null) {
|
|
if (err != null) {
|
|
|
return cb(err)
|
|
return cb(err)
|
|
|
}
|
|
}
|
|
@@ -352,22 +354,24 @@ const DockerRunner = {
|
|
|
logger.log({ container_name: name }, 'starting container')
|
|
logger.log({ container_name: name }, 'starting container')
|
|
|
const container = dockerode.getContainer(name)
|
|
const container = dockerode.getContainer(name)
|
|
|
|
|
|
|
|
- const createAndStartContainer = () =>
|
|
|
|
|
- dockerode.createContainer(options, function (error, container) {
|
|
|
|
|
|
|
+ function createAndStartContainer() {
|
|
|
|
|
+ dockerode.createContainer(options, (error, container) => {
|
|
|
if (error != null) {
|
|
if (error != null) {
|
|
|
return callback(error)
|
|
return callback(error)
|
|
|
}
|
|
}
|
|
|
startExistingContainer()
|
|
startExistingContainer()
|
|
|
})
|
|
})
|
|
|
- var startExistingContainer = () =>
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ function startExistingContainer() {
|
|
|
DockerRunner.attachToContainer(
|
|
DockerRunner.attachToContainer(
|
|
|
options.name,
|
|
options.name,
|
|
|
attachStreamHandler,
|
|
attachStreamHandler,
|
|
|
- function (error) {
|
|
|
|
|
|
|
+ (error) => {
|
|
|
if (error != null) {
|
|
if (error != null) {
|
|
|
return callback(error)
|
|
return callback(error)
|
|
|
}
|
|
}
|
|
|
- container.start(function (error) {
|
|
|
|
|
|
|
+ container.start((error) => {
|
|
|
if (error != null && error.statusCode !== 304) {
|
|
if (error != null && error.statusCode !== 304) {
|
|
|
callback(error)
|
|
callback(error)
|
|
|
} else {
|
|
} else {
|
|
@@ -377,7 +381,9 @@ const DockerRunner = {
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
)
|
|
)
|
|
|
- container.inspect(function (error, stats) {
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ container.inspect((error, stats) => {
|
|
|
if (error != null && error.statusCode === 404) {
|
|
if (error != null && error.statusCode === 404) {
|
|
|
createAndStartContainer()
|
|
createAndStartContainer()
|
|
|
} else if (error != null) {
|
|
} else if (error != null) {
|
|
@@ -394,10 +400,7 @@ const DockerRunner = {
|
|
|
|
|
|
|
|
attachToContainer(containerId, attachStreamHandler, attachStartCallback) {
|
|
attachToContainer(containerId, attachStreamHandler, attachStartCallback) {
|
|
|
const container = dockerode.getContainer(containerId)
|
|
const container = dockerode.getContainer(containerId)
|
|
|
- container.attach({ stdout: 1, stderr: 1, stream: 1 }, function (
|
|
|
|
|
- error,
|
|
|
|
|
- stream
|
|
|
|
|
- ) {
|
|
|
|
|
|
|
+ container.attach({ stdout: 1, stderr: 1, stream: 1 }, (error, stream) => {
|
|
|
if (error != null) {
|
|
if (error != null) {
|
|
|
logger.error(
|
|
logger.error(
|
|
|
{ err: error, containerId },
|
|
{ err: error, containerId },
|
|
@@ -411,7 +414,7 @@ const DockerRunner = {
|
|
|
logger.log({ containerId }, 'attached to container')
|
|
logger.log({ containerId }, 'attached to container')
|
|
|
|
|
|
|
|
const MAX_OUTPUT = 1024 * 1024 // limit output to 1MB
|
|
const MAX_OUTPUT = 1024 * 1024 // limit output to 1MB
|
|
|
- const createStringOutputStream = function (name) {
|
|
|
|
|
|
|
+ function createStringOutputStream(name) {
|
|
|
return {
|
|
return {
|
|
|
data: '',
|
|
data: '',
|
|
|
overflowed: false,
|
|
overflowed: false,
|
|
@@ -463,14 +466,16 @@ const DockerRunner = {
|
|
|
const container = dockerode.getContainer(containerId)
|
|
const container = dockerode.getContainer(containerId)
|
|
|
|
|
|
|
|
let timedOut = false
|
|
let timedOut = false
|
|
|
- const timeoutId = setTimeout(function () {
|
|
|
|
|
|
|
+ const timeoutId = setTimeout(() => {
|
|
|
timedOut = true
|
|
timedOut = true
|
|
|
logger.log({ containerId }, 'timeout reached, killing container')
|
|
logger.log({ containerId }, 'timeout reached, killing container')
|
|
|
- container.kill(function () {})
|
|
|
|
|
|
|
+ container.kill((err) => {
|
|
|
|
|
+ logger.warn({ err, containerId }, 'failed to kill container')
|
|
|
|
|
+ })
|
|
|
}, timeout)
|
|
}, timeout)
|
|
|
|
|
|
|
|
logger.log({ containerId }, 'waiting for docker container')
|
|
logger.log({ containerId }, 'waiting for docker container')
|
|
|
- container.wait(function (error, res) {
|
|
|
|
|
|
|
+ container.wait((error, res) => {
|
|
|
if (error != null) {
|
|
if (error != null) {
|
|
|
clearTimeout(timeoutId)
|
|
clearTimeout(timeoutId)
|
|
|
logger.error({ err: error, containerId }, 'error waiting for container')
|
|
logger.error({ err: error, containerId }, 'error waiting for container')
|
|
@@ -514,7 +519,7 @@ const DockerRunner = {
|
|
|
_destroyContainer(containerId, shouldForce, callback) {
|
|
_destroyContainer(containerId, shouldForce, callback) {
|
|
|
logger.log({ containerId }, 'destroying docker container')
|
|
logger.log({ containerId }, 'destroying docker container')
|
|
|
const container = dockerode.getContainer(containerId)
|
|
const container = dockerode.getContainer(containerId)
|
|
|
- container.remove({ force: shouldForce === true }, function (error) {
|
|
|
|
|
|
|
+ container.remove({ force: shouldForce === true }, (error) => {
|
|
|
if (error != null && error.statusCode === 404) {
|
|
if (error != null && error.statusCode === 404) {
|
|
|
logger.warn(
|
|
logger.warn(
|
|
|
{ err: error, containerId },
|
|
{ err: error, containerId },
|
|
@@ -550,7 +555,7 @@ const DockerRunner = {
|
|
|
},
|
|
},
|
|
|
|
|
|
|
|
destroyOldContainers(callback) {
|
|
destroyOldContainers(callback) {
|
|
|
- dockerode.listContainers({ all: true }, function (error, containers) {
|
|
|
|
|
|
|
+ dockerode.listContainers({ all: true }, (error, containers) => {
|
|
|
if (error != null) {
|
|
if (error != null) {
|
|
|
return callback(error)
|
|
return callback(error)
|
|
|
}
|
|
}
|