mirror of https://github.com/docker/docs.git
240 lines
7.6 KiB
JavaScript
240 lines
7.6 KiB
JavaScript
var EventEmitter = require('events').EventEmitter;
|
|
var _ = require('underscore');
|
|
var path = require('path');
|
|
var fs = require('fs');
|
|
var Promise = require('bluebird');
|
|
var machine = require('./DockerMachine');
|
|
var virtualBox = require('./VirtualBox');
|
|
var setupUtil = require('./SetupUtil');
|
|
var util = require('./Util');
|
|
var assign = require('object-assign');
|
|
var metrics = require('./Metrics');
|
|
var bugsnag = require('bugsnag-js');
|
|
var rimraf = require('rimraf');
|
|
|
|
var _currentStep = null;
|
|
var _error = null;
|
|
var _cancelled = false;
|
|
var _retryPromise = null;
|
|
var _requiredSteps = [];
|
|
|
|
var _steps = [{
|
|
name: 'download',
|
|
title: 'Downloading VirtualBox',
|
|
message: 'VirtualBox is being downloaded. Kitematic requires VirtualBox to run containers.',
|
|
totalPercent: 35,
|
|
percent: 0,
|
|
run: function (progressCallback) {
|
|
var packagejson = util.packagejson();
|
|
return setupUtil.download(setupUtil.virtualBoxUrl(), path.join(util.supportDir(), packagejson['virtualbox-filename']), packagejson['virtualbox-checksum'], percent => {
|
|
progressCallback(percent);
|
|
});
|
|
}
|
|
}, {
|
|
name: 'install',
|
|
title: 'Installing VirtualBox & Docker',
|
|
message: 'VirtualBox & Docker are being installed or upgraded in the background. We may need you to type in your password to continue.',
|
|
totalPercent: 5,
|
|
percent: 0,
|
|
seconds: 5,
|
|
run: Promise.coroutine(function* (progressCallback) {
|
|
var cmd = setupUtil.copyBinariesCmd() + ' && ' + setupUtil.fixBinariesCmd();
|
|
if (!virtualBox.installed()) {
|
|
yield virtualBox.killall();
|
|
cmd += ' && ' + setupUtil.installVirtualBoxCmd();
|
|
} else {
|
|
if (!setupUtil.needsBinaryFix()) {
|
|
return;
|
|
}
|
|
}
|
|
try {
|
|
progressCallback(50); // TODO: detect when the installation has started so we can simulate progress
|
|
yield util.exec(setupUtil.macSudoCmd(cmd));
|
|
} catch (err) {
|
|
throw null;
|
|
}
|
|
})
|
|
}, {
|
|
name: 'init',
|
|
title: 'Starting Docker VM',
|
|
message: 'To run Docker containers on your computer, Kitematic is starting a Linux virtual machine. This may take a minute...',
|
|
totalPercent: 60,
|
|
percent: 0,
|
|
seconds: 53,
|
|
run: Promise.coroutine(function* (progressCallback) {
|
|
setupUtil.simulateProgress(this.seconds, progressCallback);
|
|
yield virtualBox.vmdestroy('kitematic-vm');
|
|
var exists = yield machine.exists();
|
|
if (!exists || (yield machine.state()) === 'Error') {
|
|
try {
|
|
yield machine.rm();
|
|
yield machine.create();
|
|
} catch (err) {
|
|
rimraf.sync(path.join(util.home(), '.docker', 'machine', 'machines', machine.name()));
|
|
yield machine.create();
|
|
}
|
|
return;
|
|
} else if (exists && (yield machine.state()) === 'Saved') {
|
|
yield virtualBox.wake(machine.name());
|
|
}
|
|
|
|
var isoversion = machine.isoversion();
|
|
var packagejson = util.packagejson();
|
|
if (!isoversion || setupUtil.compareVersions(isoversion, packagejson['docker-version']) < 0) {
|
|
yield machine.stop();
|
|
yield machine.upgrade();
|
|
}
|
|
yield machine.start();
|
|
})
|
|
}];
|
|
|
|
var SetupStore = assign(Object.create(EventEmitter.prototype), {
|
|
PROGRESS_EVENT: 'setup_progress',
|
|
STEP_EVENT: 'setup_step',
|
|
ERROR_EVENT: 'setup_error',
|
|
step: function () {
|
|
return _currentStep;
|
|
},
|
|
steps: function () {
|
|
return _.indexBy(_steps, 'name');
|
|
},
|
|
stepCount: function () {
|
|
return _requiredSteps.length;
|
|
},
|
|
number: function () {
|
|
return _.indexOf(_requiredSteps, _currentStep) + 1;
|
|
},
|
|
percent: function () {
|
|
var sofar = 0;
|
|
var totalPercent = _requiredSteps.reduce((prev, step) => prev + step.totalPercent, 0);
|
|
_.each(_requiredSteps, step => {
|
|
sofar += step.totalPercent * step.percent / 100;
|
|
});
|
|
return Math.min(Math.round(100 * sofar / totalPercent), 99);
|
|
},
|
|
error: function () {
|
|
return _error;
|
|
},
|
|
cancelled: function () {
|
|
return _cancelled;
|
|
},
|
|
retry: function () {
|
|
_error = null;
|
|
_cancelled = false;
|
|
if (_retryPromise) {
|
|
_retryPromise.resolve();
|
|
}
|
|
},
|
|
pause: function () {
|
|
_retryPromise = Promise.defer();
|
|
return _retryPromise.promise;
|
|
},
|
|
requiredSteps: Promise.coroutine(function* () {
|
|
if (_requiredSteps.length) {
|
|
return Promise.resolve(_requiredSteps);
|
|
}
|
|
var packagejson = util.packagejson();
|
|
var isoversion = machine.isoversion();
|
|
var required = {};
|
|
var vboxfile = path.join(util.supportDir(), packagejson['virtualbox-filename']);
|
|
var vboxNeedsInstall = !virtualBox.installed();
|
|
required.download = vboxNeedsInstall && (!fs.existsSync(vboxfile) || setupUtil.checksum(vboxfile) !== packagejson['virtualbox-checksum']);
|
|
required.install = vboxNeedsInstall || setupUtil.needsBinaryFix();
|
|
required.init = required.install || !(yield machine.exists()) || (yield machine.state()) !== 'Running' || !isoversion || setupUtil.compareVersions(isoversion, packagejson['docker-version']) < 0;
|
|
|
|
var exists = yield machine.exists();
|
|
if (isoversion && setupUtil.compareVersions(isoversion, packagejson['docker-version']) < 0) {
|
|
this.steps().init.seconds = 33;
|
|
} else if (exists && (yield machine.state()) === 'Saved') {
|
|
this.steps().init.seconds = 8;
|
|
} else if (exists && (yield machine.state()) !== 'Error') {
|
|
this.steps().init.seconds = 23;
|
|
}
|
|
|
|
_requiredSteps = _steps.filter(function (step) {
|
|
return required[step.name];
|
|
});
|
|
return Promise.resolve(_requiredSteps);
|
|
}),
|
|
updateBinaries: function () {
|
|
if (setupUtil.needsBinaryFix()) {
|
|
return Promise.resolve();
|
|
}
|
|
if (setupUtil.shouldUpdateBinaries()) {
|
|
return util.exec(setupUtil.copyBinariesCmd());
|
|
}
|
|
return Promise.resolve();
|
|
},
|
|
run: Promise.coroutine(function* () {
|
|
metrics.track('Started Setup', {
|
|
virtualbox: virtualBox.installed() ? yield virtualBox.version() : 'Not Installed'
|
|
});
|
|
yield this.updateBinaries();
|
|
var steps = yield this.requiredSteps();
|
|
for (let step of steps) {
|
|
console.log(step.name);
|
|
_currentStep = step;
|
|
step.percent = 0;
|
|
while (true) {
|
|
try {
|
|
this.emit(this.STEP_EVENT);
|
|
yield step.run(percent => {
|
|
if (_currentStep) {
|
|
step.percent = percent;
|
|
this.emit(this.PROGRESS_EVENT);
|
|
}
|
|
});
|
|
metrics.track('Setup Completed Step', {
|
|
name: step.name
|
|
});
|
|
step.percent = 100;
|
|
break;
|
|
} catch (err) {
|
|
if (err) {
|
|
throw err;
|
|
} else {
|
|
metrics.track('Setup Cancelled');
|
|
_cancelled = true;
|
|
this.emit(this.STEP_EVENT);
|
|
}
|
|
yield this.pause();
|
|
}
|
|
}
|
|
}
|
|
_currentStep = null;
|
|
return yield machine.ip();
|
|
}),
|
|
setup: Promise.coroutine(function * () {
|
|
while (true) {
|
|
try {
|
|
var ip = yield this.run();
|
|
if (!ip || !ip.length) {
|
|
throw {
|
|
message: 'Machine IP could not be fetched. Please retry the setup. If this fails please file a ticket on our GitHub repo.',
|
|
machine: yield machine.info(),
|
|
ip: ip,
|
|
};
|
|
} else {
|
|
metrics.track('Setup Finished');
|
|
return ip;
|
|
}
|
|
} catch (err) {
|
|
metrics.track('Setup Failed', {
|
|
step: _currentStep
|
|
});
|
|
var virtualboxVersion = virtualBox.installed() ? yield virtualBox.version() : 'Not installed';
|
|
bugsnag.notify('SetupError', 'Setup failed', {
|
|
error: err,
|
|
step: _currentStep,
|
|
virtualbox: virtualboxVersion
|
|
});
|
|
_error = err;
|
|
this.emit(this.ERROR_EVENT);
|
|
yield this.pause();
|
|
}
|
|
}
|
|
})
|
|
});
|
|
|
|
module.exports = SetupStore;
|