зеркало из https://github.com/docker/kitematic.git
Merge pull request #1130 from kitematic/remove-machine
Remove bundling of docker-machine, macsudo
This commit is contained in:
Коммит
a788166c21
54
Gruntfile.js
54
Gruntfile.js
|
@ -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
Двоичные данные
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 & 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(() => {});
|
||||||
|
|
Загрузка…
Ссылка в новой задаче