mirror of https://github.com/docker/docs.git
- Working on changes required to setup client on windows.
- For now changes in SetupStore are made, to skip steps that do MacOS setup. - Adding deps.ps1 script for installing all required dependencies on windows. - Adding reset.ps1 script for removing all dependencies on windows. - Modifying files to work with windows dependencies - Fix for duplicate react instances in the code. - A fix required to load only one instance of React in the application. Without such fix, on windows application loads two instances of React at start time, and crashes. - Modifying files to support windows paths - Modifying deps and reset powershell scripts to loose chocolatey dependency. Adding windows VirtualBox installation steps. - Improved a workaround for adding Users directory to the shared folder in the VM on windows. Added few more fixes for Windows/Mac compatibility. - Removing unnecessary log from deps.ps1 script, - Updating Gulpfile to download and copy all the dependencies on application start, - Cleaning pre and post install scripts from package.json, as they are not realy friendly for different platforms. - Removing changes from browser.js as they were not necessary or even breaking. - Cleaning pre and post install scripts from package.json, as they are not really friendly for different platforms. - Fixing changes in package.json. - Fixed reset.ps1 file to delete all folders created by the app, - Fixed metrics.js file to properly use userAgent depending on the OS. - Uncommented updateBinaries line in SetupStore. - Adding open as a dependency. - Fixing the setupStore tests. - Adding proper directory to PATH for docker and docker-machine binaries. - Adding support for the docker terminal command. It opens a CMD on windows and sets required env variables for the docker to work. Docker and Docker-Machine should be on the path, as they are set up there on Kitematic startup. - Added Resources module which provides paths to all files stored in the resources directory, - Added docker and docker-machine binary paths to Util module, to have a single place for calling those paths, - Added binaries directory path, to Util module, to have a single place for calling this path, - Added another exec command, which utilizes "child_process" module, and it's "exec" command, as the "exec" used right now is deprecated, - Refactored the Installation step in the SetupStore, and connected with that SetupUtil commands to perform copying binaries from node instead of bash commands. That way application is more cross-platform friendly, - Added new dependencies in form of fs-extra, fs-promise and any-promise, to allow yielding of fs commands in SetupUtil. - The setup process now works correctly on windows from the beginning to end. - Fixing broken tests. - Improving tests. - Adding elevated permissions to the reset script, as it is required to kill processes and remove VirtualBox. - Added ability to run reset scripts through gulp, - Added new npm script for resetting the environment "npm run reset". - Refactored docker-machine module, to use Resources module for finding the machine command and general code cleaning, - Added windows keyboard shortcut support. - Adding the use of Resources module, instead of direct access of files in the resources dir. - Testing appveyor. - Testing appveyor + io.js. - Back to node 0.10. - Fixing permission issues with appveyor. - Testing travis. Signed-off-by: Dominik Deren <dominik.deren@live.com> - Working on changes required to setup client on windows. - For now changes in SetupStore are made, to skip steps that do MacOS setup. - Adding deps.ps1 script for installing all required dependencies on windows. - Adding reset.ps1 script for removing all dependencies on windows. Fix for duplicate react instances in the code. Modifying files to support windows paths - Removing unnecessary log from deps.ps1 script, - Updating Gulpfile to download and copy all the dependencies on application start, - Cleaning pre and post install scripts from package.json, as they are not realy friendly for different platforms. - Removing changes from browser.js as they were not necessary or even breaking. - Fixing changes in package.json. - Uncommented updateBinaries line in SetupStore. - Adding open as a dependency. - Adding proper directory to PATH for docker and docker-machine binaries. - Fixing broken tests. - Improving tests. - Adding elevated permissions to the reset script, as it is required to kill processes and remove VirtualBox. - Added ability to run reset scripts through gulp, - Added new npm script for resetting the environment "npm run reset". - Refactored docker-machine module, to use Resources module for finding the machine command and general code cleaning, - Added windows keyboard shortcut support. - Adding the use of Resources module, instead of direct access of files in the resources dir. - Testing appveyor + io.js. - Back to node 0.10. - Fixing permission issues with appveyor. Signed-off-by: Dominik Deren <dominik.deren@live.com>
This commit is contained in:
parent
2ee03ed440
commit
046e640eeb
|
@ -17,3 +17,6 @@ cache
|
|||
# Tests
|
||||
.test
|
||||
settings.json
|
||||
|
||||
# IDEs
|
||||
.idea
|
|
@ -12,7 +12,7 @@ describe('SetupStore', function () {
|
|||
pit('downloads virtualbox if it is not installed', function () {
|
||||
virtualBox.installed.mockReturnValue(false);
|
||||
setupUtil.download.mockReturnValue(Promise.resolve());
|
||||
util.packagejson.mockReturnValue({'virtualbox-filename': ''});
|
||||
setupUtil.virtualBoxFileName.mockReturnValue('');
|
||||
util.supportDir.mockReturnValue('');
|
||||
return setupStore.steps().download.run().then(() => {
|
||||
expect(setupUtil.download).toBeCalled();
|
||||
|
@ -24,7 +24,7 @@ describe('SetupStore', function () {
|
|||
virtualBox.version.mockReturnValue(Promise.resolve('4.3.16'));
|
||||
setupUtil.compareVersions.mockReturnValue(-1);
|
||||
setupUtil.download.mockReturnValue(Promise.resolve());
|
||||
util.packagejson.mockReturnValue({'virtualbox-filename': ''});
|
||||
setupUtil.virtualBoxFileName.mockReturnValue('');
|
||||
util.supportDir.mockReturnValue('');
|
||||
return setupStore.steps().download.run().then(() => {
|
||||
expect(setupUtil.download).toBeCalled();
|
||||
|
@ -34,10 +34,11 @@ describe('SetupStore', function () {
|
|||
|
||||
describe('install step', function () {
|
||||
util.exec.mockReturnValue(Promise.resolve());
|
||||
setupUtil.copyBinariesCmd.mockReturnValue('copycmd');
|
||||
setupUtil.fixBinariesCmd.mockReturnValue('fixcmd');
|
||||
util.execProper.mockReturnValue(Promise.resolve());
|
||||
setupUtil.copyBinariesCmd.mockReturnValue(Promise.resolve());
|
||||
setupUtil.fixBinariesCmd.mockReturnValue(Promise.resolve());
|
||||
virtualBox.killall.mockReturnValue(Promise.resolve());
|
||||
setupUtil.installVirtualBoxCmd.mockReturnValue('installvb');
|
||||
setupUtil.installVirtualBoxCmd.mockReturnValue(Promise.resolve());
|
||||
setupUtil.macSudoCmd.mockImplementation(cmd => 'macsudo ' + cmd);
|
||||
|
||||
pit('installs virtualbox if it is not installed', function () {
|
||||
|
@ -45,7 +46,9 @@ describe('SetupStore', function () {
|
|||
util.exec.mockReturnValue(Promise.resolve());
|
||||
return setupStore.steps().install.run().then(() => {
|
||||
expect(virtualBox.killall).toBeCalled();
|
||||
expect(util.exec).toBeCalledWith('macsudo copycmd && fixcmd && installvbcmd');
|
||||
expect(setupUtil.copyBinariesCmd).toBeCalled();
|
||||
expect(setupUtil.fixBinariesCmd).toBeCalled();
|
||||
expect(setupUtil.installVirtualBoxCmd).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -54,7 +57,9 @@ describe('SetupStore', function () {
|
|||
setupUtil.compareVersions.mockReturnValue(0);
|
||||
setupUtil.needsBinaryFix.mockReturnValue(true);
|
||||
return setupStore.steps().install.run().then(() => {
|
||||
expect(util.exec).toBeCalledWith('macsudo copycmd && fixcmd');
|
||||
expect(setupUtil.copyBinariesCmd).toBeCalled();
|
||||
expect(setupUtil.fixBinariesCmd).toBeCalled();
|
||||
expect(setupUtil.installVirtualBoxCmd).not.toBeCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
# Test against this version of Node.js
|
||||
environment:
|
||||
nodejs_version: "0.10"
|
||||
|
||||
# Install scripts. (runs after repo cloning)
|
||||
install:
|
||||
# Get the latest stable version of Node.js or io.js
|
||||
- ps: Install-Product node $env:nodejs_version
|
||||
# Updating NPM to avoid permission issues: http://www.appveyor.com/docs/lang/nodejs-iojs#locking-errors-eperm-eexist-tgz-lock
|
||||
- npm -g install npm@2
|
||||
- set PATH=%APPDATA%\npm;%PATH%
|
||||
# install modules
|
||||
- npm install
|
||||
|
||||
# Post-install test scripts.
|
||||
test_script:
|
||||
# Output useful info for debugging.
|
||||
- node --version
|
||||
- npm --version
|
||||
# run tests
|
||||
- npm test
|
65
gulpfile.js
65
gulpfile.js
|
@ -2,6 +2,7 @@ var babel = require('gulp-babel');
|
|||
var changed = require('gulp-changed');
|
||||
var concat = require('gulp-concat');
|
||||
var cssmin = require('gulp-cssmin');
|
||||
var rename = require('gulp-rename');
|
||||
var downloadatomshell = require('gulp-download-atom-shell');
|
||||
var fs = require('fs');
|
||||
var gulp = require('gulp');
|
||||
|
@ -167,11 +168,56 @@ gulp.task('settings', function () {
|
|||
string_src('settings.json', JSON.stringify(settings)).pipe(gulp.dest('dist/osx/' + options.appFilename.replace(' ', '\ ').replace('(','\(').replace(')','\)') + '/Contents/Resources/app'));
|
||||
});
|
||||
|
||||
gulp.task('release', function () {
|
||||
runSequence('download', 'dist', ['copy', 'images', 'js', 'styles', 'settings'], 'sign', 'zip');
|
||||
gulp.task('download-deps', function () {
|
||||
if(process.platform === 'win32') {
|
||||
return gulp.src('').pipe(
|
||||
shell(['powershell.exe -ExecutionPolicy unrestricted -File util\\deps.ps1'])
|
||||
);
|
||||
} else {
|
||||
return gulp.src('').pipe(
|
||||
shell(['./util/deps'])
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
gulp.task('default', ['download', 'copy', 'js', 'images', 'styles'], function () {
|
||||
gulp.task('copy-icns', ['download'], function () {
|
||||
if(process.platform === 'win32') {
|
||||
return gulp.src(options.icon)
|
||||
.pipe(rename('atom.icns'))
|
||||
.pipe(gulp.dest('./cache/resources'));
|
||||
} else {
|
||||
return gulp.src(options.icon)
|
||||
.pipe(rename('atom.icns'))
|
||||
.pipe(gulp.dest('./cache/Atom.app/Contents/Resources'));
|
||||
}
|
||||
});
|
||||
|
||||
gulp.task('copy-plist', ['download'], function (done) {
|
||||
if(process.platform === 'darwin') {
|
||||
return gulp.src('./util/Info.plist')
|
||||
.pipe(gulp.dest('./cache/Atom.app/Contents'));
|
||||
} else {
|
||||
done();
|
||||
}
|
||||
});
|
||||
|
||||
gulp.task('reset', function () {
|
||||
if(process.platform === 'win32') {
|
||||
return gulp.src('').pipe(
|
||||
shell(['powershell.exe -ExecutionPolicy unrestricted -Command "Start-Process powershell -verb runas -ArgumentList \\\"-ExecutionPolicy unrestricted -file c:\\Users\\Dominik\\Documents\\GitHub\\kitematic\\util\\reset.ps1\\\" -Wait"'])
|
||||
);
|
||||
} else {
|
||||
return gulp.src('').pipe(
|
||||
shell(['./util/reset'])
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
gulp.task('release', function () {
|
||||
runSequence('download-deps', 'download', 'copy-icns', 'copy-plist', 'dist', ['copy', 'images', 'js', 'styles', 'settings'], 'sign', 'zip');
|
||||
});
|
||||
|
||||
gulp.task('default', ['download-deps', 'download', 'copy-icns', 'copy-plist', 'copy', 'js', 'images', 'styles'], function () {
|
||||
gulp.watch('src/**/*.js', ['js']);
|
||||
gulp.watch('index.html', ['copy']);
|
||||
gulp.watch('styles/**/*.less', ['styles']);
|
||||
|
@ -181,7 +227,14 @@ gulp.task('default', ['download', 'copy', 'js', 'images', 'styles'], function ()
|
|||
|
||||
var env = process.env;
|
||||
env.NODE_ENV = 'development';
|
||||
gulp.src('').pipe(shell(['./cache/Atom.app/Contents/MacOS/Atom .'], {
|
||||
env: env
|
||||
}));
|
||||
|
||||
if(process.platform === 'win32') {
|
||||
gulp.src('').pipe(shell(['cache\\atom.exe .'], {
|
||||
env: env
|
||||
}));
|
||||
} else {
|
||||
gulp.src('').pipe(shell(['./cache/Atom.app/Contents/MacOS/Atom .'], {
|
||||
env: env
|
||||
}));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -6,6 +6,6 @@
|
|||
<title>Kitematic</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="Main.js"></script>
|
||||
<script src="Startup.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
12
package.json
12
package.json
|
@ -15,9 +15,8 @@
|
|||
"test": "jest",
|
||||
"release": "gulp release",
|
||||
"release:beta": "gulp release --beta",
|
||||
"preinstall": "./util/deps",
|
||||
"postinstall": "if [ `uname` == 'Darwin' ]; then gulp download && cp util/Info.plist cache/Atom.app/Contents/Info.plist && cp util/kitematic.icns cache/Atom.app/Contents/Resources/atom.icns; fi",
|
||||
"lint": "jsxhint src && jsxhint browser"
|
||||
"lint": "jsxhint src && jsxhint browser",
|
||||
"reset": "gulp reset"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
|
@ -45,19 +44,25 @@
|
|||
"atom-shell-version": "0.21.3",
|
||||
"virtualbox-version": "4.3.24",
|
||||
"virtualbox-filename": "VirtualBox-4.3.24.pkg",
|
||||
"virtualbox-filename-win": "VirtualBox-4.3.26.exe",
|
||||
"virtualbox-checksum": "100eee21df3808fc1b1e461e86f10b6d2a748935c5f31bc665f4ff0777e44a0b",
|
||||
"virtualbox-checksum-win": "9cb265babf307d825f5178693af95ffca077f80ae22cf43868c3538c159123ff",
|
||||
"dependencies": {
|
||||
"ansi-to-html": "0.3.0",
|
||||
"any-promise": "^0.1.0",
|
||||
"async": "^0.9.0",
|
||||
"bluebird": "^2.9.12",
|
||||
"bugsnag-js": "^2.4.7",
|
||||
"dockerode": "^2.0.7",
|
||||
"exec": "0.2.0",
|
||||
"fs-extra": "^0.17.0",
|
||||
"fs-promise": "^0.3.1",
|
||||
"jquery": "^2.1.3",
|
||||
"minimist": "^1.1.0",
|
||||
"mixpanel": "0.0.20",
|
||||
"node-uuid": "^1.4.2",
|
||||
"object-assign": "^2.0.0",
|
||||
"open": "0.0.5",
|
||||
"react": "^0.12.2",
|
||||
"react-bootstrap": "^0.15.1",
|
||||
"react-retina-image": "^1.1.2",
|
||||
|
@ -80,6 +85,7 @@
|
|||
"gulp-livereload": "^3.8.0",
|
||||
"gulp-plumber": "^0.6.6",
|
||||
"gulp-react": "^2.0.0",
|
||||
"gulp-rename": "^1.2.0",
|
||||
"gulp-shell": "^0.3.0",
|
||||
"gulp-sourcemaps": "^1.5.0",
|
||||
"gulp-util": "^3.0.4",
|
||||
|
|
|
@ -10,6 +10,8 @@ var machine = require('./DockerMachine');
|
|||
var RetinaImage = require('react-retina-image');
|
||||
var Router = require('react-router');
|
||||
var webPorts = require('./Util').webPorts;
|
||||
var util = require('./Util');
|
||||
var resources = require('./Resources');
|
||||
|
||||
var ContainerDetailsSubheader = React.createClass({
|
||||
mixins: [Router.State, Router.Navigation],
|
||||
|
@ -89,7 +91,7 @@ var ContainerDetailsSubheader = React.createClass({
|
|||
metrics.track('Opened In Browser', {
|
||||
from: 'header'
|
||||
});
|
||||
exec(['open', this.state.ports[this.state.defaultPort].url], function (err) {
|
||||
util.openPathOrUrl(this.state.ports[this.state.defaultPort].url, function (err) {
|
||||
if (err) { throw err; }
|
||||
});
|
||||
}
|
||||
|
@ -105,9 +107,8 @@ var ContainerDetailsSubheader = React.createClass({
|
|||
if (!this.disableTerminal()) {
|
||||
metrics.track('Terminaled Into Container');
|
||||
var container = this.props.container;
|
||||
var terminal = path.join(process.cwd(), 'resources', 'terminal');
|
||||
machine.ip().then(ip => {
|
||||
var cmd = [terminal, 'ssh', '-p', '22', '-o', 'UserKnownHostsFile=/dev/null', '-o', 'LogLevel=quiet', '-o', 'StrictHostKeyChecking=no', '-i', '~/.docker/machine/machines/' + machine.name() + '/id_rsa', 'docker@' + ip, '-t', 'docker', 'exec', '-i', '-t', container.Name, 'sh'];
|
||||
var cmd = [resources.terminal(), 'ssh', '-p', '22', '-o', 'UserKnownHostsFile=/dev/null', '-o', 'LogLevel=quiet', '-o', 'StrictHostKeyChecking=no', '-i', '~/.docker/machine/machines/' + machine.name() + '/id_rsa', 'docker@' + ip, '-t', 'docker', 'exec', '-i', '-t', container.Name, 'sh'];
|
||||
exec(cmd, function (stderr, stdout, code) {
|
||||
if (code) {
|
||||
console.log(stderr);
|
||||
|
|
|
@ -28,7 +28,7 @@ var ContainerHome = React.createClass({
|
|||
resizeWindow();
|
||||
},
|
||||
handleErrorClick: function () {
|
||||
util.exec(['open', 'https://github.com/kitematic/kitematic/issues/new']);
|
||||
util.openPathOrUrl('https://github.com/kitematic/kitematic/issues/new');
|
||||
},
|
||||
componentWillReceiveProps: function () {
|
||||
this.init();
|
||||
|
|
|
@ -5,6 +5,7 @@ var path = require('path');
|
|||
var exec = require('exec');
|
||||
var metrics = require('./Metrics');
|
||||
var Router = require('react-router');
|
||||
var util = require('./Util');
|
||||
|
||||
var ContainerHomeFolder = React.createClass({
|
||||
mixins: [Router.State, Router.Navigation],
|
||||
|
@ -12,7 +13,7 @@ var ContainerHomeFolder = React.createClass({
|
|||
metrics.track('Opened Volume Directory', {
|
||||
from: 'home'
|
||||
});
|
||||
exec(['open', path], function (err) {
|
||||
util.openPathOrUrl(path, function (err) {
|
||||
if (err) { throw err; }
|
||||
});
|
||||
},
|
||||
|
|
|
@ -7,6 +7,7 @@ var Router = require('react-router');
|
|||
var request = require('request');
|
||||
var metrics = require('./Metrics');
|
||||
var webPorts = require('./Util').webPorts;
|
||||
var util = require('./Util');
|
||||
|
||||
var ContainerHomePreview = React.createClass({
|
||||
mixins: [Router.State, Router.Navigation],
|
||||
|
@ -61,7 +62,7 @@ var ContainerHomePreview = React.createClass({
|
|||
metrics.track('Opened In Browser', {
|
||||
from: 'preview'
|
||||
});
|
||||
exec(['open', this.state.ports[this.state.defaultPort].url], function (err) {
|
||||
util.openPathOrUrl(this.state.ports[this.state.defaultPort].url, function (err) {
|
||||
if (err) { throw err; }
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ var ContainerStore = require('./ContainerStore');
|
|||
var ContainerUtil = require('./ContainerUtil');
|
||||
var metrics = require('./Metrics');
|
||||
var webPorts = require('./Util').webPorts;
|
||||
var util = require('./Util');
|
||||
|
||||
var ContainerSettingsPorts = React.createClass({
|
||||
mixins: [Router.State, Router.Navigation],
|
||||
|
@ -38,7 +39,7 @@ var ContainerSettingsPorts = React.createClass({
|
|||
metrics.track('Opened In Browser', {
|
||||
from: 'settings'
|
||||
});
|
||||
exec(['open', url], function (err) {
|
||||
util.openPathOrUrl(url, function (err) {
|
||||
if (err) { throw err; }
|
||||
});
|
||||
},
|
||||
|
|
|
@ -6,6 +6,7 @@ var exec = require('exec');
|
|||
var dialog = remote.require('dialog');
|
||||
var metrics = require('./Metrics');
|
||||
var ContainerStore = require('./ContainerStore');
|
||||
var util = require('./Util');
|
||||
|
||||
var ContainerSettingsVolumes = React.createClass({
|
||||
mixins: [Router.State, Router.Navigation],
|
||||
|
@ -35,7 +36,7 @@ var ContainerSettingsVolumes = React.createClass({
|
|||
metrics.track('Opened Volume Directory', {
|
||||
from: 'settings'
|
||||
});
|
||||
exec(['open', path], function (err) {
|
||||
util.openPathOrUrl(path, function (err) {
|
||||
if (err) { throw err; }
|
||||
});
|
||||
},
|
||||
|
|
|
@ -104,7 +104,17 @@ var ContainerStore = assign(Object.create(EventEmitter.prototype), {
|
|||
return b.indexOf(':' + key) !== -1;
|
||||
});
|
||||
if (!existingBind) {
|
||||
binds.push(path.join(util.home(), 'Kitematic', name, key)+ ':' + key);
|
||||
var home = util.home();
|
||||
|
||||
if(util.isWindows()) {
|
||||
home = home.charAt(0).toLowerCase() + home.slice(1);
|
||||
home = "/" + home.replace(':', '').replace(/\\/g, '/');
|
||||
var fullPath = path.join(home, 'Kitematic', name, key);
|
||||
fullPath = fullPath.replace(/\\/g, '/');
|
||||
binds.push(fullPath + ':' + key);
|
||||
} else {
|
||||
binds.push(path.join(home, 'Kitematic', name, key) + ':' + key);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ var Containers = React.createClass({
|
|||
metrics.track('Opened Issue Reporter', {
|
||||
from: 'app'
|
||||
});
|
||||
util.exec(['open', 'https://github.com/kitematic/kitematic/issues/new']);
|
||||
util.openPathOrUrl('https://github.com/kitematic/kitematic/issues/new');
|
||||
},
|
||||
handleMouseEnterDockerTerminal: function () {
|
||||
this.setState({
|
||||
|
|
|
@ -2,12 +2,13 @@ var fs = require('fs');
|
|||
var path = require('path');
|
||||
var dockerode = require('dockerode');
|
||||
var Promise = require('bluebird');
|
||||
var util = require('./Util');
|
||||
|
||||
var Docker = {
|
||||
_host: null,
|
||||
_client: null,
|
||||
setup: function(ip, name) {
|
||||
var certDir = path.join(process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'], '.docker/machine/machines', name);
|
||||
var certDir = path.join(util.home(), '.docker/machine/machines', name);
|
||||
if (!fs.existsSync(certDir)) {
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -1,27 +1,21 @@
|
|||
var _ = require('underscore');
|
||||
var path = require('path');
|
||||
var Promise = require('bluebird');
|
||||
var _ = require('underscore');
|
||||
var fs = require('fs');
|
||||
var util = require('./Util');
|
||||
var exec = require('child_process').exec;
|
||||
var resources = require('./Resources');
|
||||
|
||||
var NAME = 'dev';
|
||||
|
||||
var DockerMachine = {
|
||||
command: function () {
|
||||
return path.join(process.cwd(), 'resources', 'docker-machine-' + this.version());
|
||||
command() {
|
||||
return resources.docker_machine();
|
||||
},
|
||||
name: function () {
|
||||
name() {
|
||||
return NAME;
|
||||
},
|
||||
version: function () {
|
||||
try {
|
||||
return JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'))['docker-machine-version'];
|
||||
} catch (err) {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
isoversion: function () {
|
||||
isoversion() {
|
||||
try {
|
||||
var data = fs.readFileSync(path.join(util.home(), '.docker', 'machine', 'machines', NAME, 'boot2docker.iso'), 'utf8');
|
||||
var match = data.match(/Boot2Docker-v(\d+\.\d+\.\d+)/);
|
||||
|
@ -34,8 +28,8 @@ var DockerMachine = {
|
|||
return null;
|
||||
}
|
||||
},
|
||||
info: function () {
|
||||
return util.exec([DockerMachine.command(), 'ls']).then(stdout => {
|
||||
info() {
|
||||
return util.exec([this.command(), 'ls']).then(stdout => {
|
||||
var lines = stdout.trim().split('\n').filter(line => line.indexOf('time=') === -1);
|
||||
var machines = {};
|
||||
lines.slice(1, lines.length).forEach(line => {
|
||||
|
@ -55,44 +49,44 @@ var DockerMachine = {
|
|||
}
|
||||
});
|
||||
},
|
||||
exists: function () {
|
||||
return DockerMachine.info().then(() => {
|
||||
exists() {
|
||||
return this.info().then(() => {
|
||||
return true;
|
||||
}).catch(() => {
|
||||
return false;
|
||||
});
|
||||
},
|
||||
|
||||
create: function () {
|
||||
return util.exec([DockerMachine.command(), 'create', '-d', 'virtualbox', '--virtualbox-memory', '2048', NAME]);
|
||||
create() {
|
||||
return util.exec([this.command(), 'create', '-d', 'virtualbox', '--virtualbox-memory', '2048', NAME]);
|
||||
},
|
||||
start: function () {
|
||||
return util.exec([DockerMachine.command(), 'start', NAME]);
|
||||
start() {
|
||||
return util.exec([this.command(), 'start', NAME]);
|
||||
},
|
||||
stop: function () {
|
||||
return util.exec([DockerMachine.command(), 'stop', NAME]);
|
||||
stop() {
|
||||
return util.exec([this.command(), 'stop', NAME]);
|
||||
},
|
||||
upgrade: function () {
|
||||
return util.exec([DockerMachine.command(), 'upgrade', NAME]);
|
||||
upgrade() {
|
||||
return util.exec([this.command(), 'upgrade', NAME]);
|
||||
},
|
||||
rm: function () {
|
||||
return util.exec([DockerMachine.command(), 'rm', '-f', NAME]);
|
||||
rm() {
|
||||
return util.exec([this.command(), 'rm', '-f', NAME]);
|
||||
},
|
||||
ip: function () {
|
||||
return util.exec([DockerMachine.command(), 'ip', NAME]).then(stdout => {
|
||||
ip() {
|
||||
return util.exec([this.command(), 'ip', NAME]).then(stdout => {
|
||||
return Promise.resolve(stdout.trim().replace('\n', ''));
|
||||
});
|
||||
},
|
||||
regenerateCerts: function () {
|
||||
return util.exec([DockerMachine.command(), 'tls-regenerate-certs', '-f', NAME]);
|
||||
regenerateCerts() {
|
||||
return util.exec([this.command(), 'tls-regenerate-certs', '-f', NAME]);
|
||||
},
|
||||
state: function () {
|
||||
return DockerMachine.info().then(info => {
|
||||
state() {
|
||||
return this.info().then(info => {
|
||||
return info ? info.state : null;
|
||||
});
|
||||
},
|
||||
disk: function () {
|
||||
return util.exec([DockerMachine.command(), 'ssh', NAME, 'df']).then(stdout => {
|
||||
disk() {
|
||||
return util.exec([this.command(), 'ssh', NAME, 'df']).then(stdout => {
|
||||
try {
|
||||
var lines = stdout.split('\n');
|
||||
var dataline = _.find(lines, function (line) {
|
||||
|
@ -115,7 +109,7 @@ var DockerMachine = {
|
|||
}
|
||||
});
|
||||
},
|
||||
memory: function () {
|
||||
memory() {
|
||||
return util.exec([this.command(), 'ssh', NAME, 'free -m']).then(stdout => {
|
||||
try {
|
||||
var lines = stdout.split('\n');
|
||||
|
@ -141,13 +135,13 @@ var DockerMachine = {
|
|||
}
|
||||
});
|
||||
},
|
||||
stats: function () {
|
||||
DockerMachine.state().then(state => {
|
||||
stats() {
|
||||
this.state().then(state => {
|
||||
if (state === 'Stopped') {
|
||||
return Promise.resolve({state: state});
|
||||
}
|
||||
var memory = DockerMachine.memory();
|
||||
var disk = DockerMachine.disk();
|
||||
var memory = this.memory();
|
||||
var disk = this.disk();
|
||||
return Promise.all([memory, disk]).spread((memory, disk) => {
|
||||
return Promise.resolve({
|
||||
memory: memory,
|
||||
|
@ -156,13 +150,18 @@ var DockerMachine = {
|
|||
});
|
||||
});
|
||||
},
|
||||
dockerTerminal: function () {
|
||||
var terminal = path.join(process.cwd(), 'resources', 'terminal');
|
||||
this.info().then(machine => {
|
||||
var cmd = [terminal, `DOCKER_HOST=${machine.url} DOCKER_CERT_PATH=${path.join(process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'], '.docker/machine/machines/' + machine.name)} DOCKER_TLS_VERIFY=1 $SHELL`];
|
||||
util.exec(cmd).then(() => {});
|
||||
});
|
||||
},
|
||||
dockerTerminal() {
|
||||
if(util.isWindows()) {
|
||||
this.info().then(machine => {
|
||||
util.execProper(`start cmd.exe /k "SET DOCKER_HOST=${machine.url}&& SET DOCKER_CERT_PATH=${path.join(util.home(), '.docker/machine/machines/' + machine.name)}&& SET DOCKER_TLS_VERIFY=1`);
|
||||
});
|
||||
} else {
|
||||
this.info().then(machine => {
|
||||
var cmd = [resources.terminal(), `DOCKER_HOST=${machine.url} DOCKER_CERT_PATH=${path.join(util.home(), '.docker/machine/machines/' + machine.name)} DOCKER_TLS_VERIFY=1 $SHELL`];
|
||||
util.exec(cmd).then(() => {});
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = DockerMachine;
|
||||
|
|
|
@ -21,7 +21,7 @@ var MenuTemplate = function () {
|
|||
},
|
||||
{
|
||||
label: 'Preferences',
|
||||
accelerator: 'Command+,',
|
||||
accelerator: util.CommandOrCtrl() + '+,',
|
||||
enabled: !!docker.host(),
|
||||
click: function () {
|
||||
metrics.track('Opened Preferences', {
|
||||
|
@ -42,12 +42,12 @@ var MenuTemplate = function () {
|
|||
},
|
||||
{
|
||||
label: 'Hide Kitematic',
|
||||
accelerator: 'Command+H',
|
||||
accelerator: util.CommandOrCtrl() + '+H',
|
||||
selector: 'hide:'
|
||||
},
|
||||
{
|
||||
label: 'Hide Others',
|
||||
accelerator: 'Command+Shift+H',
|
||||
accelerator: util.CommandOrCtrl() + '+Shift+H',
|
||||
selector: 'hideOtherApplications:'
|
||||
},
|
||||
{
|
||||
|
@ -59,11 +59,11 @@ var MenuTemplate = function () {
|
|||
},
|
||||
{
|
||||
label: 'Quit',
|
||||
accelerator: 'Command+Q',
|
||||
accelerator: util.CommandOrCtrl() + '+Q',
|
||||
click: function() {
|
||||
app.quit();
|
||||
}
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -74,7 +74,7 @@ var MenuTemplate = function () {
|
|||
},
|
||||
{
|
||||
label: 'Open Docker Command Line Terminal',
|
||||
accelerator: 'Command+Shift+T',
|
||||
accelerator: util.CommandOrCtrl() + '+Shift+T',
|
||||
enabled: !!docker.host(),
|
||||
click: function() {
|
||||
metrics.track('Opened Docker Terminal', {
|
||||
|
@ -82,7 +82,7 @@ var MenuTemplate = function () {
|
|||
});
|
||||
machine.dockerTerminal();
|
||||
}
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -90,12 +90,12 @@ var MenuTemplate = function () {
|
|||
submenu: [
|
||||
{
|
||||
label: 'Undo',
|
||||
accelerator: 'Command+Z',
|
||||
accelerator: util.CommandOrCtrl() + '+Z',
|
||||
selector: 'undo:'
|
||||
},
|
||||
{
|
||||
label: 'Redo',
|
||||
accelerator: 'Shift+Command+Z',
|
||||
accelerator: 'Shift+' + util.CommandOrCtrl() + '+Z',
|
||||
selector: 'redo:'
|
||||
},
|
||||
{
|
||||
|
@ -103,24 +103,24 @@ var MenuTemplate = function () {
|
|||
},
|
||||
{
|
||||
label: 'Cut',
|
||||
accelerator: 'Command+X',
|
||||
accelerator: util.CommandOrCtrl() + '+X',
|
||||
selector: 'cut:'
|
||||
},
|
||||
{
|
||||
label: 'Copy',
|
||||
accelerator: 'Command+C',
|
||||
accelerator: util.CommandOrCtrl() + '+C',
|
||||
selector: 'copy:'
|
||||
},
|
||||
{
|
||||
label: 'Paste',
|
||||
accelerator: 'Command+V',
|
||||
accelerator: util.CommandOrCtrl() + '+V',
|
||||
selector: 'paste:'
|
||||
},
|
||||
{
|
||||
label: 'Select All',
|
||||
accelerator: 'Command+A',
|
||||
accelerator: util.CommandOrCtrl() + '+A',
|
||||
selector: 'selectAll:'
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -128,9 +128,9 @@ var MenuTemplate = function () {
|
|||
submenu: [
|
||||
{
|
||||
label: 'Toggle DevTools',
|
||||
accelerator: 'Alt+Command+I',
|
||||
accelerator: 'Alt+' + util.CommandOrCtrl() + '+I',
|
||||
click: function() { remote.getCurrentWindow().toggleDevTools(); }
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -138,12 +138,12 @@ var MenuTemplate = function () {
|
|||
submenu: [
|
||||
{
|
||||
label: 'Minimize',
|
||||
accelerator: 'Command+M',
|
||||
accelerator: util.CommandOrCtrl() + '+M',
|
||||
selector: 'performMiniaturize:'
|
||||
},
|
||||
{
|
||||
label: 'Close',
|
||||
accelerator: 'Command+W',
|
||||
accelerator: util.CommandOrCtrl() + '+W',
|
||||
click: function () {
|
||||
remote.getCurrentWindow().hide();
|
||||
}
|
||||
|
@ -154,7 +154,7 @@ var MenuTemplate = function () {
|
|||
{
|
||||
label: 'Bring All to Front',
|
||||
selector: 'arrangeInFront:'
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
|
@ -166,11 +166,11 @@ var MenuTemplate = function () {
|
|||
metrics.track('Opened Issue Reporter', {
|
||||
from: 'menu'
|
||||
});
|
||||
util.exec(['open', 'https://github.com/kitematic/kitematic/issues/new']);
|
||||
util.openPathOrUrl('https://github.com/kitematic/kitematic/issues/new');
|
||||
}
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
|
|
|
@ -45,7 +45,14 @@ var Metrics = {
|
|||
localStorage.setItem('metrics.id', uuid.v4());
|
||||
}
|
||||
|
||||
var os = navigator.userAgent.match(/Mac OS X (\d+_\d+_\d+)/)[1].replace(/_/g, '.');
|
||||
var os;
|
||||
|
||||
if(util.isWindows()) {
|
||||
os = navigator.userAgent;
|
||||
} else {
|
||||
os = navigator.userAgent.match(/Mac OS X (\d+_\d+_\d+)/)[1].replace(/_/g, '.');
|
||||
}
|
||||
|
||||
mixpanel.track(name, assign({
|
||||
distinct_id: id,
|
||||
version: util.packagejson().version,
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
var util = require('./Util');
|
||||
var path = require('path');
|
||||
|
||||
module.exports = {
|
||||
resourceDir() {
|
||||
return process.env.RESOURCES_PATH;
|
||||
},
|
||||
macsudo() {
|
||||
return path.join(this.resourceDir(), 'macsudo');
|
||||
},
|
||||
terminal() {
|
||||
return path.join(this.resourceDir(), 'terminal');
|
||||
},
|
||||
docker() {
|
||||
return path.join(this.resourceDir(), 'docker-' + util.packagejson()['docker-version'] + util.binsEnding());
|
||||
},
|
||||
docker_machine() {
|
||||
return path.join(this.resourceDir(), 'docker-machine-' + util.packagejson()['docker-machine-version'] + util.binsEnding());
|
||||
}
|
||||
};
|
|
@ -26,8 +26,7 @@ var _steps = [{
|
|||
totalPercent: 35,
|
||||
percent: 0,
|
||||
run: function (progressCallback) {
|
||||
var packagejson = util.packagejson();
|
||||
return setupUtil.download(setupUtil.virtualBoxUrl(), path.join(util.supportDir(), packagejson['virtualbox-filename']), packagejson['virtualbox-checksum'], percent => {
|
||||
return setupUtil.download(setupUtil.virtualBoxUrl(), path.join(util.supportDir(), setupUtil.virtualBoxFileName()), setupUtil.virtualBoxChecksum(), percent => {
|
||||
progressCallback(percent);
|
||||
});
|
||||
}
|
||||
|
@ -39,21 +38,20 @@ var _steps = [{
|
|||
percent: 0,
|
||||
seconds: 5,
|
||||
run: Promise.coroutine(function* (progressCallback) {
|
||||
var cmd = setupUtil.copyBinariesCmd() + ' && ' + setupUtil.fixBinariesCmd();
|
||||
yield setupUtil.copyBinariesCmd();
|
||||
yield setupUtil.fixBinariesCmd();
|
||||
|
||||
if (!virtualBox.installed()) {
|
||||
yield virtualBox.killall();
|
||||
cmd += ' && ' + setupUtil.installVirtualBoxCmd();
|
||||
} else {
|
||||
if (!setupUtil.needsBinaryFix()) {
|
||||
return;
|
||||
try {
|
||||
progressCallback(50); // TODO: detect when the installation has started so we can simulate progress
|
||||
yield setupUtil.installVirtualBoxCmd();
|
||||
} catch (err) {
|
||||
throw null;
|
||||
}
|
||||
}
|
||||
try {
|
||||
progressCallback(50); // TODO: detect when the installation has started so we can simulate progress
|
||||
yield util.exec(setupUtil.macSudoCmd(cmd));
|
||||
} catch (err) {
|
||||
throw null;
|
||||
}
|
||||
|
||||
return;
|
||||
})
|
||||
}, {
|
||||
name: 'init',
|
||||
|
@ -70,9 +68,33 @@ var _steps = [{
|
|||
try {
|
||||
yield machine.rm();
|
||||
yield machine.create();
|
||||
if(util.isWindows()) {
|
||||
var home = util.home();
|
||||
var driveLetter = home.charAt(0);
|
||||
var parts = home.split('\\').slice(0, -1);
|
||||
var usersDirName = parts[parts.length-1];
|
||||
var usersDirPath = parts.join('\\');
|
||||
var shareName = driveLetter + "/" + usersDirName;
|
||||
|
||||
yield machine.stop();
|
||||
yield virtualBox.mountSharedDir(machine.name(), shareName, usersDirPath);
|
||||
yield machine.start();
|
||||
}
|
||||
} catch (err) {
|
||||
rimraf.sync(path.join(util.home(), '.docker', 'machine', 'machines', machine.name()));
|
||||
yield machine.create();
|
||||
if(util.isWindows()) {
|
||||
var home = util.home();
|
||||
var driveLetter = home.charAt(0);
|
||||
var parts = home.split('\\').slice(0, -1);
|
||||
var usersDirName = parts[parts.length-1];
|
||||
var usersDirPath = parts.join('\\');
|
||||
var shareName = driveLetter + "/" + usersDirName;
|
||||
|
||||
yield machine.stop();
|
||||
yield virtualBox.mountSharedDir(machine.name(), shareName, usersDirPath);
|
||||
yield machine.start();
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -156,9 +178,10 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
|
|||
var packagejson = util.packagejson();
|
||||
var isoversion = machine.isoversion();
|
||||
var required = {};
|
||||
var vboxfile = path.join(util.supportDir(), packagejson['virtualbox-filename']);
|
||||
var vboxfile = path.join(util.supportDir(), setupUtil.virtualBoxFileName());
|
||||
var vboxNeedsInstall = !virtualBox.installed();
|
||||
required.download = vboxNeedsInstall && (!fs.existsSync(vboxfile) || setupUtil.checksum(vboxfile) !== packagejson['virtualbox-checksum']);
|
||||
|
||||
required.download = vboxNeedsInstall && (!fs.existsSync(vboxfile) || setupUtil.checksum(vboxfile) !== setupUtil.virtualBoxChecksum());
|
||||
required.install = vboxNeedsInstall || setupUtil.needsBinaryFix();
|
||||
required.init = required.install || !(yield machine.exists()) || (yield machine.state()) !== 'Running' || !isoversion || setupUtil.compareVersions(isoversion, packagejson['docker-version']) < 0;
|
||||
|
||||
|
@ -233,7 +256,7 @@ var SetupStore = assign(Object.create(EventEmitter.prototype), {
|
|||
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,
|
||||
ip: ip
|
||||
};
|
||||
}
|
||||
console.log('Finished Steps');
|
||||
|
|
113
src/SetupUtil.js
113
src/SetupUtil.js
|
@ -1,74 +1,63 @@
|
|||
var _ = require('underscore');
|
||||
var crypto = require('crypto');
|
||||
var fs = require('fs');
|
||||
var fs = require('fs-promise');
|
||||
var path = require('path');
|
||||
var request = require('request');
|
||||
var progress = require('request-progress');
|
||||
var Promise = require('bluebird');
|
||||
var util = require('./Util');
|
||||
var resources = require('./Resources');
|
||||
|
||||
var SetupUtil = {
|
||||
needsBinaryFix: function () {
|
||||
if (!fs.existsSync('/usr/local') || !fs.existsSync('/usr/local/bin')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (fs.statSync('/usr/local/bin').gid !== 80 || fs.statSync('/usr/local/bin').uid !== process.getuid()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (fs.existsSync('/usr/local/bin/docker') && (fs.statSync('/usr/local/bin/docker').gid !== 80 || fs.statSync('/usr/local/bin/docker').uid !== process.getuid())) {
|
||||
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())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
needsBinaryFix() {
|
||||
return !!(util.pathDoesNotExistOrDenied(util.binsPath()) || util.pathDoesNotExistOrDenied(util.dockerBinPath()) || util.pathDoesNotExistOrDenied(util.dockerMachineBinPath()));
|
||||
},
|
||||
copycmd: function (src, dest) {
|
||||
return ['rm', '-f', dest, '&&', 'cp', src, dest];
|
||||
},
|
||||
escapePath: function (str) {
|
||||
escapePath(str) {
|
||||
return str.replace(/ /g, '\\ ').replace(/\(/g, '\\(').replace(/\)/g, '\\)');
|
||||
},
|
||||
shouldUpdateBinaries: function () {
|
||||
var packagejson = util.packagejson();
|
||||
return !fs.existsSync('/usr/local/bin/docker') ||
|
||||
!fs.existsSync('/usr/local/bin/docker-machine') ||
|
||||
this.checksum('/usr/local/bin/docker-machine') !== this.checksum(path.join(util.resourceDir(), 'docker-machine-' + packagejson['docker-machine-version'])) ||
|
||||
this.checksum('/usr/local/bin/docker') !== this.checksum(path.join(util.resourceDir(), 'docker-' + packagejson['docker-version']));
|
||||
shouldUpdateBinaries() {
|
||||
return !fs.existsSync(util.dockerBinPath()) ||
|
||||
!fs.existsSync(util.dockerMachineBinPath()) ||
|
||||
this.checksum(util.dockerMachineBinPath()) !== this.checksum(resources.docker_machine()) ||
|
||||
this.checksum(util.dockerBinPath()) !== this.checksum(resources.docker());
|
||||
|
||||
},
|
||||
copyBinariesCmd: function () {
|
||||
var packagejson = util.packagejson();
|
||||
var cmd = ['mkdir', '-p', '/usr/local/bin'];
|
||||
cmd.push('&&');
|
||||
cmd.push.apply(cmd, this.copycmd(this.escapePath(path.join(util.resourceDir(), 'docker-machine-' + packagejson['docker-machine-version'])), '/usr/local/bin/docker-machine'));
|
||||
cmd.push('&&');
|
||||
cmd.push.apply(cmd, this.copycmd(this.escapePath(path.join(util.resourceDir(), 'docker-' + packagejson['docker-version'])), '/usr/local/bin/docker'));
|
||||
return cmd.join(' ');
|
||||
copyBinariesCmd: Promise.coroutine(function* () {
|
||||
yield fs.mkdirs(util.binsPath());
|
||||
yield fs.copy(resources.docker_machine(), util.dockerMachineBinPath());
|
||||
yield fs.copy(resources.docker(), util.dockerBinPath());
|
||||
return Promise.resolve();
|
||||
}),
|
||||
fixBinariesCmd: Promise.coroutine(function* () {
|
||||
if(util.isWindows()) {
|
||||
return;
|
||||
}
|
||||
|
||||
yield fs.chown(util.binsPath(), process.getuid(), '80');
|
||||
yield fs.chown(util.dockerBinPath(), process.getuid(), '80');
|
||||
yield fs.chown(util.dockerMachineBinPath(), process.getuid(), '80');
|
||||
return Promise.resolve();
|
||||
}),
|
||||
installVirtualBoxCmd: Promise.coroutine(function* () {
|
||||
if(util.isWindows()) {
|
||||
yield util.execProper(`powershell.exe -ExecutionPolicy unrestricted -Command "Start-Process \\\"${path.join(util.supportDir(), this.virtualBoxFileName())}\\\" -ArgumentList \\\"--silent --msiparams REBOOT=ReallySuppress\\\" -Verb runAs -Wait"`);
|
||||
} else {
|
||||
yield util.exec(this.macSudoCmd(`installer -pkg ${this.escapePath(path.join(util.supportDir(), this.virtualBoxFileName()))} -target /`));
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}),
|
||||
virtualBoxUrl() {
|
||||
if(util.isWindows()) {
|
||||
return 'http://download.virtualbox.org/virtualbox/4.3.26/VirtualBox-4.3.26-98988-Win.exe';
|
||||
} else {
|
||||
return `https://github.com/kitematic/virtualbox/releases/download/${util.packagejson()['virtualbox-version']}/${this.virtualBoxFileName()}`;
|
||||
}
|
||||
},
|
||||
fixBinariesCmd: function () {
|
||||
var cmd = [];
|
||||
cmd.push.apply(cmd, ['chown', `${process.getuid()}:${80}`, path.join('/usr/local/bin')]);
|
||||
cmd.push('&&');
|
||||
cmd.push.apply(cmd, ['chown', `${process.getuid()}:${80}`, path.join('/usr/local/bin', 'docker-machine')]);
|
||||
cmd.push('&&');
|
||||
cmd.push.apply(cmd, ['chown', `${process.getuid()}:${80}`, path.join('/usr/local/bin', 'docker')]);
|
||||
return cmd.join(' ');
|
||||
macSudoCmd(cmd) {
|
||||
return `${this.escapePath(resources.macsudo())} -p "Kitematic requires administrative privileges to install." sh -c \"${cmd}\"`;
|
||||
},
|
||||
installVirtualBoxCmd: function () {
|
||||
var packagejson = util.packagejson();
|
||||
return `installer -pkg ${this.escapePath(path.join(util.supportDir(), packagejson['virtualbox-filename']))} -target /`;
|
||||
},
|
||||
virtualBoxUrl: function () {
|
||||
var packagejson = util.packagejson();
|
||||
return `https://github.com/kitematic/virtualbox/releases/download/${packagejson['virtualbox-version']}/${packagejson['virtualbox-filename']}`;
|
||||
},
|
||||
macSudoCmd: function (cmd) {
|
||||
return `${this.escapePath(path.join(util.resourceDir(), 'macsudo'))} -p "Kitematic requires administrative privileges to install." sh -c \"${cmd}\"`;
|
||||
},
|
||||
simulateProgress: function (estimateSeconds, progress) {
|
||||
simulateProgress(estimateSeconds, progress) {
|
||||
var times = _.range(0, estimateSeconds * 1000, 200);
|
||||
var timers = [];
|
||||
_.each(times, time => {
|
||||
|
@ -78,10 +67,10 @@ var SetupUtil = {
|
|||
timers.push(timer);
|
||||
});
|
||||
},
|
||||
checksum: function (filename) {
|
||||
checksum(filename) {
|
||||
return crypto.createHash('sha256').update(fs.readFileSync(filename), 'utf8').digest('hex');
|
||||
},
|
||||
download: function (url, filename, checksum, percentCallback) {
|
||||
download(url, filename, checksum, percentCallback) {
|
||||
return new Promise((resolve, reject) => {
|
||||
if (fs.existsSync(filename)) {
|
||||
var existingChecksum = this.checksum(filename);
|
||||
|
@ -109,7 +98,13 @@ var SetupUtil = {
|
|||
});
|
||||
});
|
||||
},
|
||||
compareVersions: function (v1, v2, options) {
|
||||
virtualBoxFileName() {
|
||||
return util.isWindows() ? util.packagejson()['virtualbox-filename-win'] : util.packagejson()['virtualbox-filename'];
|
||||
},
|
||||
virtualBoxChecksum() {
|
||||
return util.isWindows() ? util.packagejson()['virtualbox-checksum-win'] : util.packagejson()['virtualbox-checksum'];
|
||||
},
|
||||
compareVersions(v1, v2, options) {
|
||||
var lexicographical = options && options.lexicographical,
|
||||
zeroExtend = options && options.zeroExtend,
|
||||
v1parts = v1.split('.'),
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
require('./Main');
|
70
src/Util.js
70
src/Util.js
|
@ -1,10 +1,12 @@
|
|||
var exec = require('exec');
|
||||
var execProper = require('child_process').exec;
|
||||
var Promise = require('bluebird');
|
||||
var fs = require('fs');
|
||||
var fs = require('fs-promise');
|
||||
var path = require('path');
|
||||
var open = require('open');
|
||||
|
||||
module.exports = {
|
||||
exec: function (args, options) {
|
||||
exec(args, options) {
|
||||
options = options || {};
|
||||
return new Promise((resolve, reject) => {
|
||||
exec(args, options, (stderr, stdout, code) => {
|
||||
|
@ -17,32 +19,64 @@ module.exports = {
|
|||
});
|
||||
});
|
||||
},
|
||||
home: function () {
|
||||
return process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'];
|
||||
},
|
||||
supportDir: function () {
|
||||
var dirs = ['Library', 'Application\ Support', 'Kitematic'];
|
||||
var acc = process.env.HOME;
|
||||
dirs.forEach(function (d) {
|
||||
acc = path.join(acc, d);
|
||||
if (!fs.existsSync(acc)) {
|
||||
fs.mkdirSync(acc);
|
||||
}
|
||||
execProper(args, options) {
|
||||
options = options || {};
|
||||
var cmd = Array.isArray(args) ? args.join(' ') : args;
|
||||
return new Promise((resolve, reject) => {
|
||||
execProper(cmd, options, (stderr, stdout, code) => {
|
||||
if (code) {
|
||||
reject(new Error(cmd + ' returned non zero exit code\nstdout:' + stdout + '\nstderr:' + stderr));
|
||||
} else {
|
||||
resolve(stdout);
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
home() {
|
||||
return process.env[this.isWindows() ? 'USERPROFILE' : 'HOME'];
|
||||
},
|
||||
binsPath() {
|
||||
return this.isWindows() ? path.join(this.home(), 'Kitematic-bins') : path.join('/usr/local/bin');
|
||||
},
|
||||
binsEnding() {
|
||||
return this.isWindows() ? '.exe' : '';
|
||||
},
|
||||
dockerBinPath() {
|
||||
return path.join(this.binsPath(), 'docker' + this.binsEnding());
|
||||
},
|
||||
dockerMachineBinPath() {
|
||||
return path.join(this.binsPath(), 'docker-machine' + this.binsEnding());
|
||||
},
|
||||
pathDoesNotExistOrDenied(path) {
|
||||
if(this.isWindows()) {
|
||||
return (!fs.existsSync(path));
|
||||
} else {
|
||||
return (!fs.existsSync(path) || fs.statSync(path).gid !== 80 || fs.statSync(path).uid !== process.getuid());
|
||||
}
|
||||
},
|
||||
openPathOrUrl(pathOrUrl, callback) {
|
||||
open(pathOrUrl, callback);
|
||||
},
|
||||
supportDir() {
|
||||
var acc = path.join(this.home(), 'Library', 'Application\ Support', 'Kitematic');
|
||||
fs.mkdirsSync(acc);
|
||||
return acc;
|
||||
},
|
||||
resourceDir: function () {
|
||||
return process.env.RESOURCES_PATH;
|
||||
},
|
||||
packagejson: function () {
|
||||
packagejson() {
|
||||
return JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
|
||||
},
|
||||
settingsjson: function () {
|
||||
settingsjson() {
|
||||
var settingsjson = {};
|
||||
try {
|
||||
settingsjson = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'settings.json'), 'utf8'));
|
||||
} catch (err) {}
|
||||
return settingsjson;
|
||||
},
|
||||
isWindows() {
|
||||
return process.platform === 'win32';
|
||||
},
|
||||
CommandOrCtrl() {
|
||||
return this.isWindows() ? 'Ctrl' : 'Command';
|
||||
},
|
||||
webPorts: ['80', '8000', '8080', '3000', '5000', '2368', '9200', '8983']
|
||||
};
|
||||
|
|
|
@ -4,10 +4,18 @@ var Promise = require('bluebird');
|
|||
|
||||
var VirtualBox = {
|
||||
command: function () {
|
||||
return '/usr/bin/VBoxManage';
|
||||
if(util.isWindows()) {
|
||||
return 'C:\\Program Files\\Oracle\\VirtualBox\\VBoxManage.exe';
|
||||
} else {
|
||||
return '/usr/bin/VBoxManage';
|
||||
}
|
||||
},
|
||||
installed: function () {
|
||||
return fs.existsSync('/usr/bin/VBoxManage') && fs.existsSync('/Applications/VirtualBox.app');
|
||||
if(util.isWindows()) {
|
||||
return fs.existsSync('C:\\Program Files\\Oracle\\VirtualBox\\VBoxManage.exe') && fs.existsSync('C:\\Program Files\\Oracle\\VirtualBox\\VirtualBox.exe');
|
||||
} else {
|
||||
return fs.existsSync('/usr/bin/VBoxManage') && fs.existsSync('/Applications/VirtualBox.app');
|
||||
}
|
||||
},
|
||||
version: function () {
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -26,14 +34,29 @@ var VirtualBox = {
|
|||
}
|
||||
return util.exec(this.command() + ' list runningvms | sed -E \'s/.*\\{(.*)\\}/\\1/\' | xargs -L1 -I {} ' + this.command() + ' controlvm {} poweroff');
|
||||
},
|
||||
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']);
|
||||
},
|
||||
killall: function () {
|
||||
return this.poweroffall().then(() => {
|
||||
return util.exec(['pkill', 'VirtualBox']);
|
||||
}).then(() => {
|
||||
return util.exec(['pkill', 'VBox']);
|
||||
}).catch(() => {
|
||||
if(util.isWindows()) {
|
||||
return this.poweroffall().then(() => {
|
||||
return util.exec(['powershell.exe', '\"get-process VBox* | stop-process\"']);
|
||||
}).catch(() => {
|
||||
|
||||
});
|
||||
});
|
||||
} else {
|
||||
return this.poweroffall().then(() => {
|
||||
return util.exec(['pkill', 'VirtualBox']);
|
||||
}).then(() => {
|
||||
return util.exec(['pkill', 'VBox']);
|
||||
}).catch(() => {
|
||||
|
||||
});
|
||||
}
|
||||
},
|
||||
wake: function (name) {
|
||||
return util.exec([this.command(), 'startvm', name, '--type', 'headless']);
|
||||
|
|
|
@ -8,7 +8,14 @@ var path = require('path');
|
|||
process.env.NODE_PATH = path.join(__dirname, '/../node_modules');
|
||||
process.env.RESOURCES_PATH = path.join(__dirname, '/../resources');
|
||||
process.chdir(path.join(__dirname, '..'));
|
||||
process.env.PATH = '/usr/local/bin:' + process.env.PATH;
|
||||
|
||||
if(process.platform === 'win32') {
|
||||
process.env.PATH = process.env.PATH + ';' + process.env['USERPROFILE'] + '\\Kitematic-bins';
|
||||
} else {
|
||||
process.env.PATH = '/usr/local/bin:' + process.env.PATH;
|
||||
}
|
||||
|
||||
|
||||
|
||||
var size = {}, settingsjson = {};
|
||||
try {
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
$scriptpath = $MyInvocation.MyCommand.Path
|
||||
$dir = Split-Path $scriptpath
|
||||
$BasePath = $dir + '\..\'
|
||||
$packageJson = get-content ($BasePath + 'package.json')
|
||||
[System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions") > $null
|
||||
$serializer = New-Object System.Web.Script.Serialization.JavaScriptSerializer
|
||||
$packageJsonContent = $serializer.DeserializeObject($packageJson)
|
||||
$webclient = New-Object System.Net.WebClient
|
||||
|
||||
$DOCKER_MACHINE_CLI_VERSION = $packageJsonContent['docker-machine-version']
|
||||
$DOCKER_MACHINE_CLI_FILE = 'docker-machine-' + $DOCKER_MACHINE_CLI_VERSION + '.exe'
|
||||
$DOCKER_CLI_VERSION = $packageJsonContent['docker-version']
|
||||
$DOCKER_CLI_FILE = 'docker-' + $DOCKER_CLI_VERSION + '.exe'
|
||||
|
||||
|
||||
if(-Not (test-path ($BasePath + '\resources\' + $DOCKER_CLI_FILE))) {
|
||||
echo "-----> Downloading Docker CLI..."
|
||||
$source = "https://master.dockerproject.com/windows/amd64/docker.exe"
|
||||
$destination = $BasePath + "\resources\" + $DOCKER_CLI_FILE
|
||||
$webclient.DownloadFile($source, $destination)
|
||||
}
|
||||
|
||||
if(-Not (test-path ($BasePath + '\resources\' + $DOCKER_MACHINE_CLI_FILE))) {
|
||||
echo "-----> Downloading Docker Machine CLI..."
|
||||
$source = "https://github.com/docker/machine/releases/download/v0.1.0/docker-machine_windows-amd64.exe"
|
||||
$destination = $BasePath + "\resources\" + $DOCKER_MACHINE_CLI_FILE
|
||||
$webclient.DownloadFile($source, $destination)
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
get-process VBox* | stop-process
|
||||
|
||||
$paths = '~/Kitematic/', '~/.docker', '~/.VirtualBox/', '~/Kitematic-bins/', '~/Library/Application Support/Kitematic'
|
||||
|
||||
Foreach($path in $paths) {
|
||||
if(test-path $path) {
|
||||
Remove-Item $path -Force -Recurse
|
||||
}
|
||||
}
|
||||
|
||||
$virtualBoxApp = Get-WmiObject -Class Win32_Product | Where {$_.Name -Match 'VirtualBox'}
|
||||
|
||||
if($virtualBoxApp -ne $null) {
|
||||
$virtualBoxApp.Uninstall()
|
||||
}
|
Loading…
Reference in New Issue