Merge pull request #223 from kitematic/bug-fixes

Better Setup checking, add remove VM button to setup
This commit is contained in:
Jeffrey Morgan 2015-03-05 18:09:46 -05:00
commit 7b8d6be11c
6 changed files with 70 additions and 33 deletions

View File

@ -1,6 +1,7 @@
var fs = require('fs'); var fs = require('fs');
var path = require('path'); var path = require('path');
var dockerode = require('dockerode'); var dockerode = require('dockerode');
var Promise = require('bluebird');
var Docker = { var Docker = {
_host: null, _host: null,
@ -25,7 +26,34 @@ var Docker = {
}, },
host: function () { host: function () {
return this._host; return this._host;
},
waitForConnection: Promise.coroutine(function * (tries, delay) {
tries = tries || 5;
delay = delay || 1000;
var tryCount = 1;
while (true) {
console.log('Connecting: ' + tryCount + ' tries...');
try {
yield new Promise((resolve, reject) => {
this._client.listContainers((err) => {
if (err) {
reject(err);
} else {
resolve();
} }
});
});
break;
} catch (err) {
tryCount += 1;
yield Promise.delay(delay);
if (tryCount > tries) {
throw new Error(err);
}
continue;
}
}
}),
}; };
module.exports = Docker; module.exports = Docker;

View File

