Merge pull request #1130 from kitematic/remove-machine

Remove bundling of docker-machine, macsudo
This commit is contained in:
French Ben 2015-10-22 14:05:02 -07:00
Родитель 283276abec 232824cfb3
Коммит a788166c21
10 изменённых файлов: 53 добавлений и 98 удалений

Просмотреть файл

@ -3,9 +3,6 @@ var execFile = require('child_process').execFile;
var packagejson = require('./package.json'); var packagejson = require('./package.json');
var electron = require('electron-prebuilt'); var electron = require('electron-prebuilt');
var WINDOWS_DOCKER_MACHINE_URL = 'https://github.com/docker/machine/releases/download/v' + packagejson['docker-machine-version'] + '/docker-machine_windows-amd64.exe';
var DARWIN_DOCKER_MACHINE_URL = 'https://github.com/docker/machine/releases/download/v' + packagejson['docker-machine-version'] + '/docker-machine_darwin-amd64';
module.exports = function (grunt) { module.exports = function (grunt) {
require('load-grunt-tasks')(grunt); require('load-grunt-tasks')(grunt);
var target = grunt.option('target') || 'development'; var target = grunt.option('target') || 'development';
@ -22,21 +19,6 @@ module.exports = function (grunt) {
return match ? match[1] : null; return match ? match[1] : null;
}; };
grunt.registerMultiTask('download-binary', 'Downloads binary unless version up to date', function () {
var target = grunt.task.current.target;
var done = this.async();
var config = grunt.config('download-binary')[target];
execFile(config.binary, ['--version'], function (err, stdout) {
var currentVersion = version(stdout);
if (!currentVersion || currentVersion !== version(config.version)) {
grunt.task.run('curl:' + target);
grunt.task.run('chmod');
}
done();
});
});
var BASENAME = 'Kitematic'; var BASENAME = 'Kitematic';
var APPNAME = BASENAME; var APPNAME = BASENAME;
@ -128,15 +110,6 @@ module.exports = function (grunt) {
} }
}, },
// docker binaries
'download-binary': {
'docker-machine': {
version: packagejson['docker-machine-version'],
binary: path.join('resources', 'docker-machine'),
download: 'curl:docker-machine'
}
},
// images // images
copy: { copy: {
dev: { dev: {
@ -166,7 +139,7 @@ module.exports = function (grunt) {
files: [{ files: [{
expand: true, expand: true,
cwd: 'resources', cwd: 'resources',
src: ['docker*', 'ssh.exe', 'OPENSSH_LICENSE', 'msys-*'], src: ['ssh.exe', 'OPENSSH_LICENSE', 'msys-*'],
dest: 'dist/' + BASENAME + '-win32-x64/resources/resources' dest: 'dist/' + BASENAME + '-win32-x64/resources/resources'
}], }],
options: { options: {
@ -177,7 +150,7 @@ module.exports = function (grunt) {
files: [{ files: [{
expand: true, expand: true,
cwd: 'resources', cwd: 'resources',
src: ['docker*', 'macsudo', 'terminal'], src: ['terminal'],
dest: '<%= OSX_FILENAME %>/Contents/Resources/resources/' dest: '<%= OSX_FILENAME %>/Contents/Resources/resources/'
}, { }, {
src: 'util/kitematic.icns', src: 'util/kitematic.icns',
@ -196,23 +169,6 @@ module.exports = function (grunt) {
} }
}, },
// download binaries
curl: {
'docker-machine': {
src: process.platform === 'win32' ? WINDOWS_DOCKER_MACHINE_URL : DARWIN_DOCKER_MACHINE_URL,
dest: process.platform === 'win32' ? path.join('resources', 'docker-machine.exe') : path.join('resources', 'docker-machine')
}
},
chmod: {
binaries: {
options: {
mode: '755'
},
src: ['resources/docker*']
}
},
// styles // styles
less: { less: {
options: { options: {
@ -312,12 +268,12 @@ module.exports = function (grunt) {
} }
}); });
grunt.registerTask('default', ['download-binary', 'newer:babel', 'less', 'newer:copy:dev', 'shell:electron', 'watchChokidar']); grunt.registerTask('default', ['newer:babel', 'less', 'newer:copy:dev', 'shell:electron', 'watchChokidar']);
if (process.platform === 'win32') { if (process.platform === 'win32') {
grunt.registerTask('release', ['clean:release', 'download-binary', 'babel', 'less', 'copy:dev', 'electron:windows', 'copy:windows', 'rcedit:exes', 'compress']); grunt.registerTask('release', ['clean:release', 'babel', 'less', 'copy:dev', 'electron:windows', 'copy:windows', 'rcedit:exes', 'compress']);
} else { } else {
grunt.registerTask('release', ['clean:release', 'download-binary', 'babel', 'less', 'copy:dev', 'electron:osx', 'copy:osx', 'shell:sign', 'shell:zip']); grunt.registerTask('release', ['clean:release', 'babel', 'less', 'copy:dev', 'electron:osx', 'copy:osx', 'shell:sign', 'shell:zip']);
} }
process.on('SIGINT', function () { process.on('SIGINT', function () {

Просмотреть файл

@ -17,7 +17,6 @@
"lint": "jsxhint src" "lint": "jsxhint src"
}, },
"license": "Apache-2.0", "license": "Apache-2.0",
"docker-machine-version": "0.4.1",
"electron-version": "0.33.6", "electron-version": "0.33.6",
"dependencies": { "dependencies": {
"alt": "^0.16.2", "alt": "^0.16.2",

Двоичные данные
resources/macsudo

Двоичный файл не отображается.

Просмотреть файл

@ -4,7 +4,8 @@ class SetupServerActions {
constructor () { constructor () {
this.generateActions( this.generateActions(
'progress', 'progress',
'error' 'error',
'started'
); );
} }
} }

Просмотреть файл

@ -3,10 +3,10 @@ import Router from 'react-router';
import Radial from './Radial.react.js'; import Radial from './Radial.react.js';
import RetinaImage from 'react-retina-image'; import RetinaImage from 'react-retina-image';
import Header from './Header.react'; import Header from './Header.react';
import Util from '../utils/Util';
import metrics from '../utils/MetricsUtil'; import metrics from '../utils/MetricsUtil';
import setupStore from '../stores/SetupStore'; import setupStore from '../stores/SetupStore';
import setupActions from '../actions/SetupActions'; import setupActions from '../actions/SetupActions';
import shell from 'shell';
var Setup = React.createClass({ var Setup = React.createClass({
mixins: [Router.Navigation], mixins: [Router.Navigation],
@ -32,10 +32,17 @@ var Setup = React.createClass({
}, },
handleErrorRemoveRetry: function () { handleErrorRemoveRetry: function () {
console.log('Deleting VM and trying again.'); console.log('Deleting VM and trying again.' );
setupActions.retry(true); setupActions.retry(true);
}, },
handleToolBox: function () {
metrics.track('Getting toolbox', {
from: 'setup'
});
shell.openExternal('https://www.docker.com/docker-toolbox');
},
renderContents: function () { renderContents: function () {
return ( return (
<div className="contents"> <div className="contents">
@ -65,6 +72,7 @@ var Setup = React.createClass({
</div> </div>
); );
}, },
renderError: function () { renderError: function () {
return ( return (
<div className="setup"> <div className="setup">
@ -85,7 +93,7 @@ var Setup = React.createClass({
<p className="error">{this.state.error.message || this.state.error}</p> <p className="error">{this.state.error.message || this.state.error}</p>
<p className="setup-actions"> <p className="setup-actions">
<button className="btn btn-action" onClick={this.handleErrorRetry}>Retry Setup</button> <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> {this.state.started ? <button className="btn btn-action" onClick={this.handleErrorRemoveRetry}>Delete VM &amp; Retry Setup</button> : <button className="btn btn-action" onClick={this.handleToolBox}>Get Toolbox</button>}
</p> </p>
</div> </div>
</div> </div>

Просмотреть файл

@ -6,16 +6,21 @@ class SetupStore {
constructor () { constructor () {
this.bindActions(setupActions); this.bindActions(setupActions);
this.bindActions(setupServerActions); this.bindActions(setupServerActions);
this.percent = 0; this.started = false;
this.progress = null;
this.error = null; this.error = null;
} }
started ({started}) {
this.setState({error: null, started});
}
error ({error}) { error ({error}) {
this.setState({error}); this.setState({error, progress: null});
} }
progress ({progress}) { progress ({progress}) {
this.setState({error: null, progress}); this.setState({progress});
} }
} }

Просмотреть файл

@ -3,15 +3,24 @@ import path from 'path';
import Promise from 'bluebird'; import Promise from 'bluebird';
import fs from 'fs'; import fs from 'fs';
import util from './Util'; import util from './Util';
import resources from './ResourcesUtil';
var DockerMachine = { var DockerMachine = {
command: function () { command: function () {
return resources.dockerMachine(); if (util.isWindows()) {
return path.join(process.env.DOCKER_TOOLBOX_INSTALL_PATH, 'docker-machine.exe');
} else {
return '/usr/local/bin/docker-machine';
}
}, },
name: function () { name: function () {
return 'default'; return 'default';
}, },
installed: function () {
if (util.isWindows() && !process.env.DOCKER_TOOLBOX_INSTALL_PATH) {
return false;
}
return fs.existsSync(this.command());
},
isoversion: function (machineName = this.name()) { isoversion: function (machineName = this.name()) {
try { try {
var data = fs.readFileSync(path.join(util.home(), '.docker', 'machine', 'machines', machineName, 'boot2docker.iso'), 'utf8'); var data = fs.readFileSync(path.join(util.home(), '.docker', 'machine', 'machines', machineName, 'boot2docker.iso'), 'utf8');
@ -161,7 +170,7 @@ var DockerMachine = {
} else { } else {
cmd = cmd || process.env.SHELL; cmd = cmd || process.env.SHELL;
this.info(machineName).then(machine => { this.info(machineName).then(machine => {
util.exec([resources.terminal(), `DOCKER_HOST=${machine.url} DOCKER_CERT_PATH=${path.join(util.home(), '.docker/machine/machines/' + machine.name)} DOCKER_TLS_VERIFY=1 ${cmd}`]).then(() => {}); util.exec([path.join(process.env.RESOURCES_PATH, 'terminal'), `DOCKER_HOST=${machine.url} DOCKER_CERT_PATH=${path.join(util.home(), '.docker/machine/machines/' + machine.name)} DOCKER_TLS_VERIFY=1 ${cmd}`]).then(() => {});
}); });
} }
}, },

Просмотреть файл

@ -1,23 +0,0 @@
import util from './Util';
import path from 'path';
module.exports = {
resourceDir: function () {
return process.env.RESOURCES_PATH;
},
macsudo: function () {
return path.join(this.resourceDir(), 'macsudo');
},
terminal: function () {
return path.join(this.resourceDir(), 'terminal');
},
docker: function () {
return path.join(this.resourceDir(), 'docker' + util.binsEnding());
},
dockerMachine: function () {
return path.join(this.resourceDir(), 'docker-machine' + util.binsEnding());
},
dockerCompose: function () {
return path.join(this.resourceDir(), 'docker-compose' + util.binsEnding());
}
};

Просмотреть файл

@ -16,6 +16,7 @@ let _timers = [];
export default { export default {
simulateProgress (estimateSeconds) { simulateProgress (estimateSeconds) {
this.clearTimers();
var times = _.range(0, estimateSeconds * 1000, 200); var times = _.range(0, estimateSeconds * 1000, 200);
_.each(times, time => { _.each(times, time => {
var timer = setTimeout(() => { var timer = setTimeout(() => {
@ -50,13 +51,19 @@ export default {
metrics.track('Started Setup'); metrics.track('Started Setup');
while (true) { while (true) {
try { try {
if (!util.isWindows() && !virtualBox.active()) { setupServerActions.started({started: false});
await util.exec(setupUtil.macSudoCmd(util.escapePath('/Library/Application Support/VirtualBox/LaunchDaemons/VirtualBoxStartup.sh') + ' restart')); router.get().transitionTo('setup');
if (!virtualBox.installed()) {
throw new Error('VirtualBox is not installed. Please install it via the Docker Toolbox.');
} }
let exists = await virtualBox.vmExists(machine.name()); if (!machine.installed()) {
throw new Error('Docker Machine is not installed. Please install it via the Docker Toolbox.');
}
setupServerActions.started({started: true});
let exists = await virtualBox.vmExists(machine.name()) && fs.existsSync(path.join(util.home(), '.docker', 'machine', 'machines', machine.name()));
if (!exists) { if (!exists) {
router.get().transitionTo('setup');
this.simulateProgress(60); this.simulateProgress(60);
try { try {
await machine.rm(); await machine.rm();
@ -70,7 +77,7 @@ export default {
this.simulateProgress(10); this.simulateProgress(10);
} else if (state === 'Stopped') { } else if (state === 'Stopped') {
router.get().transitionTo('setup'); router.get().transitionTo('setup');
this.simulateProgress(25) this.simulateProgress(25);
} }
await machine.start(); await machine.start();
} }

Просмотреть файл

@ -5,7 +5,7 @@ import Promise from 'bluebird';
var VirtualBox = { var VirtualBox = {
command: function () { command: function () {
if(util.isWindows()) { if (util.isWindows()) {
if (process.env.VBOX_MSI_INSTALL_PATH) { if (process.env.VBOX_MSI_INSTALL_PATH) {
return path.join(process.env.VBOX_MSI_INSTALL_PATH, 'VBoxManage.exe'); return path.join(process.env.VBOX_MSI_INSTALL_PATH, 'VBoxManage.exe');
} else { } else {
@ -16,7 +16,7 @@ var VirtualBox = {
} }
}, },
installed: function () { installed: function () {
if(util.isWindows()) { if (util.isWindows()) {
return (process.env.VBOX_MSI_INSTALL_PATH && fs.existsSync(path.join(process.env.VBOX_MSI_INSTALL_PATH, 'VBoxManage.exe'))) || return (process.env.VBOX_MSI_INSTALL_PATH && fs.existsSync(path.join(process.env.VBOX_MSI_INSTALL_PATH, 'VBoxManage.exe'))) ||
(process.env.VBOX_INSTALL_PATH && fs.existsSync(path.join(process.env.VBOX_INSTALL_PATH, 'VBoxManage.exe'))); (process.env.VBOX_INSTALL_PATH && fs.existsSync(path.join(process.env.VBOX_INSTALL_PATH, 'VBoxManage.exe')));
} else { } else {
@ -38,20 +38,13 @@ var VirtualBox = {
}); });
}, },
poweroffall: function () { poweroffall: function () {
if (!this.installed()) {
return Promise.reject('VirtualBox not installed.');
}
return util.exec(this.command() + ' list runningvms | sed -E \'s/.*\\{(.*)\\}/\\1/\' | xargs -L1 -I {} ' + this.command() + ' controlvm {} poweroff'); return util.exec(this.command() + ' list runningvms | sed -E \'s/.*\\{(.*)\\}/\\1/\' | xargs -L1 -I {} ' + this.command() + ' controlvm {} poweroff');
}, },
mountSharedDir: function (vmName, pathName, hostPath) { mountSharedDir: function (vmName, pathName, hostPath) {
if (!this.installed()) {
return Promise.reject('VirtualBox not installed.');
}
return util.exec([this.command(), 'sharedfolder', 'add', vmName, '--name', pathName, '--hostpath', hostPath, '--automount']); return util.exec([this.command(), 'sharedfolder', 'add', vmName, '--name', pathName, '--hostpath', hostPath, '--automount']);
}, },
killall: function () { killall: function () {
if(util.isWindows()) { if (util.isWindows()) {
return this.poweroffall().then(() => { return this.poweroffall().then(() => {
return util.exec(['powershell.exe', '\"get-process VBox* | stop-process\"']); return util.exec(['powershell.exe', '\"get-process VBox* | stop-process\"']);
}).catch(() => {}); }).catch(() => {});