mirror of https://github.com/docker/docs.git
Setup fixes & unit tests
This commit is contained in:
parent
2c587445e9
commit
1445c62ed1
|
@ -0,0 +1 @@
|
||||||
|
### Manual tests
|
|
@ -13,7 +13,6 @@ describe('SetupStore', function () {
|
||||||
virtualBox.installed.mockReturnValue(false);
|
virtualBox.installed.mockReturnValue(false);
|
||||||
setupUtil.download.mockReturnValue(Promise.resolve());
|
setupUtil.download.mockReturnValue(Promise.resolve());
|
||||||
return setupStore.steps().download.run().then(() => {
|
return setupStore.steps().download.run().then(() => {
|
||||||
// TODO: make sure download was called with the right args
|
|
||||||
expect(setupUtil.download).toBeCalled();
|
expect(setupUtil.download).toBeCalled();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -30,26 +29,38 @@ describe('SetupStore', function () {
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('install step', function () {
|
describe('install step', function () {
|
||||||
|
util.exec.mockReturnValue(Promise.resolve());
|
||||||
|
util.copyBinariesCmd.mockReturnValue('copycmd');
|
||||||
|
util.fixBinariesCmd.mockReturnValue('fixcmd');
|
||||||
|
virtualBox.killall.mockReturnValue(Promise.resolve());
|
||||||
|
setupUtil.installVirtualBoxCmd.mockReturnValue('installvb');
|
||||||
|
setupUtil.macSudoCmd.mockImplementation(cmd => 'macsudo ' + cmd);
|
||||||
|
|
||||||
pit('installs virtualbox if it is not installed', function () {
|
pit('installs virtualbox if it is not installed', function () {
|
||||||
virtualBox.installed.mockReturnValue(false);
|
virtualBox.installed.mockReturnValue(false);
|
||||||
virtualBox.killall.mockReturnValue(Promise.resolve());
|
|
||||||
util.exec.mockReturnValue(Promise.resolve());
|
util.exec.mockReturnValue(Promise.resolve());
|
||||||
return setupStore.steps().install.run().then(() => {
|
return setupStore.steps().install.run().then(() => {
|
||||||
// TODO: make sure that the right install command was executed
|
expect(virtualBox.killall).toBeCalled();
|
||||||
expect(util.exec).toBeCalled();
|
expect(util.exec).toBeCalledWith('macsudo copycmd && fixcmd && installvbcmd');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
pit('installs virtualbox if it is installed but has an outdated version', function () {
|
pit('installs virtualbox if it is installed but has an outdated version', function () {
|
||||||
virtualBox.installed.mockReturnValue(true);
|
virtualBox.installed.mockReturnValue(true);
|
||||||
virtualBox.version.mockReturnValue(Promise.resolve('4.3.16'));
|
virtualBox.version.mockReturnValue(Promise.resolve('4.3.16'));
|
||||||
virtualBox.killall.mockReturnValue(Promise.resolve());
|
|
||||||
setupUtil.compareVersions.mockReturnValue(-1);
|
setupUtil.compareVersions.mockReturnValue(-1);
|
||||||
util.exec.mockReturnValue(Promise.resolve());
|
util.exec.mockReturnValue(Promise.resolve());
|
||||||
return setupStore.steps().install.run().then(() => {
|
return setupStore.steps().install.run().then(() => {
|
||||||
// TODO: make sure the right install command was executed
|
|
||||||
expect(virtualBox.killall).toBeCalled();
|
expect(virtualBox.killall).toBeCalled();
|
||||||
expect(util.exec).toBeCalled();
|
expect(util.exec).toBeCalledWith('macsudo copycmd && fixcmd && installvbcmd');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
pit('only installs binaries if virtualbox is installed', function () {
|
||||||
|
virtualBox.installed.mockReturnValue(true);
|
||||||
|
setupUtil.compareVersions.mockReturnValue(0);
|
||||||
|
return setupStore.steps().install.run().then(() => {
|
||||||
|
expect(util.exec).toBeCalledWith('macsudo copycmd && fixcmd');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -16,6 +16,7 @@ try {
|
||||||
process.env.NODE_PATH = __dirname + '/../node_modules';
|
process.env.NODE_PATH = __dirname + '/../node_modules';
|
||||||
process.env.RESOURCES_PATH = __dirname + '/../resources';
|
process.env.RESOURCES_PATH = __dirname + '/../resources';
|
||||||
process.chdir(path.join(__dirname, '..'));
|
process.chdir(path.join(__dirname, '..'));
|
||||||
|
process.env.PATH = '/usr/local/bin:' + process.env.PATH;
|
||||||
|
|
||||||
if (argv.integration) {
|
if (argv.integration) {
|
||||||
process.env.TEST_TYPE = 'integration';
|
process.env.TEST_TYPE = 'integration';
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -11,6 +11,7 @@ var ContainerUtil = require('./ContainerUtil');
|
||||||
|
|
||||||
var convert = new Convert();
|
var convert = new Convert();
|
||||||
var _recommended = [];
|
var _recommended = [];
|
||||||
|
var _placeholders = {};
|
||||||
var _containers = {};
|
var _containers = {};
|
||||||
var _progress = {};
|
var _progress = {};
|
||||||
var _logs = {};
|
var _logs = {};
|
||||||
|
@ -23,32 +24,8 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
||||||
SERVER_CONTAINER_EVENT: 'server_container_event',
|
SERVER_CONTAINER_EVENT: 'server_container_event',
|
||||||
SERVER_PROGRESS_EVENT: 'server_progress_event',
|
SERVER_PROGRESS_EVENT: 'server_progress_event',
|
||||||
SERVER_LOGS_EVENT: 'server_logs_event',
|
SERVER_LOGS_EVENT: 'server_logs_event',
|
||||||
_pullScratchImage: function (callback) {
|
|
||||||
var image = docker.client().getImage('scratch:latest');
|
|
||||||
image.inspect(function (err, data) {
|
|
||||||
if (!data) {
|
|
||||||
docker.client().pull('scratch:latest', function (err, stream) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
stream.setEncoding('utf8');
|
|
||||||
stream.on('data', function () {});
|
|
||||||
stream.on('end', function () {
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
callback();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
_pullImage: function (repository, tag, callback, progressCallback) {
|
_pullImage: function (repository, tag, callback, progressCallback) {
|
||||||
registry.layers(repository, tag, function (err, layerSizes) {
|
registry.layers(repository, tag, function (err, layerSizes) {
|
||||||
|
|
||||||
// TODO: Support v2 registry API
|
|
||||||
// TODO: clean this up- It's messy to work with pulls from both the v1 and v2 registry APIs
|
|
||||||
// Use the per-layer pull progress % to update the total progress.
|
|
||||||
docker.client().listImages({all: 1}, function(err, images) {
|
docker.client().listImages({all: 1}, function(err, images) {
|
||||||
var existingIds = new Set(images.map(function (image) {
|
var existingIds = new Set(images.map(function (image) {
|
||||||
return image.Id.slice(0, 12);
|
return image.Id.slice(0, 12);
|
||||||
|
@ -162,29 +139,14 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
_createPlaceholderContainer: function (imageName, name, callback) {
|
_createPlaceholderContainer: function (imageName, name, callback) {
|
||||||
var self = this;
|
if (_placeholders[name]) {
|
||||||
this._pullScratchImage(function (err) {
|
delete _placeholders[name];
|
||||||
if (err) {
|
}
|
||||||
callback(err);
|
_placeholders[name] = {
|
||||||
return;
|
State: {
|
||||||
}
|
}
|
||||||
docker.client().createContainer({
|
};
|
||||||
Image: 'scratch:latest',
|
return _placeholders[name];
|
||||||
Tty: false,
|
|
||||||
Env: [
|
|
||||||
'KITEMATIC_DOWNLOADING=true',
|
|
||||||
'KITEMATIC_DOWNLOADING_IMAGE=' + imageName
|
|
||||||
],
|
|
||||||
Cmd: 'placeholder',
|
|
||||||
name: name
|
|
||||||
}, function (err) {
|
|
||||||
if (err) {
|
|
||||||
callback(err);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.fetchContainer(name, callback);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
_generateName: function (repository) {
|
_generateName: function (repository) {
|
||||||
var base = _.last(repository.split('/'));
|
var base = _.last(repository.split('/'));
|
||||||
|
@ -386,28 +348,24 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
||||||
var self = this;
|
var self = this;
|
||||||
var imageName = repository + ':' + tag;
|
var imageName = repository + ':' + tag;
|
||||||
var containerName = this._generateName(repository);
|
var containerName = this._generateName(repository);
|
||||||
// Pull image
|
|
||||||
self._createPlaceholderContainer(imageName, containerName, function (err, container) {
|
// Create placeholder container
|
||||||
if (err) {
|
var container = this._createPlaceholderContainer(imageName, containerName);
|
||||||
callback(err);
|
_containers[containerName] = container;
|
||||||
return;
|
self.emit(self.CLIENT_CONTAINER_EVENT, containerName, 'create');
|
||||||
}
|
_muted[containerName] = true;
|
||||||
_containers[containerName] = container;
|
_progress[containerName] = 0;
|
||||||
self.emit(self.CLIENT_CONTAINER_EVENT, containerName, 'create');
|
self._pullImage(repository, tag, function () {
|
||||||
_muted[containerName] = true;
|
self._createContainer(containerName, {Image: imageName}, function () {
|
||||||
_progress[containerName] = 0;
|
delete _progress[containerName];
|
||||||
self._pullImage(repository, tag, function () {
|
_muted[containerName] = false;
|
||||||
self._createContainer(containerName, {Image: imageName}, function () {
|
self.emit(self.CLIENT_CONTAINER_EVENT, containerName);
|
||||||
delete _progress[containerName];
|
|
||||||
_muted[containerName] = false;
|
|
||||||
self.emit(self.CLIENT_CONTAINER_EVENT, containerName);
|
|
||||||
});
|
|
||||||
}, function (progress) {
|
|
||||||
_progress[containerName] = progress;
|
|
||||||
self.emit(self.SERVER_PROGRESS_EVENT, containerName);
|
|
||||||
});
|
});
|
||||||
callback(null, containerName);
|
}, function (progress) {
|
||||||
|
_progress[containerName] = progress;
|
||||||
|
self.emit(self.SERVER_PROGRESS_EVENT, containerName);
|
||||||
});
|
});
|
||||||
|
callback(null, containerName);
|
||||||
},
|
},
|
||||||
updateContainer: function (name, data, callback) {
|
updateContainer: function (name, data, callback) {
|
||||||
_muted[name] = true;
|
_muted[name] = true;
|
||||||
|
|
|
@ -43,7 +43,7 @@ var Setup = React.createClass({
|
||||||
},
|
},
|
||||||
renderContents: function () {
|
renderContents: function () {
|
||||||
var img = 'virtualbox.png';
|
var img = 'virtualbox.png';
|
||||||
if (SetupStore.step().name.indexOf('Boot2Docker') !== -1) {
|
if (SetupStore.step().name.indexOf('start') !== -1 || SetupStore.step().name.indexOf('init') !== -1) {
|
||||||
img = 'boot2docker.png';
|
img = 'boot2docker.png';
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
var EventEmitter = require('events').EventEmitter;
|
var EventEmitter = require('events').EventEmitter;
|
||||||
var _ = require('underscore');
|
var _ = require('underscore');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
var fs = require('fs');
|
||||||
var Promise = require('bluebird');
|
var Promise = require('bluebird');
|
||||||
var boot2docker = require('./Boot2Docker');
|
var boot2docker = require('./Boot2Docker');
|
||||||
var virtualBox = require('./VirtualBox');
|
var virtualBox = require('./VirtualBox');
|
||||||
|
@ -20,13 +21,12 @@ var _steps = [{
|
||||||
message: 'VirtualBox is being downloaded. Kitematic requires VirtualBox to run containers.',
|
message: 'VirtualBox is being downloaded. Kitematic requires VirtualBox to run containers.',
|
||||||
totalPercent: 35,
|
totalPercent: 35,
|
||||||
percent: 0,
|
percent: 0,
|
||||||
run: Promise.coroutine(function* (progressCallback) {
|
run: function (progressCallback) {
|
||||||
var packagejson = util.packagejson();
|
var packagejson = util.packagejson();
|
||||||
var virtualBoxFile = `https://github.com/kitematic/virtualbox/releases/download/${packagejson['virtualbox-version']}/${packagejson['virtualbox-filename']}`;
|
return setupUtil.download(setupUtil.virtualBoxUrl(), path.join(util.supportDir(), packagejson['virtualbox-filename']), packagejson['virtualbox-checksum'], percent => {
|
||||||
yield setupUtil.download(virtualBoxFile, path.join(util.supportDir(), packagejson['virtualbox-filename']), packagejson['virtualbox-checksum'], percent => {
|
|
||||||
progressCallback(percent);
|
progressCallback(percent);
|
||||||
});
|
});
|
||||||
})
|
}
|
||||||
}, {
|
}, {
|
||||||
name: 'install',
|
name: 'install',
|
||||||
title: 'Installing Docker & VirtualBox',
|
title: 'Installing Docker & VirtualBox',
|
||||||
|
@ -34,16 +34,16 @@ var _steps = [{
|
||||||
totalPercent: 5,
|
totalPercent: 5,
|
||||||
percent: 0,
|
percent: 0,
|
||||||
seconds: 5,
|
seconds: 5,
|
||||||
run: Promise.coroutine(function* () {
|
run: Promise.coroutine(function* (progressCallback) {
|
||||||
var packagejson = util.packagejson();
|
var packagejson = util.packagejson();
|
||||||
var base = util.copyBinariesCmd() + ' && ' + util.fixBinariesCmd();
|
var cmd = util.copyBinariesCmd() + ' && ' + util.fixBinariesCmd();
|
||||||
if (!virtualBox.installed() || setupUtil.compareVersions(yield virtualBox.version(), packagejson['virtualbox-required-version']) < 0) {
|
if (!virtualBox.installed() || setupUtil.compareVersions(yield virtualBox.version(), packagejson['virtualbox-required-version']) < 0) {
|
||||||
yield virtualBox.killall();
|
yield virtualBox.killall();
|
||||||
base += ` && installer -pkg ${path.join(util.supportDir(), packagejson['virtualbox-filename'])} -target /`;
|
cmd += ' && ' + setupUtil.installVirtualBoxCmd();
|
||||||
}
|
}
|
||||||
var cmd = `${util.escapePath(path.join(util.resourceDir(), 'cocoasudo'))} --prompt="Kitematic requires administrative privileges to install VirtualBox." bash -c \"${base}\"`;
|
|
||||||
try {
|
try {
|
||||||
yield util.exec(cmd);
|
progressCallback(50); // TODO: detect when the installation has started so we can simulate progress
|
||||||
|
yield util.exec(setupUtil.macSudoCmd(cmd));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
throw null;
|
throw null;
|
||||||
}
|
}
|
||||||
|
@ -130,12 +130,16 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
|
||||||
_retryPromise = Promise.defer();
|
_retryPromise = Promise.defer();
|
||||||
return _retryPromise.promise;
|
return _retryPromise.promise;
|
||||||
},
|
},
|
||||||
init: Promise.coroutine(function* () {
|
requiredSteps: Promise.coroutine(function* () {
|
||||||
|
if (_requiredSteps.length) {
|
||||||
|
return Promise.resolve(_requiredSteps);
|
||||||
|
}
|
||||||
var packagejson = util.packagejson();
|
var packagejson = util.packagejson();
|
||||||
var isoversion = boot2docker.isoversion();
|
var isoversion = boot2docker.isoversion();
|
||||||
var required = {};
|
var required = {};
|
||||||
required.download = !virtualBox.installed() || setupUtil.compareVersions(yield virtualBox.version(), packagejson['virtualbox-required-version']) < 0;
|
var vboxfile = path.join(util.supportDir(), packagejson['virtualbox-filename']);
|
||||||
required.install = required.download || setupUtil.needsBinaryFix();
|
required.download = !virtualBox.installed() && (!fs.existsSync(vboxfile) || setupUtil.checksum(vboxfile) !== packagejson['virtualbox-checksum']);
|
||||||
|
required.install = !virtualBox.installed() || setupUtil.needsBinaryFix();
|
||||||
required.init = !(yield boot2docker.exists()) || !isoversion || setupUtil.compareVersions(isoversion, boot2docker.version()) < 0;
|
required.init = !(yield boot2docker.exists()) || !isoversion || setupUtil.compareVersions(isoversion, boot2docker.version()) < 0;
|
||||||
required.start = required.init || (yield boot2docker.status()) !== 'running';
|
required.start = required.init || (yield boot2docker.status()) !== 'running';
|
||||||
|
|
||||||
|
@ -147,6 +151,7 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
|
||||||
_requiredSteps = _steps.filter(function (step) {
|
_requiredSteps = _steps.filter(function (step) {
|
||||||
return required[step.name];
|
return required[step.name];
|
||||||
});
|
});
|
||||||
|
return Promise.resolve(_requiredSteps);
|
||||||
}),
|
}),
|
||||||
updateBinaries: function () {
|
updateBinaries: function () {
|
||||||
if (setupUtil.needsBinaryFix()) {
|
if (setupUtil.needsBinaryFix()) {
|
||||||
|
@ -158,9 +163,9 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
|
||||||
return Promise.resolve();
|
return Promise.resolve();
|
||||||
},
|
},
|
||||||
run: Promise.coroutine(function* () {
|
run: Promise.coroutine(function* () {
|
||||||
yield this.init();
|
|
||||||
yield this.updateBinaries();
|
yield this.updateBinaries();
|
||||||
for (let step of _requiredSteps) {
|
var steps = yield this.requiredSteps();
|
||||||
|
for (let step of steps) {
|
||||||
_currentStep = step;
|
_currentStep = step;
|
||||||
step.percent = 0;
|
step.percent = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -176,7 +181,6 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
|
||||||
break;
|
break;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.log(err.stack);
|
|
||||||
_error = err;
|
_error = err;
|
||||||
this.emit(this.ERROR_EVENT);
|
this.emit(this.ERROR_EVENT);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -29,6 +29,17 @@ var SetupUtil = {
|
||||||
this.checksum('/usr/local/bin/boot2docker') !== this.checksum(path.join(util.resourceDir(), 'boot2docker-' + packagejson['boot2docker-version'])) ||
|
this.checksum('/usr/local/bin/boot2docker') !== this.checksum(path.join(util.resourceDir(), 'boot2docker-' + packagejson['boot2docker-version'])) ||
|
||||||
this.checksum('/usr/local/bin/docker') !== this.checksum(path.join(util.resourceDir(), 'docker-' + packagejson['docker-version']));
|
this.checksum('/usr/local/bin/docker') !== this.checksum(path.join(util.resourceDir(), 'docker-' + packagejson['docker-version']));
|
||||||
},
|
},
|
||||||
|
installVirtualBoxCmd: function () {
|
||||||
|
var packagejson = util.packagejson();
|
||||||
|
return `installer -pkg ${util.escapePath(path.join(util.supportDir(), packagejson['virtualbox-filename']))} -target /`;
|
||||||
|
},
|
||||||
|
virtualBoxUrl: function () {
|
||||||
|
var packagejson = util.packagejson();
|
||||||
|
return `https://github.com/kitematic/virtualbox/releases/download/${packagejson['virtualbox-version']}/${packagejson['virtualbox-filename']}`;
|
||||||
|
},
|
||||||
|
macSudoCmd: function (cmd) {
|
||||||
|
return `${util.escapePath(path.join(util.resourceDir(), 'macsudo'))} -p "Kitematic requires administrative privileges to install VirtualBox." sh -c \"${cmd}\"`;
|
||||||
|
},
|
||||||
simulateProgress: function (estimateSeconds, progress) {
|
simulateProgress: function (estimateSeconds, progress) {
|
||||||
var times = _.range(0, estimateSeconds * 1000, 200);
|
var times = _.range(0, estimateSeconds * 1000, 200);
|
||||||
var timers = [];
|
var timers = [];
|
||||||
|
|
Loading…
Reference in New Issue