@ -83,20 +83,12 @@ setInterval(function () {
}, 14400000); }, 14400000);
router.run(Handler => React.render(<Handler/>, document.body)); router.run(Handler => React.render(<Handler/>, document.body));
SetupStore.setup().then(ip => { SetupStore.setup().then(() => {
docker.setup(ip, machine.name());
Menu.setApplicationMenu(Menu.buildFromTemplate(template())); Menu.setApplicationMenu(Menu.buildFromTemplate(template()));
ContainerStore.on(ContainerStore.SERVER_ERROR_EVENT, (err) => { ContainerStore.on(ContainerStore.SERVER_ERROR_EVENT, (err) => {
bugsnag.notify(err); bugsnag.notify(err);
}); });
ContainerStore.init(function (err) { ContainerStore.init(function () {
if (err) {
console.log(err);
bugsnag.notify('ContainerStoreError', 'Could not init containerstore', {
error: err,
machine: machine
});
}
router.transitionTo('containers'); router.transitionTo('containers');
}); });
}).catch(err => { }).catch(err => {

View File

@ -6,7 +6,6 @@ var RetinaImage = require('react-retina-image');
var Header = require('./Header.react'); var Header = require('./Header.react');
var Util = require('./Util'); var Util = require('./Util');
var metrics = require('./Metrics'); var metrics = require('./Metrics');
var machine = require('./DockerMachine');
var Setup = React.createClass({ var Setup = React.createClass({
mixins: [ Router.Navigation ], mixins: [ Router.Navigation ],
@ -14,7 +13,6 @@ var Setup = React.createClass({
return { return {
progress: 0, progress: 0,
name: '', name: '',
retrying: false
}; };
}, },
componentWillMount: function () { componentWillMount: function () {
@ -37,18 +35,18 @@ var Setup = React.createClass({
SetupStore.retry(); SetupStore.retry();
}, },
handleErrorRetry: function () { handleErrorRetry: function () {
this.setState({
retrying: true
});
metrics.track('Setup Retried', { metrics.track('Setup Retried', {
from: 'error' from: 'error',
removeVM: false
}); });
machine.stop().finally(() => { SetupStore.retry(false);
this.setState({ },
retrying: false handleErrorRemoveRetry: function () {
}); metrics.track('Setup Retried', {
SetupStore.retry(); from: 'error',
removeVM: true
}); });
SetupStore.retry(true);
}, },
handleOpenWebsite: function () { handleOpenWebsite: function () {
Util.exec(['open', 'https://www.virtualbox.org/wiki/Downloads']); Util.exec(['open', 'https://www.virtualbox.org/wiki/Downloads']);
@ -128,7 +126,7 @@ var Setup = React.createClass({
<h1>We&#39;re Sorry!</h1> <h1>We&#39;re Sorry!</h1>
<p>There seems to have been an unexpected error with Kitematic:</p> <p>There seems to have been an unexpected error with Kitematic:</p>
<p className="error">{this.state.error.message || this.state.error}</p> <p className="error">{this.state.error.message || this.state.error}</p>
<p><button className="btn btn-action" disabled={this.state.retrying} onClick={this.handleErrorRetry}>Retry Setup</button></p> <p><button className="btn btn-action" onClick={this.handleErrorRetry}>Retry Setup</button> <button className="btn btn-action" onClick={this.handleErrorRemoveRetry}>Delete VM and Retry Setup</button></p>
</div> </div>
</div> </div>
</div> </div>

View File

@ -11,6 +11,7 @@ var assign = require('object-assign');
var metrics = require('./Metrics'); var metrics = require('./Metrics');
var bugsnag = require('bugsnag-js'); var bugsnag = require('bugsnag-js');
var rimraf = require('rimraf'); var rimraf = require('rimraf');
var docker = require('./Docker');
var _currentStep = null; var _currentStep = null;
var _error = null; var _error = null;
@ -118,12 +119,26 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
cancelled: function () { cancelled: function () {
return _cancelled; return _cancelled;
}, },
retry: function () { retry: function (remove) {
_error = null; _error = null;
_cancelled = false; _cancelled = false;
if (_retryPromise) { if (!_retryPromise) {
_retryPromise.resolve(); return;
} }
this.emit(this.ERROR_EVENT);
if (remove) {
machine.rm().finally(() => {
_retryPromise.resolve();
});
} else {
machine.stop().finally(() => {
_retryPromise.resolve();
});
}
},
setError: function (error) {
_error = error;
this.emit(this.ERROR_EVENT);
}, },
pause: function () { pause: function () {
_retryPromise = Promise.defer(); _retryPromise = Promise.defer();
@ -207,6 +222,7 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
setup: Promise.coroutine(function * () { setup: Promise.coroutine(function * () {
while (true) { while (true) {
try { try {
console.log('Starting Steps');
var ip = yield this.run(); var ip = yield this.run();
if (!ip || !ip.length) { if (!ip || !ip.length) {
throw { throw {
@ -214,10 +230,13 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
machine: yield machine.info(), machine: yield machine.info(),
ip: ip, ip: ip,
}; };
} else {
metrics.track('Setup Finished');
return ip;
} }
console.log('Finished Steps');
console.log(ip);
docker.setup(ip, machine.name());
yield docker.waitForConnection();
metrics.track('Setup Finished');
break;
} catch (err) { } catch (err) {
metrics.track('Setup Failed', { metrics.track('Setup Failed', {
step: _currentStep step: _currentStep
@ -227,7 +246,7 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
error: err, error: err,
step: _currentStep, step: _currentStep,
virtualbox: virtualboxVersion virtualbox: virtualboxVersion
}); }, 'info');
_error = err; _error = err;
this.emit(this.ERROR_EVENT); this.emit(this.ERROR_EVENT);
yield this.pause(); yield this.pause();

View File

@ -17,11 +17,11 @@ var SetupUtil = {
return fs.statSync('/usr/local/bin').gid !== 80 || fs.statSync('/usr/local/bin').uid !== process.getuid(); return fs.statSync('/usr/local/bin').gid !== 80 || fs.statSync('/usr/local/bin').uid !== process.getuid();
} }
if (fs.existsSync('/usr/local/bin/docker') && (fs.statSync('/usr/local/bin/docker').gid !== 80 || fs.statSync('/usr/local/bin/docker').uid !== process.getuid())) { if (fs.statSync('/usr/local/bin/docker').gid !== 80 || fs.statSync('/usr/local/bin/docker').uid !== process.getuid()) {
return true; return true;
} }
if (fs.existsSync('/usr/local/bin/docker-machine') && (fs.statSync('/usr/local/bin/docker-machine').gid !== 80 || fs.statSync('/usr/local/bin/docker-machine').uid !== process.getuid())) { if (fs.statSync('/usr/local/bin/docker-machine').gid !== 80 || fs.statSync('/usr/local/bin/docker-machine').uid !== process.getuid()) {
return true; return true;
} }
return false; return false;

View File

@ -11,7 +11,7 @@ module.exports = {
if (code) { if (code) {
var cmd = Array.isArray(args) ? args.join(' ') : args; var cmd = Array.isArray(args) ? args.join(' ') : args;
reject({ reject({
message: cmd.replace(this.home(), '') + ' returned non zero exit code', message: cmd + ' returned non zero exit code',
stderr: stderr, stderr: stderr,
stdout: stdout stdout: stdout
}); });