Merge pull request #222 from kitematic/setup-hardening

Fix error with permissions when setting up CLI tools. Better error messages and reporting
This commit is contained in:
Jeffrey Morgan 2015-03-05 14:55:22 -05:00
commit 7cd3153623
6 changed files with 25 additions and 36 deletions

View File

@ -74,7 +74,7 @@ var ContainerHome = React.createClass({
if (this.props.error) { if (this.props.error) {
body = ( body = (
<div className="details-progress"> <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> <h3>There was a problem connecting to the Docker Engine in the VirtualBox VM.<br/>This could be caused because this Mac is currently connected a VPN, blocking access to the VM. 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}/> <Radial progress={100} error={true} thick={true} transparent={true}/>
</div> </div>
); );

View File

@ -108,6 +108,4 @@ SetupStore.setup().then(ip => {
step: 'catch', step: 'catch',
error: err error: err
}); });
console.log(err);
console.log(err.stack);
}); });

View File

@ -127,7 +127,7 @@ var Setup = React.createClass({
<h4>Setup Error</h4> <h4>Setup Error</h4>
<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}<br />{this.state.error.message}</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" disabled={this.state.retrying} onClick={this.handleErrorRetry}>Retry Setup</button></p>
</div> </div>
</div> </div>

View File

@ -115,10 +115,6 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
error: function () { error: function () {
return _error; return _error;
}, },
setError: function (error) {
_error = error;
this.emit(this.ERROR_EVENT);
},
cancelled: function () { cancelled: function () {
return _cancelled; return _cancelled;
}, },
@ -195,20 +191,7 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
break; break;
} catch (err) { } catch (err) {
if (err) { if (err) {
console.log('Setup encountered an error.'); throw err;
console.log(err);
console.log(err.stack);
metrics.track('Setup Failed', {
step: step.name
});
var virtualboxVersion = virtualBox.installed() ? yield virtualBox.version() : 'Not installed';
bugsnag.notify('SetupError', 'Setup failed', {
error: err,
step: step.name,
virtualbox: virtualboxVersion
});
_error = err;
this.emit(this.ERROR_EVENT);
} else { } else {
metrics.track('Setup Cancelled'); metrics.track('Setup Cancelled');
_cancelled = true; _cancelled = true;
@ -223,24 +206,31 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
}), }),
setup: Promise.coroutine(function * () { setup: Promise.coroutine(function * () {
while (true) { while (true) {
var ip = yield this.run(); try {
if (!ip || !ip.length) { 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', { metrics.track('Setup Failed', {
step: 'done', step: _currentStep
message: 'Machine IP not set'
}); });
var virtualboxVersion = virtualBox.installed() ? yield virtualBox.version() : 'Not installed'; var virtualboxVersion = virtualBox.installed() ? yield virtualBox.version() : 'Not installed';
bugsnag.notify('SetupError', 'Machine ip was not set', { bugsnag.notify('SetupError', 'Setup failed', {
machine: yield machine.info(), error: err,
ip: ip, step: _currentStep,
step: 'done',
virtualbox: virtualboxVersion virtualbox: virtualboxVersion
}); });
SetupStore.setError('Could not reach the Docker Engine inside the VirtualBox VM'); _error = err;
this.emit(this.ERROR_EVENT);
yield this.pause(); yield this.pause();
} else {
metrics.track('Setup Finished');
return ip;
} }
} }
}) })

View File

@ -12,7 +12,8 @@ var SetupUtil = {
if (!fs.existsSync('/usr/local') || !fs.existsSync('/usr/local/bin')) { if (!fs.existsSync('/usr/local') || !fs.existsSync('/usr/local/bin')) {
return true; return true;
} }
if (!fs.existsSync('/usr/local/bin/docker') && !fs.existsSync('/usr/local/bin/docker-machine')) {
if (!fs.existsSync('/usr/local/bin/docker') || !fs.existsSync('/usr/local/bin/docker-machine')) {
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();
} }

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.replace(this.home(), '') + ' returned non zero exit code',
stderr: stderr, stderr: stderr,
stdout: stdout stdout: stdout
}); });