зеркало из https://github.com/docker/kitematic.git
0.5.3 setup stability, errors & retrying
This commit is contained in:
Родитель
bf0abc1d2c
Коммит
9b32a6a680
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "Kitematic",
|
||||
"version": "0.5.2",
|
||||
"version": "0.5.3",
|
||||
"author": "Kitematic",
|
||||
"description": "Simple Docker Container management for Mac OS X.",
|
||||
"homepage": "https://kitematic.com/",
|
||||
|
|
|
@ -28,7 +28,7 @@ var ContainerDetail = React.createClass({
|
|||
<div className="details">
|
||||
<ContainerDetailsHeader container={this.props.container}/>
|
||||
<ContainerDetailsSubheader container={this.props.container} />
|
||||
<Router.RouteHandler container={this.props.container}/>
|
||||
<Router.RouteHandler container={this.props.container} error={this.props.error}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ var ContainerHomePreview = require('./ContainerHomePreview.react');
|
|||
var ContainerHomeLogs = require('./ContainerHomeLogs.react');
|
||||
var ContainerHomeFolders = require('./ContainerHomeFolders.react');
|
||||
var ContainerUtil = require('./ContainerUtil');
|
||||
var webPorts = require('./Util').webPorts;
|
||||
var util = require('./Util');
|
||||
|
||||
var resizeWindow = function () {
|
||||
$('.left .wrapper').height(window.innerHeight - 240);
|
||||
|
@ -27,6 +27,9 @@ var ContainerHome = React.createClass({
|
|||
handleResize: function () {
|
||||
resizeWindow();
|
||||
},
|
||||
handleErrorClick: function () {
|
||||
util.exec(['open', 'https://github.com/kitematic/kitematic/issues/new']);
|
||||
},
|
||||
componentWillReceiveProps: function () {
|
||||
this.init();
|
||||
},
|
||||
|
@ -52,7 +55,7 @@ var ContainerHome = React.createClass({
|
|||
this.setState({
|
||||
ports: ports,
|
||||
defaultPort: _.find(_.keys(ports), function (port) {
|
||||
return webPorts.indexOf(port) !== -1;
|
||||
return util.webPorts.indexOf(port) !== -1;
|
||||
}),
|
||||
progress: ContainerStore.progress(this.getParams().name),
|
||||
blocked: ContainerStore.blocked(this.getParams().name)
|
||||
|
@ -68,7 +71,14 @@ var ContainerHome = React.createClass({
|
|||
},
|
||||
render: function () {
|
||||
var body;
|
||||
if (this.props.container && this.props.container.State.Downloading) {
|
||||
if (this.props.error) {
|
||||
body = (
|
||||
<div className="details-progress">
|
||||
<h3>There was a problem connecting to the Docker Engine.<br/>Either the VirtualBox VM was removed, is not responding or Docker is not running inside of it. Try restarting Kitematic. If the issue persists, please <a onClick={this.handleErrorClick}>file a ticket on our GitHub repo.</a></h3>
|
||||
<Radial progress={100} error={true} thick={true} transparent={true}/>
|
||||
</div>
|
||||
);
|
||||
} else if (this.props.container && this.props.container.State.Downloading) {
|
||||
if (this.state.progress) {
|
||||
body = (
|
||||
<div className="details-progress">
|
||||
|
|
|
@ -7,17 +7,20 @@ var docker = require('./Docker');
|
|||
var metrics = require('./Metrics');
|
||||
var registry = require('./Registry');
|
||||
var LogStore = require('./LogStore');
|
||||
var bugsnag = require('bugsnag-js');
|
||||
|
||||
var _placeholders = {};
|
||||
var _containers = {};
|
||||
var _progress = {};
|
||||
var _muted = {};
|
||||
var _blocked = {};
|
||||
var _error = null;
|
||||
|
||||
var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
||||
CLIENT_CONTAINER_EVENT: 'client_container_event',
|
||||
SERVER_CONTAINER_EVENT: 'server_container_event',
|
||||
SERVER_PROGRESS_EVENT: 'server_progress_event',
|
||||
SERVER_ERROR_EVENT: 'server_error_event',
|
||||
_pullImage: function (repository, tag, callback, progressCallback, blockedCallback) {
|
||||
registry.layers(repository, tag, (err, layerSizes) => {
|
||||
|
||||
|
@ -35,6 +38,10 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
|
||||
var totalBytes = layersToDownload.map(function (s) { return s.size; }).reduce(function (pv, sv) { return pv + sv; }, 0);
|
||||
docker.client().pull(repository + ':' + tag, (err, stream) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
stream.setEncoding('utf8');
|
||||
|
||||
var layerProgress = layersToDownload.reduce(function (r, layer) {
|
||||
|
@ -50,7 +57,7 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
var data = JSON.parse(str);
|
||||
console.log(data);
|
||||
|
||||
if (data.status === 'Pulling dependent layers') {
|
||||
if (data.status === 'Pulling dependent layers' || data.status.indexOf('already being pulled by another client') !== -1) {
|
||||
blockedCallback();
|
||||
return;
|
||||
}
|
||||
|
@ -153,7 +160,7 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
}
|
||||
}
|
||||
},
|
||||
_resumePulling: function () {
|
||||
_resumePulling: function (callback) {
|
||||
var downloading = _.filter(_.values(this.containers()), function (container) {
|
||||
return container.State.Downloading;
|
||||
});
|
||||
|
@ -163,12 +170,20 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
downloading.forEach(function (container) {
|
||||
_progress[container.Name] = 99;
|
||||
docker.client().pull(container.Config.Image, function (err, stream) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
stream.setEncoding('utf8');
|
||||
stream.on('data', function () {});
|
||||
stream.on('end', function () {
|
||||
delete _placeholders[container.Name];
|
||||
localStorage.setItem('store.placeholders', JSON.stringify(_placeholders));
|
||||
self._createContainer(container.Name, {Image: container.Config.Image}, function () {
|
||||
self._createContainer(container.Name, {Image: container.Config.Image}, err => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
self.emit(self.SERVER_PROGRESS_EVENT, container.Name);
|
||||
self.emit(self.CLIENT_CONTAINER_EVENT, container.Name);
|
||||
});
|
||||
|
@ -176,13 +191,17 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
});
|
||||
});
|
||||
},
|
||||
_startListeningToEvents: function () {
|
||||
docker.client().getEvents(function (err, stream) {
|
||||
_startListeningToEvents: function (callback) {
|
||||
docker.client().getEvents((err, stream) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
if (stream) {
|
||||
stream.setEncoding('utf8');
|
||||
stream.on('data', this._dockerEvent.bind(this));
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
_dockerEvent: function (json) {
|
||||
var data = JSON.parse(json);
|
||||
|
@ -200,7 +219,7 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
this.emit(this.SERVER_CONTAINER_EVENT, data.status);
|
||||
}
|
||||
} else {
|
||||
this.fetchContainer(data.id, function (err) {
|
||||
this.fetchContainer(data.id, err => {
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
|
@ -209,13 +228,16 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
return;
|
||||
}
|
||||
this.emit(this.SERVER_CONTAINER_EVENT, container ? container.Name : null, data.status);
|
||||
}.bind(this));
|
||||
});
|
||||
}
|
||||
},
|
||||
init: function (callback) {
|
||||
// TODO: Load cached data from db on loading
|
||||
this.fetchAllContainers(function (err) {
|
||||
this.fetchAllContainers(err => {
|
||||
if (err) {
|
||||
_error = err;
|
||||
this.emit(this.SERVER_ERROR_EVENT, err);
|
||||
bugsnag.notify(err, 'Container Store failed to init', err);
|
||||
callback(err);
|
||||
return;
|
||||
} else {
|
||||
|
@ -227,12 +249,20 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
localStorage.setItem('store.placeholders', JSON.stringify(_placeholders));
|
||||
}
|
||||
this.emit(this.CLIENT_CONTAINER_EVENT);
|
||||
this._resumePulling();
|
||||
this._startListeningToEvents();
|
||||
}.bind(this));
|
||||
this._resumePulling(err => {
|
||||
_error = err;
|
||||
this.emit(this.SERVER_ERROR_EVENT, err);
|
||||
bugsnag.notify(err, 'Container Store failed to resume pulling', err);
|
||||
});
|
||||
this._startListeningToEvents(err => {
|
||||
_error = err;
|
||||
this.emit(this.SERVER_ERROR_EVENT, err);
|
||||
bugsnag.notify(err, 'Container Store failed to listen to events', err);
|
||||
});
|
||||
});
|
||||
},
|
||||
fetchContainer: function (id, callback) {
|
||||
docker.client().getContainer(id).inspect(function (err, container) {
|
||||
docker.client().getContainer(id).inspect((err, container) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
} else {
|
||||
|
@ -245,11 +275,10 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
_containers[container.Name] = container;
|
||||
callback(null, container);
|
||||
}
|
||||
}.bind(this));
|
||||
});
|
||||
},
|
||||
fetchAllContainers: function (callback) {
|
||||
var self = this;
|
||||
docker.client().listContainers({all: true}, function (err, containers) {
|
||||
docker.client().listContainers({all: true}, (err, containers) => {
|
||||
if (err) {
|
||||
callback(err);
|
||||
return;
|
||||
|
@ -260,8 +289,8 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
delete _containers[name];
|
||||
}
|
||||
});
|
||||
async.each(containers, function (container, callback) {
|
||||
self.fetchContainer(container.Id, function (err) {
|
||||
async.each(containers, (container, callback) => {
|
||||
this.fetchContainer(container.Id, function (err) {
|
||||
callback(err);
|
||||
});
|
||||
}, function (err) {
|
||||
|
@ -289,14 +318,28 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
|
||||
_muted[containerName] = true;
|
||||
_progress[containerName] = 0;
|
||||
this._pullImage(repository, tag, () => {
|
||||
this._pullImage(repository, tag, err => {
|
||||
if (err) {
|
||||
_error = err;
|
||||
this.emit(this.SERVER_ERROR_EVENT, err);
|
||||
bugsnag.notify(err, 'Container Store failed to create container', err);
|
||||
return;
|
||||
}
|
||||
_error = null;
|
||||
_blocked[containerName] = false;
|
||||
if (!_placeholders[containerName]) {
|
||||
return;
|
||||
}
|
||||
delete _placeholders[containerName];
|
||||
localStorage.setItem('store.placeholders', JSON.stringify(_placeholders));
|
||||
this._createContainer(containerName, {Image: imageName}, () => {
|
||||
this._createContainer(containerName, {Image: imageName}, err => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
_error = err;
|
||||
this.emit(this.SERVER_ERROR_EVENT, err);
|
||||
return;
|
||||
}
|
||||
_error = null;
|
||||
metrics.track('Container Finished Creating');
|
||||
delete _progress[containerName];
|
||||
_muted[containerName] = false;
|
||||
|
@ -321,10 +364,10 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
LogStore.rename(name, data.name);
|
||||
}
|
||||
var fullData = assign(_containers[name], data);
|
||||
this._createContainer(name, fullData, function (err) {
|
||||
this._createContainer(name, fullData, function () {
|
||||
_muted[name] = false;
|
||||
this.emit(this.CLIENT_CONTAINER_EVENT, name);
|
||||
callback(err);
|
||||
callback();
|
||||
}.bind(this));
|
||||
},
|
||||
rename: function (name, newName, callback) {
|
||||
|
@ -417,6 +460,9 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
},
|
||||
blocked: function (name) {
|
||||
return !!_blocked[name];
|
||||
},
|
||||
error: function () {
|
||||
return _error;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -20,11 +20,13 @@ var Containers = React.createClass({
|
|||
containers: ContainerStore.containers(),
|
||||
sorted: ContainerStore.sorted(),
|
||||
updateAvailable: false,
|
||||
currentButtonLabel: ''
|
||||
currentButtonLabel: '',
|
||||
error: ContainerStore.error()
|
||||
};
|
||||
},
|
||||
componentDidMount: function () {
|
||||
this.update();
|
||||
ContainerStore.on(ContainerStore.SERVER_ERROR_EVENT, this.updateError);
|
||||
ContainerStore.on(ContainerStore.SERVER_CONTAINER_EVENT, this.update);
|
||||
ContainerStore.on(ContainerStore.CLIENT_CONTAINER_EVENT, this.updateFromClient);
|
||||
|
||||
|
@ -52,6 +54,11 @@ var Containers = React.createClass({
|
|||
this.transitionTo('containers');
|
||||
}
|
||||
},
|
||||
updateError: function (err) {
|
||||
this.setState({
|
||||
error: err
|
||||
});
|
||||
},
|
||||
update: function (name, status) {
|
||||
this.setState({
|
||||
containers: ContainerStore.containers(),
|
||||
|
@ -175,7 +182,7 @@ var Containers = React.createClass({
|
|||
<div className="sidebar-buttons-padding"></div>
|
||||
</section>
|
||||
</div>
|
||||
<Router.RouteHandler container={container}/>
|
||||
<Router.RouteHandler container={container} error={this.state.error}/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -23,10 +23,7 @@ var ImageCard = React.createClass({
|
|||
},
|
||||
handleClick: function (name) {
|
||||
metrics.track('Created Container');
|
||||
ContainerStore.create(name, this.state.chosenTag, function (err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
ContainerStore.create(name, this.state.chosenTag, function () {
|
||||
$(document.body).find('.new-container-item').parent().fadeOut();
|
||||
}.bind(this));
|
||||
},
|
||||
|
|
14
src/Main.js
14
src/Main.js
|
@ -6,13 +6,13 @@ var fs = require('fs');
|
|||
var path = require('path');
|
||||
var docker = require('./Docker');
|
||||
var router = require('./Router');
|
||||
var machine = require('./DockerMachine');
|
||||
var ContainerStore = require('./ContainerStore');
|
||||
var SetupStore = require('./SetupStore');
|
||||
var metrics = require('./Metrics');
|
||||
var template = require('./MenuTemplate');
|
||||
var util = require('./Util');
|
||||
var Menu = remote.require('menu');
|
||||
var bugsnag = require('bugsnag-js');
|
||||
|
||||
window.addEventListener('resize', function () {
|
||||
fs.writeFileSync(path.join(util.supportDir(), 'size'), JSON.stringify({
|
||||
|
@ -38,7 +38,6 @@ if (process.env.NODE_ENV === 'development') {
|
|||
head.appendChild(script);
|
||||
}
|
||||
|
||||
var bugsnag = require('bugsnag-js');
|
||||
bugsnag.apiKey = settingsjson.bugsnag;
|
||||
bugsnag.autoNotify = true;
|
||||
bugsnag.releaseStage = process.env.NODE_ENV === 'development' ? 'development' : 'production';
|
||||
|
@ -81,18 +80,25 @@ setInterval(function () {
|
|||
}, 14400000);
|
||||
|
||||
router.run(Handler => React.render(<Handler/>, document.body));
|
||||
SetupStore.run().then(machine.info).then(machine => {
|
||||
SetupStore.setup().then(machine => {
|
||||
console.log('setup complete');
|
||||
console.log(machine);
|
||||
docker.setup(machine.url, machine.name);
|
||||
Menu.setApplicationMenu(Menu.buildFromTemplate(template()));
|
||||
ContainerStore.on(ContainerStore.SERVER_ERROR_EVENT, (err) => {
|
||||
bugsnag.notify(err);
|
||||
});
|
||||
ContainerStore.init(function (err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
bugsnag.notify(err);
|
||||
}
|
||||
router.transitionTo('containers');
|
||||
});
|
||||
}).catch(err => {
|
||||
metrics.track('Setup Failed', {
|
||||
step: SetupStore.step(),
|
||||
step: 'catch',
|
||||
message: err.message
|
||||
});
|
||||
bugsnag.notify(err);
|
||||
console.log(err);
|
||||
|
|
|
@ -3,7 +3,7 @@ var React = require('react/addons');
|
|||
var Radial = React.createClass({
|
||||
render: function () {
|
||||
var percentage;
|
||||
if ((this.props.progress !== null && this.props.progress !== undefined) && !this.props.spin) {
|
||||
if ((this.props.progress !== null && this.props.progress !== undefined) && !this.props.spin && !this.props.error) {
|
||||
percentage = (
|
||||
<div className="percentage"></div>
|
||||
);
|
||||
|
|
|
@ -6,13 +6,15 @@ var RetinaImage = require('react-retina-image');
|
|||
var Header = require('./Header.react');
|
||||
var Util = require('./Util');
|
||||
var metrics = require('./Metrics');
|
||||
var machine = require('./DockerMachine');
|
||||
|
||||
var Setup = React.createClass({
|
||||
mixins: [ Router.Navigation ],
|
||||
getInitialState: function () {
|
||||
return {
|
||||
progress: 0,
|
||||
name: ''
|
||||
name: '',
|
||||
retrying: false
|
||||
};
|
||||
},
|
||||
componentWillMount: function () {
|
||||
|
@ -28,10 +30,26 @@ var Setup = React.createClass({
|
|||
SetupStore.removeListener(SetupStore.STEP_EVENT, this.update);
|
||||
SetupStore.removeListener(SetupStore.ERROR_EVENT, this.update);
|
||||
},
|
||||
handleRetry: function () {
|
||||
metrics.track('Setup Retried');
|
||||
handleCancelRetry: function () {
|
||||
metrics.track('Setup Retried', {
|
||||
from: 'cancel'
|
||||
});
|
||||
SetupStore.retry();
|
||||
},
|
||||
handleErrorRetry: function () {
|
||||
this.setState({
|
||||
retrying: true
|
||||
});
|
||||
metrics.track('Setup Retried', {
|
||||
from: 'error'
|
||||
});
|
||||
machine.stop().finally(() => {
|
||||
this.setState({
|
||||
retrying: false
|
||||
});
|
||||
SetupStore.retry();
|
||||
});
|
||||
},
|
||||
handleOpenWebsite: function () {
|
||||
Util.exec(['open', 'https://www.virtualbox.org/wiki/Downloads']);
|
||||
},
|
||||
|
@ -110,21 +128,21 @@ var Setup = React.createClass({
|
|||
<h1>We're Sorry!</h1>
|
||||
<p>There seems to have been an unexpected error with Kitematic:</p>
|
||||
<p className="error">{this.state.error}<br />{this.state.error.message}</p>
|
||||
<p><button className="btn btn-action" disabled={this.state.retrying} onClick={this.handleErrorRetry}>Retry Setup</button></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
render: function () {
|
||||
if (!SetupStore.step()) {
|
||||
return false;
|
||||
}
|
||||
if (this.state.cancelled) {
|
||||
return this.renderCancelled();
|
||||
} else if (this.state.error) {
|
||||
return this.renderError();
|
||||
} else {
|
||||
} else if (SetupStore.step()) {
|
||||
return this.renderStep();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -10,6 +10,7 @@ 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;
|
||||
|
@ -59,26 +60,25 @@ var _steps = [{
|
|||
message: 'To run Docker containers on your computer, Kitematic is starting a Linux virutal machine. This may take a minute...',
|
||||
totalPercent: 60,
|
||||
percent: 0,
|
||||
seconds: 52,
|
||||
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.create();
|
||||
return;
|
||||
} else if ((yield machine.state()) === 'Error') {
|
||||
if (!exists || (yield machine.state()) === 'Error') {
|
||||
try {
|
||||
yield machine.rm();
|
||||
} catch (err) {}
|
||||
yield machine.create();
|
||||
yield machine.create();
|
||||
} catch (err) {
|
||||
rimraf.sync(path.join(util.home(), '.docker', 'machine', 'machines', machine.name()));
|
||||
yield machine.create();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var isoversion = machine.isoversion();
|
||||
var packagejson = util.packagejson();
|
||||
if (!isoversion || setupUtil.compareVersions(isoversion, packagejson['docker-version']) < 0) {
|
||||
console.log('upgrading');
|
||||
yield machine.stop();
|
||||
yield machine.upgrade();
|
||||
}
|
||||
|
@ -113,15 +113,21 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
|
|||
error: function () {
|
||||
return _error;
|
||||
},
|
||||
setError: function (error) {
|
||||
_error = error;
|
||||
this.emit(this.ERROR_EVENT);
|
||||
},
|
||||
cancelled: function () {
|
||||
return _cancelled;
|
||||
},
|
||||
retry: function () {
|
||||
_error = null;
|
||||
_cancelled = false;
|
||||
_retryPromise.resolve();
|
||||
if (_retryPromise) {
|
||||
_retryPromise.resolve();
|
||||
}
|
||||
},
|
||||
wait: function () {
|
||||
pause: function () {
|
||||
_retryPromise = Promise.defer();
|
||||
return _retryPromise.promise;
|
||||
},
|
||||
|
@ -141,7 +147,7 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
|
|||
if (isoversion && setupUtil.compareVersions(isoversion, packagejson['docker-version']) < 0) {
|
||||
this.steps().init.seconds = 33;
|
||||
} else if (exists && (yield machine.state()) !== 'Error') {
|
||||
this.steps().init.seconds = 13;
|
||||
this.steps().init.seconds = 23;
|
||||
}
|
||||
|
||||
_requiredSteps = _steps.filter(function (step) {
|
||||
|
@ -196,12 +202,30 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
|
|||
_cancelled = true;
|
||||
this.emit(this.STEP_EVENT);
|
||||
}
|
||||
yield this.wait();
|
||||
yield this.pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
metrics.track('Finished Setup');
|
||||
_currentStep = null;
|
||||
return yield machine.info();
|
||||
}),
|
||||
setup: Promise.coroutine(function * () {
|
||||
while (true) {
|
||||
var info = yield this.run();
|
||||
console.log(info);
|
||||
if (!info.url) {
|
||||
metrics.track('Setup Failed', {
|
||||
step: 'done',
|
||||
message: 'Machine URL not set'
|
||||
});
|
||||
bugsnag.notify('SetupError', 'Machine url was not set', machine);
|
||||
SetupStore.setError('Could not reach the Docker Engine inside the VirtualBox VM');
|
||||
yield this.pause();
|
||||
} else {
|
||||
metrics.track('Finished Setup');
|
||||
return info;
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ module.exports = {
|
|||
return new Promise((resolve, reject) => {
|
||||
exec(args, options, (stderr, stdout, code) => {
|
||||
if (code) {
|
||||
reject(stderr);
|
||||
reject(stderr || args.join(' ').replace(this.home(), '') + 'returned non zero exit code');
|
||||
}
|
||||
resolve(stdout);
|
||||
});
|
||||
|
|
|
@ -122,7 +122,7 @@
|
|||
.details-progress {
|
||||
margin: 20% auto 0;
|
||||
text-align: center;
|
||||
width: 300px;
|
||||
width: 400px;
|
||||
h2 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
|
|
@ -8,4 +8,5 @@ pkill VBox
|
|||
rm -rf ~/Library/Application\ Support/Kitematic/
|
||||
rm -rf ~/.docker
|
||||
rm -rf ~/Library/VirtualBox/
|
||||
rm -rf ~/Kitematic
|
||||
$DIR/VirtualBox_Uninstall.tool
|
||||
|
|
Загрузка…
Ссылка в новой задаче