Make addons code remove a BoxError
This commit is contained in:
107
src/docker.js
107
src/docker.js
@@ -1,8 +1,6 @@
|
||||
'use strict';
|
||||
|
||||
exports = module.exports = {
|
||||
connection: connectionInstance(),
|
||||
|
||||
testRegistryConfig: testRegistryConfig,
|
||||
setRegistryConfig: setRegistryConfig,
|
||||
injectPrivateFields: injectPrivateFields,
|
||||
@@ -27,6 +25,7 @@ exports = module.exports = {
|
||||
getContainerIdByIp: getContainerIdByIp,
|
||||
inspect: inspect,
|
||||
inspectByName: inspect,
|
||||
execContainer: execContainer,
|
||||
getEvents: getEvents,
|
||||
memoryUsage: memoryUsage,
|
||||
createVolume: createVolume,
|
||||
@@ -34,20 +33,14 @@ exports = module.exports = {
|
||||
clearVolume: clearVolume
|
||||
};
|
||||
|
||||
// timeout is optional
|
||||
function connectionInstance(timeout) {
|
||||
var Docker = require('dockerode');
|
||||
var docker = new Docker({ socketPath: '/var/run/docker.sock', timeout: timeout });
|
||||
return docker;
|
||||
}
|
||||
|
||||
var addons = require('./addons.js'),
|
||||
async = require('async'),
|
||||
assert = require('assert'),
|
||||
BoxError = require('./boxerror.js'),
|
||||
child_process = require('child_process'),
|
||||
constants = require('./constants.js'),
|
||||
debug = require('debug')('box:docker.js'),
|
||||
debug = require('debug')('box:gConnection.js'),
|
||||
Docker = require('dockerode'),
|
||||
path = require('path'),
|
||||
settings = require('./settings.js'),
|
||||
shell = require('./shell.js'),
|
||||
@@ -58,6 +51,8 @@ var addons = require('./addons.js'),
|
||||
const CLEARVOLUME_CMD = path.join(__dirname, 'scripts/clearvolume.sh'),
|
||||
MKDIRVOLUME_CMD = path.join(__dirname, 'scripts/mkdirvolume.sh');
|
||||
|
||||
const gConnection = new Docker({ socketPath: '/var/run/docker.sock' });
|
||||
|
||||
function debugApp(app) {
|
||||
assert(typeof app === 'object');
|
||||
|
||||
@@ -68,8 +63,7 @@ function testRegistryConfig(auth, callback) {
|
||||
assert.strictEqual(typeof auth, 'object');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
let docker = exports.connection;
|
||||
docker.checkAuth(auth, function (error /*, data */) { // this returns a 500 even for auth errors
|
||||
gConnection.checkAuth(auth, function (error /*, data */) { // this returns a 500 even for auth errors
|
||||
if (error) return callback(new BoxError(BoxError.BAD_FIELD, error, { field: 'serverAddress' }));
|
||||
|
||||
callback();
|
||||
@@ -108,9 +102,9 @@ function ping(callback) {
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
// do not let the request linger
|
||||
var docker = connectionInstance(1000);
|
||||
const connection = new Docker({ socketPath: '/var/run/gConnection.sock', timeout: 1000 });
|
||||
|
||||
docker.ping(function (error, result) {
|
||||
connection.ping(function (error, result) {
|
||||
if (error) return callback(new BoxError(BoxError.DOCKER_ERROR, error));
|
||||
if (result !== 'OK') return callback(new BoxError(BoxError.DOCKER_ERROR, 'Unable to ping the docker daemon'));
|
||||
|
||||
@@ -140,14 +134,12 @@ function getRegistryConfig(image, callback) {
|
||||
}
|
||||
|
||||
function pullImage(manifest, callback) {
|
||||
var docker = exports.connection;
|
||||
|
||||
getRegistryConfig(manifest.dockerImage, function (error, authConfig) {
|
||||
if (error) return callback(error);
|
||||
|
||||
debug(`pullImage: will pull ${manifest.dockerImage}. auth: ${authConfig ? 'yes' : 'no'}`);
|
||||
|
||||
docker.pull(manifest.dockerImage, { authconfig: authConfig }, function (error, stream) {
|
||||
gConnection.pull(manifest.dockerImage, { authconfig: authConfig }, function (error, stream) {
|
||||
if (error) return callback(new BoxError(BoxError.DOCKER_ERROR, 'Unable to pull image. Please check the network or if the image needs authentication. statusCode: ' + error.statusCode));
|
||||
|
||||
// https://github.com/dotcloud/docker/issues/1074 says each status message
|
||||
@@ -203,8 +195,7 @@ function createSubcontainer(app, name, cmd, options, callback) {
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
var docker = exports.connection,
|
||||
isAppContainer = !cmd; // non app-containers are like scheduler and exec (terminal) containers
|
||||
let isAppContainer = !cmd; // non app-containers are like scheduler and exec (terminal) containers
|
||||
|
||||
var manifest = app.manifest;
|
||||
var exposedPorts = {}, dockerPortBindings = { };
|
||||
@@ -330,7 +321,7 @@ function createSubcontainer(app, name, cmd, options, callback) {
|
||||
|
||||
debugApp(app, 'Creating container for %s', app.manifest.dockerImage);
|
||||
|
||||
docker.createContainer(containerOptions, function (error, container) {
|
||||
gConnection.createContainer(containerOptions, function (error, container) {
|
||||
if (error) return callback(new BoxError(BoxError.DOCKER_ERROR, error));
|
||||
|
||||
callback(null, container);
|
||||
@@ -346,9 +337,7 @@ function startContainer(containerId, callback) {
|
||||
assert.strictEqual(typeof containerId, 'string');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
var docker = exports.connection;
|
||||
|
||||
var container = docker.getContainer(containerId);
|
||||
var container = gConnection.getContainer(containerId);
|
||||
debug('Starting container %s', containerId);
|
||||
|
||||
container.start(function (error) {
|
||||
@@ -369,8 +358,7 @@ function stopContainer(containerId, callback) {
|
||||
return callback();
|
||||
}
|
||||
|
||||
var docker = exports.connection;
|
||||
var container = docker.getContainer(containerId);
|
||||
var container = gConnection.getContainer(containerId);
|
||||
debug('Stopping container %s', containerId);
|
||||
|
||||
var options = {
|
||||
@@ -400,8 +388,7 @@ function deleteContainer(containerId, callback) {
|
||||
|
||||
if (containerId === null) return callback(null);
|
||||
|
||||
var docker = exports.connection;
|
||||
var container = docker.getContainer(containerId);
|
||||
var container = gConnection.getContainer(containerId);
|
||||
|
||||
var removeOptions = {
|
||||
force: true, // kill container if it's running
|
||||
@@ -425,14 +412,12 @@ function deleteContainers(appId, options, callback) {
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
var docker = exports.connection;
|
||||
|
||||
debug('deleting containers of %s', appId);
|
||||
|
||||
let labels = [ 'appId=' + appId ];
|
||||
if (options.managedOnly) labels.push('isCloudronManaged=true');
|
||||
|
||||
docker.listContainers({ all: 1, filters: JSON.stringify({ label: labels }) }, function (error, containers) {
|
||||
gConnection.listContainers({ all: 1, filters: JSON.stringify({ label: labels }) }, function (error, containers) {
|
||||
if (error) return callback(new BoxError(BoxError.DOCKER_ERROR, error));
|
||||
|
||||
async.eachSeries(containers, function (container, iteratorDone) {
|
||||
@@ -445,11 +430,9 @@ function stopContainers(appId, callback) {
|
||||
assert.strictEqual(typeof appId, 'string');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
var docker = exports.connection;
|
||||
|
||||
debug('stopping containers of %s', appId);
|
||||
|
||||
docker.listContainers({ all: 1, filters: JSON.stringify({ label: [ 'appId=' + appId ] }) }, function (error, containers) {
|
||||
gConnection.listContainers({ all: 1, filters: JSON.stringify({ label: [ 'appId=' + appId ] }) }, function (error, containers) {
|
||||
if (error) return callback(new BoxError(BoxError.DOCKER_ERROR, error));
|
||||
|
||||
async.eachSeries(containers, function (container, iteratorDone) {
|
||||
@@ -465,8 +448,6 @@ function deleteImage(manifest, callback) {
|
||||
var dockerImage = manifest ? manifest.dockerImage : null;
|
||||
if (!dockerImage) return callback(null);
|
||||
|
||||
var docker = exports.connection;
|
||||
|
||||
var removeOptions = {
|
||||
force: false, // might be shared with another instance of this app
|
||||
noprune: false // delete untagged parents
|
||||
@@ -475,7 +456,7 @@ function deleteImage(manifest, callback) {
|
||||
// registry v1 used to pull down all *tags*. this meant that deleting image by tag was not enough (since that
|
||||
// just removes the tag). we used to remove the image by id. this is not required anymore because aliases are
|
||||
// not created anymore after https://github.com/docker/docker/pull/10571
|
||||
docker.getImage(dockerImage).remove(removeOptions, function (error) {
|
||||
gConnection.getImage(dockerImage).remove(removeOptions, function (error) {
|
||||
if (error && error.statusCode === 400) return callback(null); // invalid image format. this can happen if user installed with a bad --docker-image
|
||||
if (error && error.statusCode === 404) return callback(null); // not found
|
||||
if (error && error.statusCode === 409) return callback(null); // another container using the image
|
||||
@@ -493,9 +474,7 @@ function getContainerIdByIp(ip, callback) {
|
||||
assert.strictEqual(typeof ip, 'string');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
var docker = exports.connection;
|
||||
|
||||
docker.getNetwork('cloudron').inspect(function (error, bridge) {
|
||||
gConnection.getNetwork('cloudron').inspect(function (error, bridge) {
|
||||
if (error && error.statusCode === 404) return callback(new BoxError(BoxError.DOCKER_ERROR, 'Unable to find the cloudron network'));
|
||||
if (error) return callback(new BoxError(BoxError.DOCKER_ERROR, error));
|
||||
|
||||
@@ -516,7 +495,7 @@ function inspect(containerId, callback) {
|
||||
assert.strictEqual(typeof containerId, 'string');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
var container = exports.connection.getContainer(containerId);
|
||||
var container = gConnection.getContainer(containerId);
|
||||
|
||||
container.inspect(function (error, result) {
|
||||
if (error && error.statusCode === 404) return callback(new BoxError(BoxError.NOT_FOUND));
|
||||
@@ -526,13 +505,38 @@ function inspect(containerId, callback) {
|
||||
});
|
||||
}
|
||||
|
||||
function execContainer(containerId, options, callback) {
|
||||
assert.strictEqual(typeof containerId, 'string');
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
var container = gConnection.getContainer(containerId);
|
||||
|
||||
container.exec(options.execOptions, function (error, exec) {
|
||||
if (error && error.statusCode === 409) return callback(new BoxError(BoxError.BAD_STATE, error.message)); // container restarting/not running
|
||||
if (error) return callback(new BoxError(BoxError.DOCKER_ERROR, error));
|
||||
|
||||
exec.start(options.startOptions, function(error, stream /* in hijacked mode, this is a net.socket */) {
|
||||
if (error) return callback(new BoxError(BoxError.DOCKER_ERROR, error));
|
||||
|
||||
if (options.rows && options.columns) {
|
||||
// there is a race where resizing too early results in a 404 "no such exec"
|
||||
// https://git.cloudron.io/cloudron/box/issues/549
|
||||
setTimeout(function () {
|
||||
exec.resize({ h: options.rows, w: options.columns }, function (error) { if (error) debug('Error resizing console', error); });
|
||||
}, 2000);
|
||||
}
|
||||
|
||||
callback(null, stream);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function getEvents(options, callback) {
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
let docker = exports.connection;
|
||||
|
||||
docker.getEvents(options, function (error, stream) {
|
||||
gConnection.getEvents(options, function (error, stream) {
|
||||
if (error) return callback(new BoxError(BoxError.DOCKER_ERROR, error));
|
||||
|
||||
callback(null, stream);
|
||||
@@ -543,7 +547,7 @@ function memoryUsage(containerId, callback) {
|
||||
assert.strictEqual(typeof containerId, 'string');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
var container = exports.connection.getContainer(containerId);
|
||||
var container = gConnection.getContainer(containerId);
|
||||
|
||||
container.stats({ stream: false }, function (error, result) {
|
||||
if (error && error.statusCode === 404) return callback(new BoxError(BoxError.NOT_FOUND));
|
||||
@@ -559,8 +563,6 @@ function createVolume(app, name, volumeDataDir, callback) {
|
||||
assert.strictEqual(typeof volumeDataDir, 'string');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
let docker = exports.connection;
|
||||
|
||||
const volumeOptions = {
|
||||
Name: name,
|
||||
Driver: 'local',
|
||||
@@ -579,7 +581,7 @@ function createVolume(app, name, volumeDataDir, callback) {
|
||||
shell.sudo('createVolume', [ MKDIRVOLUME_CMD, volumeDataDir ], {}, function (error) {
|
||||
if (error) return callback(new BoxError(BoxError.FS_ERROR, `Error creating app data dir: ${error.message}`));
|
||||
|
||||
docker.createVolume(volumeOptions, function (error) {
|
||||
gConnection.createVolume(volumeOptions, function (error) {
|
||||
if (error) return callback(new BoxError(BoxError.DOCKER_ERROR, error));
|
||||
|
||||
callback();
|
||||
@@ -593,8 +595,7 @@ function clearVolume(app, name, options, callback) {
|
||||
assert.strictEqual(typeof options, 'object');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
let docker = exports.connection;
|
||||
let volume = docker.getVolume(name);
|
||||
let volume = gConnection.getVolume(name);
|
||||
volume.inspect(function (error, v) {
|
||||
if (error && error.statusCode === 404) return callback();
|
||||
if (error) return callback(new BoxError(BoxError.DOCKER_ERROR, error));
|
||||
@@ -614,9 +615,7 @@ function removeVolume(app, name, callback) {
|
||||
assert.strictEqual(typeof name, 'string');
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
let docker = exports.connection;
|
||||
|
||||
let volume = docker.getVolume(name);
|
||||
let volume = gConnection.getVolume(name);
|
||||
volume.remove(function (error) {
|
||||
if (error && error.statusCode !== 404) return callback(new BoxError(BoxError.DOCKER_ERROR, `removeVolume: Error removing volume of ${app.id} ${error.message}`));
|
||||
|
||||
@@ -627,9 +626,7 @@ function removeVolume(app, name, callback) {
|
||||
function info(callback) {
|
||||
assert.strictEqual(typeof callback, 'function');
|
||||
|
||||
let docker = exports.connection;
|
||||
|
||||
docker.info(function (error, result) {
|
||||
gConnection.info(function (error, result) {
|
||||
if (error) return callback(new BoxError(BoxError.DOCKER_ERROR, 'Error connecting to docker'));
|
||||
|
||||
callback(null, result);
|
||||
|
||||
Reference in New Issue
Block a user