170
Gruntfile.js
|
|
@ -1,15 +1,10 @@
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var fs = require('fs');
|
|
||||||
var execFile = require('child_process').execFile;
|
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_URL = 'https://get.docker.com/builds/Windows/x86_64/docker-' + packagejson['docker-version'] + '.exe';
|
|
||||||
var DARWIN_DOCKER_URL = 'https://get.docker.com/builds/Darwin/x86_64/docker-' + packagejson['docker-version'];
|
|
||||||
var WINDOWS_DOCKER_MACHINE_URL = 'https://github.com/docker/machine/releases/download/v' + packagejson['docker-machine-version'] + '/docker-machine_windows-amd64.exe';
|
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';
|
var DARWIN_DOCKER_MACHINE_URL = 'https://github.com/docker/machine/releases/download/v' + packagejson['docker-machine-version'] + '/docker-machine_darwin-amd64';
|
||||||
var DARWIN_COMPOSE_URL = 'https://github.com/docker/compose/releases/download/' + packagejson['docker-compose-version'] + '/docker-compose-Darwin-x86_64';
|
|
||||||
var BOOT2DOCKER_ISO_URL = 'https://github.com/boot2docker/boot2docker/releases/download/v' + packagejson['docker-version'] + '/boot2docker.iso';
|
|
||||||
|
|
||||||
module.exports = function (grunt) {
|
module.exports = function (grunt) {
|
||||||
require('load-grunt-tasks')(grunt);
|
require('load-grunt-tasks')(grunt);
|
||||||
|
|
@ -21,25 +16,12 @@ module.exports = function (grunt) {
|
||||||
env.NODE_ENV = target;
|
env.NODE_ENV = target;
|
||||||
|
|
||||||
var certificateFile = grunt.option('certificateFile');
|
var certificateFile = grunt.option('certificateFile');
|
||||||
var certificatePassword = grunt.option('certificatePassword');
|
|
||||||
|
|
||||||
var version = function (str) {
|
var version = function (str) {
|
||||||
var match = str.match(/(\d+\.\d+\.\d+)/);
|
var match = str.match(/(\d+\.\d+\.\d+)/);
|
||||||
return match ? match[1] : null;
|
return match ? match[1] : null;
|
||||||
};
|
};
|
||||||
|
|
||||||
grunt.registerTask('download-boot2docker-iso', 'Downloads provided boot2docker version', function () {
|
|
||||||
try {
|
|
||||||
var data = fs.readFileSync(path.join('resources', 'boot2docker.iso'), {encoding: 'utf-8'});
|
|
||||||
var match = data.match(/Boot2Docker-v(\d+\.\d+\.\d+)/);
|
|
||||||
if (match && match[1] !== packagejson['docker-version']) {
|
|
||||||
grunt.task.run('curl:boot2docker-iso');
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
grunt.task.run('curl:boot2docker-iso');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
grunt.registerMultiTask('download-binary', 'Downloads binary unless version up to date', function () {
|
grunt.registerMultiTask('download-binary', 'Downloads binary unless version up to date', function () {
|
||||||
var target = grunt.task.current.target;
|
var target = grunt.task.current.target;
|
||||||
var done = this.async();
|
var done = this.async();
|
||||||
|
|
@ -64,15 +46,19 @@ module.exports = function (grunt) {
|
||||||
APPNAME += ' (Beta)';
|
APPNAME += ' (Beta)';
|
||||||
}
|
}
|
||||||
|
|
||||||
var OSX_OUT = './dist/osx';
|
var OSX_OUT = './dist';
|
||||||
var OSX_FILENAME = OSX_OUT + '/' + APPNAME + '.app';
|
var OSX_OUT_X64 = OSX_OUT + '/' + APPNAME + '-darwin-x64';
|
||||||
|
var OSX_FILENAME = OSX_OUT_X64 + '/' + APPNAME + '.app';
|
||||||
|
|
||||||
grunt.initConfig({
|
grunt.initConfig({
|
||||||
IDENTITY: 'Developer ID Application: Docker Inc',
|
IDENTITY: 'Developer ID Application: Docker Inc',
|
||||||
APPNAME: APPNAME,
|
APPNAME: APPNAME,
|
||||||
|
APPNAME_ESCAPED: APPNAME.replace(/ /g, '\\ ').replace(/\(/g,'\\(').replace(/\)/g,'\\)'),
|
||||||
OSX_OUT: OSX_OUT,
|
OSX_OUT: OSX_OUT,
|
||||||
|
OSX_OUT_ESCAPED: OSX_OUT.replace(/ /g, '\\ ').replace(/\(/g,'\\(').replace(/\)/g,'\\)'),
|
||||||
|
OSX_OUT_X64: OSX_OUT_X64,
|
||||||
OSX_FILENAME: OSX_FILENAME,
|
OSX_FILENAME: OSX_FILENAME,
|
||||||
OSX_FILENAME_ESCAPED: OSX_FILENAME.replace(' ', '\\ ').replace('(','\\(').replace(')','\\)'),
|
OSX_FILENAME_ESCAPED: OSX_FILENAME.replace(/ /g, '\\ ').replace(/\(/g,'\\(').replace(/\)/g,'\\)'),
|
||||||
|
|
||||||
// electron
|
// electron
|
||||||
electron: {
|
electron: {
|
||||||
|
|
@ -80,7 +66,7 @@ module.exports = function (grunt) {
|
||||||
options: {
|
options: {
|
||||||
name: BASENAME,
|
name: BASENAME,
|
||||||
dir: 'build/',
|
dir: 'build/',
|
||||||
out: 'dist/',
|
out: 'dist',
|
||||||
version: packagejson['electron-version'],
|
version: packagejson['electron-version'],
|
||||||
platform: 'win32',
|
platform: 'win32',
|
||||||
arch: 'x64',
|
arch: 'x64',
|
||||||
|
|
@ -92,7 +78,7 @@ module.exports = function (grunt) {
|
||||||
options: {
|
options: {
|
||||||
name: APPNAME,
|
name: APPNAME,
|
||||||
dir: 'build/',
|
dir: 'build/',
|
||||||
out: '<%= OSX_OUT %>',
|
out: 'dist',
|
||||||
version: packagejson['electron-version'],
|
version: packagejson['electron-version'],
|
||||||
platform: 'darwin',
|
platform: 'darwin',
|
||||||
arch: 'x64',
|
arch: 'x64',
|
||||||
|
|
@ -103,11 +89,25 @@ module.exports = function (grunt) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
prompt: {
|
||||||
|
'create-windows-installer': {
|
||||||
|
options: {
|
||||||
|
questions: [
|
||||||
|
{
|
||||||
|
config: 'certificatePassword',
|
||||||
|
type: 'password',
|
||||||
|
message: 'Certificate Password: '
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
rcedit: {
|
rcedit: {
|
||||||
exes: {
|
exes: {
|
||||||
files: [{
|
files: [{
|
||||||
expand: true,
|
expand: true,
|
||||||
cwd: 'dist/' + BASENAME + '-win32',
|
cwd: 'dist/' + BASENAME + '-win32-x64',
|
||||||
src: [BASENAME + '.exe']
|
src: [BASENAME + '.exe']
|
||||||
}],
|
}],
|
||||||
options: {
|
options: {
|
||||||
|
|
@ -115,7 +115,7 @@ module.exports = function (grunt) {
|
||||||
'file-version': packagejson.version,
|
'file-version': packagejson.version,
|
||||||
'product-version': packagejson.version,
|
'product-version': packagejson.version,
|
||||||
'version-string': {
|
'version-string': {
|
||||||
'CompanyName': 'Docker Inc',
|
'CompanyName': 'Docker',
|
||||||
'ProductVersion': packagejson.version,
|
'ProductVersion': packagejson.version,
|
||||||
'ProductName': APPNAME,
|
'ProductName': APPNAME,
|
||||||
'FileDescription': APPNAME,
|
'FileDescription': APPNAME,
|
||||||
|
|
@ -128,34 +128,27 @@ module.exports = function (grunt) {
|
||||||
},
|
},
|
||||||
|
|
||||||
'create-windows-installer': {
|
'create-windows-installer': {
|
||||||
appDirectory: 'dist/' + BASENAME + '-win32/',
|
config: {
|
||||||
authors: 'Docker Inc.',
|
appDirectory: path.join(__dirname, 'dist/' + BASENAME + '-win32-x64'),
|
||||||
loadingGif: 'util/loading.gif',
|
outputDirectory: path.join(__dirname, 'dist'),
|
||||||
setupIcon: 'util/setup.ico',
|
authors: 'Docker Inc.',
|
||||||
iconUrl: 'https://raw.githubusercontent.com/kitematic/kitematic/master/util/kitematic.ico',
|
loadingGif: 'util/loading.gif',
|
||||||
description: APPNAME,
|
setupIcon: 'util/setup.ico',
|
||||||
title: APPNAME,
|
iconUrl: 'https://raw.githubusercontent.com/kitematic/kitematic/master/util/kitematic.ico',
|
||||||
exe: BASENAME + '.exe',
|
description: APPNAME,
|
||||||
version: packagejson.version,
|
title: APPNAME,
|
||||||
signWithParams: '/f ' + certificateFile + ' /p ' + certificatePassword + ' /tr http://timestamp.comodoca.com/rfc3161'
|
exe: BASENAME + '.exe',
|
||||||
|
version: packagejson.version,
|
||||||
|
signWithParams: '/f ' + certificateFile + ' /p <%= certificatePassword %> /tr http://timestamp.comodoca.com/rfc3161'
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// docker binaries
|
// docker binaries
|
||||||
'download-binary': {
|
'download-binary': {
|
||||||
docker: {
|
|
||||||
version: packagejson['docker-version'],
|
|
||||||
binary: path.join('resources', 'docker'),
|
|
||||||
download: 'curl:docker'
|
|
||||||
},
|
|
||||||
'docker-machine': {
|
'docker-machine': {
|
||||||
version: packagejson['docker-machine-version'],
|
version: packagejson['docker-machine-version'],
|
||||||
binary: path.join('resources', 'docker-machine'),
|
binary: path.join('resources', 'docker-machine'),
|
||||||
download: 'curl:docker-machine'
|
download: 'curl:docker-machine'
|
||||||
},
|
|
||||||
'docker-compose': {
|
|
||||||
version: packagejson['docker-compose-version'],
|
|
||||||
binary: path.join('resources', 'docker-compose'),
|
|
||||||
download: 'curl:docker-compose'
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -188,8 +181,8 @@ module.exports = function (grunt) {
|
||||||
files: [{
|
files: [{
|
||||||
expand: true,
|
expand: true,
|
||||||
cwd: 'resources',
|
cwd: 'resources',
|
||||||
src: ['docker*', 'boot2docker.iso', 'ssh.exe', 'OPENSSH_LICENSE', 'msys-*'],
|
src: ['docker*', 'ssh.exe', 'OPENSSH_LICENSE', 'msys-*'],
|
||||||
dest: 'dist/' + BASENAME + '-win32/resources/resources/'
|
dest: 'dist/' + BASENAME + '-win32-x64/resources/resources'
|
||||||
}],
|
}],
|
||||||
options: {
|
options: {
|
||||||
mode: true
|
mode: true
|
||||||
|
|
@ -199,7 +192,7 @@ module.exports = function (grunt) {
|
||||||
files: [{
|
files: [{
|
||||||
expand: true,
|
expand: true,
|
||||||
cwd: 'resources',
|
cwd: 'resources',
|
||||||
src: ['docker*', 'boot2docker.iso', 'macsudo', 'terminal'],
|
src: ['docker*', 'macsudo', 'terminal'],
|
||||||
dest: '<%= OSX_FILENAME %>/Contents/Resources/resources/'
|
dest: '<%= OSX_FILENAME %>/Contents/Resources/resources/'
|
||||||
}, {
|
}, {
|
||||||
src: 'util/kitematic.icns',
|
src: 'util/kitematic.icns',
|
||||||
|
|
@ -213,28 +206,16 @@ module.exports = function (grunt) {
|
||||||
|
|
||||||
rename: {
|
rename: {
|
||||||
installer: {
|
installer: {
|
||||||
src: 'installer/Setup.exe',
|
src: 'dist/Setup.exe',
|
||||||
dest: 'installer/' + BASENAME + 'Setup-' + packagejson.version + '-Windows-Alpha.exe'
|
dest: 'dist/' + BASENAME + 'Setup-' + packagejson.version + '-Windows-Alpha.exe'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
// download binaries
|
// download binaries
|
||||||
curl: {
|
curl: {
|
||||||
docker: {
|
|
||||||
src: process.platform === 'win32' ? WINDOWS_DOCKER_URL : DARWIN_DOCKER_URL,
|
|
||||||
dest: process.platform === 'win32' ? path.join('resources', 'docker.exe') : path.join('resources', 'docker')
|
|
||||||
},
|
|
||||||
'docker-machine': {
|
'docker-machine': {
|
||||||
src: process.platform === 'win32' ? WINDOWS_DOCKER_MACHINE_URL : DARWIN_DOCKER_MACHINE_URL,
|
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')
|
dest: process.platform === 'win32' ? path.join('resources', 'docker-machine.exe') : path.join('resources', 'docker-machine')
|
||||||
},
|
|
||||||
'docker-compose': {
|
|
||||||
src: DARWIN_COMPOSE_URL,
|
|
||||||
dest: 'resources/docker-compose'
|
|
||||||
},
|
|
||||||
'boot2docker-iso': {
|
|
||||||
src: BOOT2DOCKER_ISO_URL,
|
|
||||||
dest: path.join('resources', 'boot2docker.iso')
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -275,41 +256,6 @@ module.exports = function (grunt) {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
plistbuddy: {
|
|
||||||
addBundleURLTypes: {
|
|
||||||
method: 'Add',
|
|
||||||
entry: 'CFBundleURLTypes',
|
|
||||||
type: 'array',
|
|
||||||
src: '<%= OSX_FILENAME %>/Contents/Info.plist'
|
|
||||||
},
|
|
||||||
addBundleURLTypesDict: {
|
|
||||||
method: 'Add',
|
|
||||||
entry: 'CFBundleURLTypes:0',
|
|
||||||
type: 'dict',
|
|
||||||
src: '<%= OSX_FILENAME %>/Contents/Info.plist'
|
|
||||||
},
|
|
||||||
addBundleURLTypesDictName: {
|
|
||||||
method: 'Add',
|
|
||||||
entry: 'CFBundleURLTypes:0:CFBundleURLName',
|
|
||||||
type: 'string',
|
|
||||||
value: 'Docker App Protocol',
|
|
||||||
src: '<%= OSX_FILENAME %>/Contents/Info.plist'
|
|
||||||
},
|
|
||||||
addBundleURLTypesDictSchemes: {
|
|
||||||
method: 'Add',
|
|
||||||
entry: 'CFBundleURLTypes:0:CFBundleURLSchemes',
|
|
||||||
type: 'array',
|
|
||||||
src: '<%= OSX_FILENAME %>/Contents/Info.plist'
|
|
||||||
},
|
|
||||||
addBundleURLTypesDictSchemesDocker: {
|
|
||||||
method: 'Add',
|
|
||||||
entry: 'CFBundleURLTypes:0:CFBundleURLSchemes:0',
|
|
||||||
type: 'string',
|
|
||||||
value: 'docker',
|
|
||||||
src: '<%= OSX_FILENAME %>/Contents/Info.plist'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
shell: {
|
shell: {
|
||||||
electron: {
|
electron: {
|
||||||
command: electron + ' ' + 'build',
|
command: electron + ' ' + 'build',
|
||||||
|
|
@ -332,13 +278,27 @@ module.exports = function (grunt) {
|
||||||
].join(' && '),
|
].join(' && '),
|
||||||
},
|
},
|
||||||
zip: {
|
zip: {
|
||||||
command: 'ditto -c -k --sequesterRsrc --keepParent <%= OSX_FILENAME_ESCAPED %> <%= OSX_OUT %>/' + BASENAME + '-' + packagejson.version + '-Mac.zip',
|
command: 'ditto -c -k --sequesterRsrc --keepParent <%= OSX_FILENAME_ESCAPED %> dist/' + BASENAME + '-' + packagejson.version + '-Mac.zip',
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
clean: {
|
clean: {
|
||||||
release: ['build/', 'dist/', 'installer/'],
|
release: ['build/', 'dist/'],
|
||||||
isos: ['resources/boot2docker*']
|
},
|
||||||
|
|
||||||
|
compress: {
|
||||||
|
windows: {
|
||||||
|
options: {
|
||||||
|
archive: './dist/' + BASENAME + '-' + packagejson.version + '-Windows-Alpha.zip',
|
||||||
|
mode: 'zip'
|
||||||
|
},
|
||||||
|
files: [{
|
||||||
|
expand: true,
|
||||||
|
dot: true,
|
||||||
|
cwd: './dist/Kitematic-win32-x64',
|
||||||
|
src: '**/*'
|
||||||
|
}]
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// livereload
|
// livereload
|
||||||
|
|
@ -365,16 +325,12 @@ module.exports = function (grunt) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (process.platform === 'win32') {
|
grunt.registerTask('default', ['download-binary', 'newer:babel', 'less', 'newer:copy:dev', 'shell:electron', 'watchChokidar']);
|
||||||
grunt.registerTask('default', ['download-binary:docker', 'download-binary:docker-machine', 'download-boot2docker-iso', 'newer:babel', 'less', 'newer:copy:dev', 'shell:electron', 'watchChokidar']);
|
|
||||||
} else {
|
|
||||||
grunt.registerTask('default', ['download-binary', 'download-boot2docker-iso', 'newer:babel', 'less', 'newer:copy:dev', 'shell:electron', 'watchChokidar']);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (process.platform === 'win32') {
|
if (process.platform === 'win32') {
|
||||||
grunt.registerTask('release', ['clean:release', 'download-binary:docker', 'download-binary:docker-machine', 'download-boot2docker-iso', 'babel', 'less', 'copy:dev', 'electron:windows', 'copy:windows', 'rcedit:exes', 'create-windows-installer', 'rename:installer']);
|
grunt.registerTask('release', ['clean:release', 'download-binary', 'babel', 'less', 'copy:dev', 'electron:windows', 'copy:windows', 'rcedit:exes', 'compress', 'prompt:create-windows-installer', 'create-windows-installer', 'rename:installer']);
|
||||||
} else {
|
} else {
|
||||||
grunt.registerTask('release', ['clean:release', 'download-binary', 'download-boot2docker-iso', 'babel', 'less', 'copy:dev', 'electron:osx', 'copy:osx', 'plistbuddy', 'shell:sign', 'shell:zip']);
|
grunt.registerTask('release', ['clean:release', 'download-binary', 'babel', 'less', 'copy:dev', 'electron:osx', 'copy:osx', 'shell:sign', 'shell:zip']);
|
||||||
}
|
}
|
||||||
|
|
||||||
process.on('SIGINT', function () {
|
process.on('SIGINT', function () {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
Jeff Morgan <jmorgan@docker.com> (@jeffdm)
|
||||||
|
Sean Li <mail@shang.li> (@elesant)
|
||||||
|
Michael Chiang <mchiang@docker.com> (@mchiang0610)
|
||||||
|
Ben French <me@frenchben.com> (@FrenchBen)
|
||||||
|
|
@ -11,12 +11,6 @@ Kitematic is a simple application for managing Docker containers on Mac and Wind
|
||||||
|
|
||||||
[Download the latest version](https://kitematic.com/download) of Kitematic.
|
[Download the latest version](https://kitematic.com/download) of Kitematic.
|
||||||
|
|
||||||
On the Mac, Kitematic can copy the binaries for Docker, Docker Machine and Docker Compose into `/usr/local/bin` for command line use outside of Kitematic.
|
|
||||||
|
|
||||||
To do so please click on the Kitematic dropdown menu and select `Install Docker Commands`
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
Kitematic's documentation and other information can be found at [http://kitematic.com/docs](http://kitematic.com/docs).
|
Kitematic's documentation and other information can be found at [http://kitematic.com/docs](http://kitematic.com/docs).
|
||||||
|
|
@ -38,7 +32,7 @@ Please read through our [Contributing Guidelines](https://github.com/kitematic/k
|
||||||
## Community
|
## Community
|
||||||
|
|
||||||
- [](https://gitter.im/kitematic/kitematic?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
- [](https://gitter.im/kitematic/kitematic?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||||
- Ask questions on our [user forum](https://forums.docker.com/c/kitematic).
|
- Ask questions on our [user forum](https://forums.docker.com/c/open-source-projects/kitematic).
|
||||||
- **#kitematic** on IRC. [Join the channel](http://webchat.freenode.net/?channels=%23kitematic&uio=d4).
|
- **#kitematic** on IRC. [Join the channel](http://webchat.freenode.net/?channels=%23kitematic&uio=d4).
|
||||||
- Follow [@kitematic on Twitter](https://twitter.com/kitematic).
|
- Follow [@kitematic on Twitter](https://twitter.com/kitematic).
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -28,4 +28,9 @@
|
||||||
|
|
||||||
**June 2015**
|
**June 2015**
|
||||||
|
|
||||||
* Microsoft Windows port
|
* Microsoft Windows alpha
|
||||||
|
|
||||||
|
**July 2015**
|
||||||
|
|
||||||
|
* Refactor to Flux Architecture
|
||||||
|
* Stability & code quality improvements
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ describe('SetupStore', function () {
|
||||||
|
|
||||||
pit('downloads virtualbox if it is installed but has an outdated version', function () {
|
pit('downloads virtualbox if it is installed but has an outdated version', function () {
|
||||||
virtualBox.installed.mockReturnValue(true);
|
virtualBox.installed.mockReturnValue(true);
|
||||||
virtualBox.version.mockReturnValue(Promise.resolve('4.3.16'));
|
virtualBox.version.mockReturnValue(Promise.resolve('5.0.0'));
|
||||||
util.compareVersions.mockReturnValue(-1);
|
util.compareVersions.mockReturnValue(-1);
|
||||||
setupUtil.download.mockReturnValue(Promise.resolve());
|
setupUtil.download.mockReturnValue(Promise.resolve());
|
||||||
virtualBox.filename.mockReturnValue('');
|
virtualBox.filename.mockReturnValue('');
|
||||||
|
|
@ -55,6 +55,7 @@ describe('SetupStore', function () {
|
||||||
machine.stop.mockReturnValue(Promise.resolve());
|
machine.stop.mockReturnValue(Promise.resolve());
|
||||||
machine.start.mockReturnValue(Promise.resolve());
|
machine.start.mockReturnValue(Promise.resolve());
|
||||||
machine.upgrade.mockReturnValue(Promise.resolve());
|
machine.upgrade.mockReturnValue(Promise.resolve());
|
||||||
|
util.packagejson.mockReturnValue({'docker-version':'1.8.0'});
|
||||||
util.compareVersions.mockReturnValue(-1);
|
util.compareVersions.mockReturnValue(-1);
|
||||||
machine.create.mockClear();
|
machine.create.mockClear();
|
||||||
machine.upgrade.mockClear();
|
machine.upgrade.mockClear();
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,12 @@ describe('Util', function () {
|
||||||
expect(util.removeSensitiveData(testdata).indexOf('/Users/<redacted>/.docker')).toNotEqual(-1);
|
expect(util.removeSensitiveData(testdata).indexOf('/Users/<redacted>/.docker')).toNotEqual(-1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('filters Windows username data', function () {
|
||||||
|
var testdata = String.raw`C:\\Users\\johnappleseed\\.docker\\machine`;
|
||||||
|
expect(util.removeSensitiveData(testdata).indexOf('johnappleseed')).toEqual(-1);
|
||||||
|
expect(util.removeSensitiveData(testdata).indexOf('<redacted>')).toNotEqual(-1);
|
||||||
|
});
|
||||||
|
|
||||||
it ('returns input if empty or not a string', function () {
|
it ('returns input if empty or not a string', function () {
|
||||||
expect(util.removeSensitiveData('')).toBe('');
|
expect(util.removeSensitiveData('')).toBe('');
|
||||||
expect(util.removeSensitiveData(1)).toBe(1);
|
expect(util.removeSensitiveData(1)).toBe(1);
|
||||||
|
|
|
||||||
|
|
@ -3,17 +3,13 @@ var virtualBox = require('../src/utils/VirtualBoxUtil');
|
||||||
var util = require('../src/utils/Util');
|
var util = require('../src/utils/Util');
|
||||||
|
|
||||||
describe('VirtualBox', function () {
|
describe('VirtualBox', function () {
|
||||||
it('returns the right command', function () {
|
describe('version 5.0.0r101573', function () {
|
||||||
expect(virtualBox.command()).toBe('/usr/bin/VBoxManage');
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('version 4.3.20r96996', function () {
|
|
||||||
pit('correctly parses virtualbox version', function () {
|
pit('correctly parses virtualbox version', function () {
|
||||||
util.exec.mockImplementation(function () {
|
util.exec.mockImplementation(function () {
|
||||||
return Promise.resolve('4.3.20r96996');
|
return Promise.resolve('5.0.0r101573');
|
||||||
});
|
});
|
||||||
return virtualBox.version().then(function (version) {
|
return virtualBox.version().then(function (version) {
|
||||||
expect(version).toBe('4.3.20');
|
expect(version).toBe('5.0.0');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,27 @@
|
||||||
FROM docs/base:hugo
|
FROM docs/base:latest
|
||||||
MAINTAINER Mary Anthony <mary@docker.com> (@moxiegirl)
|
MAINTAINER Mary Anthony <mary@docker.com> (@moxiegirl)
|
||||||
|
|
||||||
# to get the git info for this repo
|
# To get the git info for this repo
|
||||||
COPY . /src
|
COPY . /src
|
||||||
|
|
||||||
COPY . /docs/content/kitematic/
|
COPY . /docs/content/kitematic/
|
||||||
|
|
||||||
|
RUN svn checkout https://github.com/docker/compose/trunk/docs /docs/content/compose
|
||||||
|
RUN svn checkout https://github.com/docker/docker/trunk/docs /docs/content/docker
|
||||||
|
RUN svn checkout https://github.com/docker/swarm/trunk/docs /docs/content/swarm
|
||||||
|
RUN svn checkout https://github.com/docker/distribution/trunk/docs /docs/content/registry
|
||||||
|
RUN svn checkout https://github.com/docker/tutorials/trunk/docs /docs/content
|
||||||
|
RUN svn checkout https://github.com/docker/opensource/trunk/docs /docs/content/opensource
|
||||||
|
RUN svn checkout https://github.com/docker/machine/trunk/docs /docs/content/machine
|
||||||
|
|
||||||
|
|
||||||
# Sed to process GitHub Markdown
|
# Sed to process GitHub Markdown
|
||||||
# 1-2 Remove comment code from metadata block
|
# 1-2 Remove comment code from metadata block
|
||||||
# 3 Change ](/word to ](/project/ in links
|
# 3 Change ](/word to ](/project/ in links
|
||||||
# 4 Change ](word.md) to ](/project/word)
|
# 4 Change ](word.md) to ](/project/word)
|
||||||
# 5 Remove .md extension from link text
|
# 5 Remove .md extension from link text
|
||||||
# 6 Change ](./ to ](/project/word)
|
# 6 Change ](../ to ](/project/word)
|
||||||
# 7 Change ](../../ to ](/project/
|
# 7 Change ](../../ to ](/project/ --> not implemented
|
||||||
# 8 Change ](../ to ](/project/
|
|
||||||
# 9 Change ](# to ](/project/
|
|
||||||
#
|
#
|
||||||
RUN find /docs/content/kitematic -type f -name "*.md" -exec sed -i.old \
|
#
|
||||||
-e '/^<!.*metadata]>/g' \
|
RUN /src/pre-process.sh /docs
|
||||||
-e '/^<!.*end-metadata.*>/g' \
|
|
||||||
-e 's/\(\]\)\([(]\)\(\/\)/\1\2\/kitematic\//g' \
|
|
||||||
-e 's/\(\][(]\)\([A-z].*\)\(\.md\)/\1\/kitematic\/\2/g' \
|
|
||||||
-e 's/\([(]\)\(.*\)\(\.md\)/\1\2/g' \
|
|
||||||
-e 's/\(\][(]\)\(\.\/\)/\1\/kitematic\//g' \
|
|
||||||
-e 's/\(\][(]\)\(\.\.\/\.\.\/\)/\1\/kitematic\//g' \
|
|
||||||
-e 's/\(\][(]\)\(\.\.\/\)/\1\/kitematic\//g' {} \;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
10
docs/faq.md
|
|
@ -21,8 +21,7 @@ software released under the Apache 2.0 license.
|
||||||
### How can I contribute to Kitematic?
|
### How can I contribute to Kitematic?
|
||||||
|
|
||||||
We always welcome (and deeply appreciate!) new contributions to the project. The
|
We always welcome (and deeply appreciate!) new contributions to the project. The
|
||||||
best way to start contributing to Kitematic is to review our doc on
|
best way to start contributing to Kitematic is to review our doc on <a href="https://github.com/kitematic/kitematic/blob/master/CONTRIBUTING.md">contributing</a>.
|
||||||
[contributing](https://github.com/kitematic/kitematic/blob/master/CONTRIBUTING.md).
|
|
||||||
|
|
||||||
### How does Kitematic work with Docker?
|
### How does Kitematic work with Docker?
|
||||||
|
|
||||||
|
|
@ -31,10 +30,9 @@ the Docker Remote API.
|
||||||
|
|
||||||
### Which platforms does Kitematic support?
|
### Which platforms does Kitematic support?
|
||||||
|
|
||||||
Right now Kitematic only works on Mac OS X. That said, Windows is on the
|
Right now Kitematic works on Mac OS X and Windows. Linux is planned in the
|
||||||
short-term
|
future. Review our product <a
|
||||||
[roadmap](https://github.com/kitematic/kitematic/blob/master/ROADMAP.md) (coming
|
href="https://github.com/kitematic/kitematic/blob/master/ROADMAP.md">roadmap</a>.
|
||||||
soon!) and a Linux version is in high demand.
|
|
||||||
|
|
||||||
### Why does Kitematic collect usage analytics and bug reports?
|
### Why does Kitematic collect usage analytics and bug reports?
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,45 +9,8 @@ weight=2
|
||||||
+++
|
+++
|
||||||
<![end-metadata]-->
|
<![end-metadata]-->
|
||||||
|
|
||||||
# Kitematic: Install Kitematic
|
# Kitematic
|
||||||
|
|
||||||
You install Kitematic much the same way you install any application on a Mac or
|
Kitematic, the Docker GUI, runs on Mac OS X and Windows operating systems. Beginning with the 1.8 Docker release, you use the Docker Toolbox to install Kitematic. See the [Mac OS X installation guide](https://docs.docker.com/mac) or the [Windows installation guide](https://docs.docker.com/installation/windows) for details on installing with Docker Toolbox.
|
||||||
Windows PC: download an image and run an installer.
|
|
||||||
|
|
||||||
## Download Kitematic
|
For information about using Kitematic, take a look at the [User Guide](userguide).
|
||||||
|
|
||||||
[Download the Kitematic zip file](https://kitematic.com/download/), unzip the
|
|
||||||
file by double-clicking it, and then double-click the application to run it.
|
|
||||||
You'll probably also want to put the application in your Applications folder.
|
|
||||||
|
|
||||||
## Initial Setup
|
|
||||||
|
|
||||||
Opening Kitematic for the first time sets up everything you need to run Docker
|
|
||||||
containers. If you don't already have VirtualBox installed, Kitematic will
|
|
||||||
download and install the latest version.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
All Done! Within a minute you should be ready to start running your first
|
|
||||||
container!
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Technical Details
|
|
||||||
|
|
||||||
Kitematic is a self-contained .app, with an exception:
|
|
||||||
|
|
||||||
- It will install VirtualBox if it's not already installed.
|
|
||||||
|
|
||||||
### Why does Kitematic need my root password?
|
|
||||||
|
|
||||||
Kitematic needs your root password for two reasons:
|
|
||||||
|
|
||||||
- Installing VirtualBox requires root access as it includes Mac OS X kernel extensions.
|
|
||||||
- Copying `docker` and `docker-machine` to `/usr/local/bin` may require root
|
|
||||||
permission if the default permissions for this directory have been changed
|
|
||||||
prior to installing Kitematic.
|
|
||||||
|
|
||||||
## Next Steps
|
|
||||||
|
|
||||||
For information about using Kitematic, take a look at the [User Guide](/userguide).
|
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ commands on the command line:
|
||||||
- `docker-machine create -d virtualbox dev`
|
- `docker-machine create -d virtualbox dev`
|
||||||
|
|
||||||
Then re-open Kitematic. This usually fixes the issue, but if it persists, feel
|
Then re-open Kitematic. This usually fixes the issue, but if it persists, feel
|
||||||
free to view our [existing GitHub
|
free to view our <a href="https://github.com/kitematic/kitematic/issues?q=is%3Aopen+is%3Aissue+label%3Abug">existing GitHub
|
||||||
issues](https://github.com/kitematic/kitematic/issues?q=is%3Aopen+is%3Aissue+label%3Abug).
|
issues</a>.
|
||||||
|
|
||||||
## Contributing Fixes
|
## Contributing Fixes
|
||||||
|
|
||||||
|
|
@ -46,6 +46,5 @@ if you're looking to help fix specific issues around VM provisioning.
|
||||||
|
|
||||||
## View All Issues
|
## View All Issues
|
||||||
|
|
||||||
For a full list of Kitematic bugs or issues see our [GitHub
|
For a full list of Kitematic bugs or issues see our <a href="https://github.com/kitematic/kitematic/issues?q=is%3Aopen+is%3Aissue+label%3Abug">existing GitHub
|
||||||
issues](https://github.com/kitematic/kitematic/issues?q=is%3Aopen+is%3Aissue+label%3Abug)
|
issues</a> labelled as `bug`.
|
||||||
labelled as `bug`.
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
#!/bin/bash -e
|
||||||
|
|
||||||
|
# Populate an array with just docker dirs and one with content dirs
|
||||||
|
docker_dir=(`ls -d /docs/content/docker/*`)
|
||||||
|
content_dir=(`ls -d /docs/content/*`)
|
||||||
|
|
||||||
|
# Loop content not of docker/
|
||||||
|
#
|
||||||
|
# Sed to process GitHub Markdown
|
||||||
|
# 1-2 Remove comment code from metadata block
|
||||||
|
# 3 Remove .md extension from link text
|
||||||
|
# 4 Change ](/ to ](/project/ in links
|
||||||
|
# 5 Change ](word) to ](/project/word)
|
||||||
|
# 6 Change ](../../ to ](/project/
|
||||||
|
# 7 Change ](../ to ](/project/word)
|
||||||
|
#
|
||||||
|
for i in "${content_dir[@]}"
|
||||||
|
do
|
||||||
|
:
|
||||||
|
case $i in
|
||||||
|
"/docs/content/windows")
|
||||||
|
;;
|
||||||
|
"/docs/content/mac")
|
||||||
|
;;
|
||||||
|
"/docs/content/linux")
|
||||||
|
;;
|
||||||
|
"/docs/content/docker")
|
||||||
|
y=${i##*/}
|
||||||
|
find $i -type f -name "*.md" -exec sed -i.old \
|
||||||
|
-e '/^<!.*metadata]>/g' \
|
||||||
|
-e '/^<!.*end-metadata.*>/g' {} \;
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
y=${i##*/}
|
||||||
|
find $i -type f -name "*.md" -exec sed -i.old \
|
||||||
|
-e '/^<!.*metadata]>/g' \
|
||||||
|
-e '/^<!.*end-metadata.*>/g' \
|
||||||
|
-e 's/\(\]\)\([(]\)\(\/\)/\1\2\/'$y'\//g' \
|
||||||
|
-e 's/\(\][(]\)\([A-z].*\)\(\.md\)/\1\/'$y'\/\2/g' \
|
||||||
|
-e 's/\([(]\)\(.*\)\(\.md\)/\1\2/g' \
|
||||||
|
-e 's/\(\][(]\)\(\.\/\)/\1\/'$y'\//g' \
|
||||||
|
-e 's/\(\][(]\)\(\.\.\/\.\.\/\)/\1\/'$y'\//g' \
|
||||||
|
-e 's/\(\][(]\)\(\.\.\/\)/\1\/'$y'\//g' {} \;
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
#
|
||||||
|
# Move docker directories to content
|
||||||
|
#
|
||||||
|
for i in "${docker_dir[@]}"
|
||||||
|
do
|
||||||
|
:
|
||||||
|
if [ -d $i ]
|
||||||
|
then
|
||||||
|
mv $i /docs/content/
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
rm -rf /docs/content/docker
|
||||||
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
+++
|
+++
|
||||||
title = "Kitematic User Guide: Intro & Overview"
|
title = "Kitematic User Guide: Intro & Overview"
|
||||||
description = "Documentation that provides an overview of Kitematic and installation instructions"
|
description = "Documentation that provides an overview of Kitematic and installation instructions"
|
||||||
keywords = ["docker, documentation, about, technology, kitematic, gui"]
|
keywords = ["docker, documentation, about, technology, kitematic, gui"]
|
||||||
[menu.main]
|
[menu.main]
|
||||||
parent="smn_workw_kitematic"
|
parent="smn_workw_kitematic"
|
||||||
+++
|
+++
|
||||||
|
|
@ -16,12 +16,12 @@ Kitematic is an open source project built to simplify and streamline using
|
||||||
Docker on a Mac or Windows (coming soon) PC. Kitematic automates the Docker
|
Docker on a Mac or Windows (coming soon) PC. Kitematic automates the Docker
|
||||||
installation and setup process and provides an intuitive graphical user
|
installation and setup process and provides an intuitive graphical user
|
||||||
interface (GUI) for running Docker containers. Kitematic integrates with
|
interface (GUI) for running Docker containers. Kitematic integrates with
|
||||||
[Docker Machine](http://docs.docker.com/machine/) to provision a VirtualBox VM
|
[Docker Machine](https://docs.docker.com/machine/) to provision a VirtualBox VM
|
||||||
and install the Docker Engine locally on your machine.
|
and install the Docker Engine locally on your machine.
|
||||||
|
|
||||||
Once installed, the Kitematic GUI launches and from the home screen you will be
|
Once installed, the Kitematic GUI launches and from the home screen you will be
|
||||||
presented with curated images that you can run instantly. You can search for any
|
presented with curated images that you can run instantly. You can search for any
|
||||||
public images on Docker Hub from Kitematic just by typing in the search bar.
|
public images on Docker Hub from Kitematic just by typing in the search bar.
|
||||||
You can use the GUI to create, run and manage your containers just by clicking
|
You can use the GUI to create, run and manage your containers just by clicking
|
||||||
on buttons. Kitematic allows you to switch back and forth between the Docker CLI
|
on buttons. Kitematic allows you to switch back and forth between the Docker CLI
|
||||||
and the GUI. Kitematic also automates advanced features such as managing ports
|
and the GUI. Kitematic also automates advanced features such as managing ports
|
||||||
|
|
@ -78,17 +78,17 @@ The currently detected "web" ports are, `80`, `8000`, `8080`, `3000`, `5000`,
|
||||||
|
|
||||||
### Viewing container logs
|
### Viewing container logs
|
||||||
|
|
||||||
You can view the entire main container process' log output either by cicking on the "Logs"
|
You can view the entire main container process' log output either by clicking on the "Logs"
|
||||||
preview image, or by clicking on the "Logs" tab.
|
preview image, or by clicking on the "Logs" tab.
|
||||||
|
|
||||||
You can then scroll through the logs from the current running container. Note that
|
You can then scroll through the logs from the current running container. Note that
|
||||||
if you make changes to the container Settings, then the container will be restarted,
|
if you make changes to the container settings, then the container will be restarted,
|
||||||
so will reset this log view.
|
so this will reset this log view.
|
||||||
|
|
||||||
### Starting a terminal in a container
|
### Starting a terminal in a container
|
||||||
|
|
||||||
The "Terminal" icon at the top of the container summary will `docker exec sh <your container>`.
|
The "Terminal" icon at the top of the container summary will `docker exec sh <your container>`.
|
||||||
This will allow you to make quick changes, or to debug a problem.
|
This will allow you to make quick changes, or to debug a problem.
|
||||||
|
|
||||||
> **Note**: Your exec'ed `sh` process will not have the same environment settings
|
> **Note**: Your exec'ed `sh` process will not have the same environment settings
|
||||||
> as the main container process and its children.
|
> as the main container process and its children.
|
||||||
|
|
@ -100,7 +100,7 @@ on your Mac by clicking on the folders in the "Edit Files" section of the
|
||||||
container summary screen.
|
container summary screen.
|
||||||
|
|
||||||
This allows you to manage files in volumes via the Finder.
|
This allows you to manage files in volumes via the Finder.
|
||||||
Kitematic exposes a container's volume data under `~/Kitematic/<container's name>/`.
|
Kitematic exposes a container's volume data under `~/Documents/Kitematic/<container's name>/`.
|
||||||
Quick access to this folder (or directory) is available via the app:
|
Quick access to this folder (or directory) is available via the app:
|
||||||
|
|
||||||

|

|
||||||
|
|
@ -117,7 +117,7 @@ use the default directory created for the website_files volume. Instead, you
|
||||||
already have the HTML, Javascript, and CSS for your website under
|
already have the HTML, Javascript, and CSS for your website under
|
||||||
`~/workspace/website`.
|
`~/workspace/website`.
|
||||||
|
|
||||||
Navigate to the "Settings" tab of the container, and goto the "Volumes". This
|
Navigate to the "Settings" tab of the container, and go to the "Volumes". This
|
||||||
screen allows you to set the mappings individually.
|
screen allows you to set the mappings individually.
|
||||||
|
|
||||||

|

|
||||||
|
|
@ -142,12 +142,12 @@ Many images use environment variables to let you customise them. The "General"
|
||||||
"Settings" tab allows you to add and modify the environment variables used to
|
"Settings" tab allows you to add and modify the environment variables used to
|
||||||
start a container.
|
start a container.
|
||||||
|
|
||||||
The list of Environment variables will show any that have been set on the image
|
The list of environment variables will show any that have been set on the image
|
||||||
metadata - for example, using the `ENV` instruction in the Dockerfile.
|
metadata - for example, using the `ENV` instruction in the Dockerfile.
|
||||||
|
|
||||||
<TODO: image of the jenkins container>
|
<TODO: image of the jenkins container>
|
||||||
|
|
||||||
Wen you "Save" the changed environment variables, the container will be stopped
|
When you "Save" the changed environment variables, the container will be stopped,
|
||||||
removed and re-created.
|
removed and re-created.
|
||||||
|
|
||||||
### Delete container
|
### Delete container
|
||||||
|
|
@ -155,14 +155,14 @@ removed and re-created.
|
||||||
On the "General" "Settings" tab, you can delete the container. Clicking "Delete
|
On the "General" "Settings" tab, you can delete the container. Clicking "Delete
|
||||||
Container" will also stop the container if necessary.
|
Container" will also stop the container if necessary.
|
||||||
|
|
||||||
You can also delete a container clicking the `X` icon in the container list.
|
You can also delete a container by clicking the `X` icon in the container list.
|
||||||
|
|
||||||
Kitematic will prompt you to confirm that you want to delete.
|
Kitematic will prompt you to confirm that you want to delete.
|
||||||
|
|
||||||
#### List the exposed Ports and how to access them
|
#### List the exposed Ports and how to access them
|
||||||
|
|
||||||
To see the complete list of exposed ports, go to "Settings" then "Ports". This
|
To see the complete list of exposed ports, go to "Settings" then "Ports". This
|
||||||
page lists all the container ports exposed, and the IP address and host only
|
page lists all the container ports exposed, and the IP address and host-only
|
||||||
network port that you can access use to access that container from your OS X
|
network port that you can access use to access that container from your OS X
|
||||||
system.
|
system.
|
||||||
|
|
||||||
|
|
@ -172,7 +172,7 @@ You can interact with existing containers in Kitematic or create new containers
|
||||||
via the Docker Command Line Interface (CLI). Any changes you make on the CLI are
|
via the Docker Command Line Interface (CLI). Any changes you make on the CLI are
|
||||||
directly reflected in Kitematic.
|
directly reflected in Kitematic.
|
||||||
|
|
||||||
To open a terminal via Kitematic, just press whale button at the bottom left, as
|
To open a terminal via Kitematic, just press the whale button at the bottom left, as
|
||||||
shown below:
|
shown below:
|
||||||
|
|
||||||

|

|
||||||
|
|
@ -185,9 +185,9 @@ will pull and run a new Redis container via the Docker CLI.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
> **Note**: If you're creating containers from the commandline, use `docker run -d`
|
> **Note**: If you're creating containers from the command line, use `docker run -d`
|
||||||
> so that Kitematic can re-create the container when settings are changed via the
|
> so that Kitematic can re-create the container when settings are changed via the
|
||||||
> Kitematic user interface. containers started without `-d` will fail to re-start.
|
> Kitematic user interface. Containers started without `-d` will fail to re-start.
|
||||||
|
|
||||||
Now, go back to Kitematic. The Redis container should now be visible.
|
Now, go back to Kitematic. The Redis container should now be visible.
|
||||||
|
|
||||||
|
|
@ -196,4 +196,4 @@ Now, go back to Kitematic. The Redis container should now be visible.
|
||||||
## Next Steps
|
## Next Steps
|
||||||
|
|
||||||
For an example using Kitematic to run a Minecraft server, take a look at
|
For an example using Kitematic to run a Minecraft server, take a look at
|
||||||
the [Mincraft server](./minecraft-server.md) page.
|
the [Minecraft server](./minecraft-server.md) page.
|
||||||
|
|
|
||||||
|
After Width: | Height: | Size: 25 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 93 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 44 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 46 KiB |
23
package.json
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "Kitematic",
|
"name": "Kitematic",
|
||||||
"version": "0.7.3",
|
"version": "0.8.3",
|
||||||
"author": "Kitematic",
|
"author": "Kitematic",
|
||||||
"description": "Simple Docker Container management for Mac OS X.",
|
"description": "Simple Docker Container management for Mac OS X.",
|
||||||
"homepage": "https://kitematic.com/",
|
"homepage": "https://kitematic.com/",
|
||||||
|
|
@ -22,15 +22,14 @@
|
||||||
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"docker-version": "1.7.0",
|
"docker-version": "1.8.1",
|
||||||
"docker-machine-version": "0.3.0-rc2",
|
"docker-machine-version": "0.4.1",
|
||||||
"docker-compose-version": "1.3.0",
|
|
||||||
"electron-version": "0.27.2",
|
"electron-version": "0.27.2",
|
||||||
"virtualbox-version": "4.3.28",
|
"virtualbox-version": "5.0.2",
|
||||||
"virtualbox-filename": "VirtualBox-4.3.28.pkg",
|
"virtualbox-filename": "VirtualBox-5.0.2.pkg",
|
||||||
"virtualbox-filename-win": "VirtualBox-4.3.28.exe",
|
"virtualbox-filename-win": "VirtualBox-5.0.2.exe",
|
||||||
"virtualbox-checksum": "60521caff652fc32ad733eee2eea27f03d0b4f7239af3bf4b21dc6f0251cf47a",
|
"virtualbox-checksum": "384414edab277c376a2ac3d02e5f316434fa4d54d31db44dc85b6e560eda4143",
|
||||||
"virtualbox-checksum-win": "82039b615bf18dfff92ac1d9a15b2cbd5c59c608631ccf77e2371d0fd67a6cf7",
|
"virtualbox-checksum-win": "a8183d21566fc6cb327e4b71303fa0d04fc6cd079ba83d66818d18c5ef427037",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"alt": "^0.16.2",
|
"alt": "^0.16.2",
|
||||||
"ansi-to-html": "0.3.0",
|
"ansi-to-html": "0.3.0",
|
||||||
|
|
@ -71,16 +70,18 @@
|
||||||
"grunt-chmod": "^1.0.3",
|
"grunt-chmod": "^1.0.3",
|
||||||
"grunt-cli": "^0.1.13",
|
"grunt-cli": "^0.1.13",
|
||||||
"grunt-contrib-clean": "^0.6.0",
|
"grunt-contrib-clean": "^0.6.0",
|
||||||
|
"grunt-contrib-compress": "^0.13.0",
|
||||||
"grunt-contrib-copy": "^0.8.0",
|
"grunt-contrib-copy": "^0.8.0",
|
||||||
"grunt-contrib-less": "^1.0.1",
|
"grunt-contrib-less": "^1.0.1",
|
||||||
"grunt-contrib-watch-chokidar": "^1.0.0",
|
"grunt-contrib-watch-chokidar": "^1.0.0",
|
||||||
"grunt-curl": "^2.2.0",
|
"grunt-curl": "^2.2.0",
|
||||||
"grunt-download-electron": "^2.1.1",
|
"grunt-download-electron": "^2.1.1",
|
||||||
"grunt-electron": "^1.0.0",
|
"grunt-electron": "^2.0.0",
|
||||||
"grunt-electron-installer": "^0.33.0",
|
"grunt-electron-installer": "^0.37.0",
|
||||||
"grunt-if-missing": "^1.0.0",
|
"grunt-if-missing": "^1.0.0",
|
||||||
"grunt-newer": "^1.1.1",
|
"grunt-newer": "^1.1.1",
|
||||||
"grunt-plistbuddy": "^0.1.1",
|
"grunt-plistbuddy": "^0.1.1",
|
||||||
|
"grunt-prompt": "^1.3.0",
|
||||||
"grunt-rcedit": "^0.3.1",
|
"grunt-rcedit": "^0.3.1",
|
||||||
"grunt-rename": "^0.1.4",
|
"grunt-rename": "^0.1.4",
|
||||||
"grunt-shell": "^1.1.2",
|
"grunt-shell": "^1.1.2",
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
PATH=$DIR:$PATH
|
CMD="clear && $*"
|
||||||
CMD="export PATH='$PATH' && clear && $*"
|
|
||||||
|
|
||||||
ITERM_EXISTS=`osascript <<EOF
|
ITERM_EXISTS=`osascript <<EOF
|
||||||
set doesExist to false
|
set doesExist to false
|
||||||
|
|
|
||||||
33
src/app.js
|
|
@ -1,24 +1,23 @@
|
||||||
require.main.paths.splice(0, 0, process.env.NODE_PATH);
|
require.main.paths.splice(0, 0, process.env.NODE_PATH);
|
||||||
var remote = require('remote');
|
import remote from 'remote';
|
||||||
var Menu = remote.require('menu');
|
var Menu = remote.require('menu');
|
||||||
var React = require('react');
|
import React from 'react';
|
||||||
var SetupStore = require('./stores/SetupStore');
|
import SetupStore from './stores/SetupStore';
|
||||||
var ipc = require('ipc');
|
import ipc from 'ipc';
|
||||||
var machine = require('./utils/DockerMachineUtil');
|
import machine from './utils/DockerMachineUtil';
|
||||||
var metrics = require('./utils/MetricsUtil');
|
import metrics from './utils/MetricsUtil';
|
||||||
var router = require('./router');
|
import template from './menutemplate';
|
||||||
var template = require('./menutemplate');
|
import webUtil from './utils/WebUtil';
|
||||||
var webUtil = require('./utils/WebUtil');
|
import hubUtil from './utils/HubUtil';
|
||||||
var hubUtil = require('./utils/HubUtil');
|
|
||||||
var urlUtil = require ('./utils/URLUtil');
|
var urlUtil = require ('./utils/URLUtil');
|
||||||
var app = remote.require('app');
|
var app = remote.require('app');
|
||||||
var request = require('request');
|
import request from 'request';
|
||||||
var docker = require('./utils/DockerUtil');
|
import docker from './utils/DockerUtil';
|
||||||
var hub = require('./utils/HubUtil');
|
import hub from './utils/HubUtil';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
var routes = require('./routes');
|
import routes from './routes';
|
||||||
var routerContainer = require('./router');
|
import routerContainer from './router';
|
||||||
var repositoryActions = require('./actions/RepositoryActions');
|
import repositoryActions from './actions/RepositoryActions';
|
||||||
|
|
||||||
hubUtil.init();
|
hubUtil.init();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
var app = require('app');
|
import app from 'app';
|
||||||
var autoUpdater = require('auto-updater');
|
import autoUpdater from 'auto-updater';
|
||||||
var BrowserWindow = require('browser-window');
|
import BrowserWindow from 'browser-window';
|
||||||
var fs = require('fs');
|
import fs from 'fs';
|
||||||
var os = require('os');
|
import os from 'os';
|
||||||
var ipc = require('ipc');
|
import ipc from 'ipc';
|
||||||
var path = require('path');
|
import path from 'path';
|
||||||
var child_process = require('child_process');
|
import child_process from 'child_process';
|
||||||
|
|
||||||
process.env.NODE_PATH = path.join(__dirname, 'node_modules');
|
process.env.NODE_PATH = path.join(__dirname, 'node_modules');
|
||||||
process.env.RESOURCES_PATH = path.join(__dirname, '/../resources');
|
process.env.RESOURCES_PATH = path.join(__dirname, '/../resources');
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,69 @@
|
||||||
|
import React from 'react/addons';
|
||||||
|
import metrics from '../utils/MetricsUtil';
|
||||||
|
import utils from '../utils/Util';
|
||||||
|
import Router from 'react-router';
|
||||||
|
import RetinaImage from 'react-retina-image';
|
||||||
|
var packages;
|
||||||
|
|
||||||
|
try {
|
||||||
|
packages = utils.packagejson();
|
||||||
|
} catch (err) {
|
||||||
|
packages = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var Preferences = React.createClass({
|
||||||
|
mixins: [Router.Navigation],
|
||||||
|
getInitialState: function () {
|
||||||
|
return {
|
||||||
|
metricsEnabled: metrics.enabled()
|
||||||
|
};
|
||||||
|
},
|
||||||
|
handleGoBackClick: function () {
|
||||||
|
this.goBack();
|
||||||
|
metrics.track('Went Back From About');
|
||||||
|
},
|
||||||
|
render: function () {
|
||||||
|
return (
|
||||||
|
<div className="preferences">
|
||||||
|
<div className="about-content">
|
||||||
|
<a onClick={this.handleGoBackClick}>Go Back</a>
|
||||||
|
<div className="items">
|
||||||
|
<div className="item">
|
||||||
|
<RetinaImage src="cartoon-kitematic.png"/>
|
||||||
|
<h4>Docker {packages.name}</h4>
|
||||||
|
<p>{packages.version}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3>Kitematic is built with:</h3>
|
||||||
|
<div className="items">
|
||||||
|
<div className="item">
|
||||||
|
<RetinaImage src="cartoon-docker.png"/>
|
||||||
|
<h4>Docker Engine</h4>
|
||||||
|
<p>{packages["docker-version"]}</p>
|
||||||
|
</div>
|
||||||
|
<div className="item">
|
||||||
|
<RetinaImage src="cartoon-docker-machine.png"/>
|
||||||
|
<h4>Docker Machine</h4>
|
||||||
|
<p>{packages["docker-machine-version"]}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<h3>Third-Party Software</h3>
|
||||||
|
<div className="items">
|
||||||
|
<div className="item">
|
||||||
|
<h4>VirtualBox</h4>
|
||||||
|
<p>{packages["virtualbox-version"]}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="items">
|
||||||
|
<div className="item">
|
||||||
|
<h4>Electron</h4>
|
||||||
|
<p>{packages["electron-version"]}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
module.exports = Preferences;
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
var RetinaImage = require('react-retina-image');
|
import RetinaImage from 'react-retina-image';
|
||||||
var Header = require('./Header.react');
|
import Header from './Header.react';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var accountStore = require('../stores/AccountStore');
|
import accountStore from '../stores/AccountStore';
|
||||||
var accountActions = require('../actions/AccountActions');
|
import accountActions from '../actions/AccountActions';
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [Router.Navigation],
|
mixins: [Router.Navigation],
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
var validator = require('validator');
|
import validator from 'validator';
|
||||||
var accountActions = require('../actions/AccountActions');
|
import accountActions from '../actions/AccountActions';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var shell = require('shell');
|
import shell from 'shell';
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [Router.Navigation, React.addons.LinkedStateMixin],
|
mixins: [Router.Navigation, React.addons.LinkedStateMixin],
|
||||||
|
|
@ -60,7 +60,7 @@ module.exports = React.createClass({
|
||||||
},
|
},
|
||||||
|
|
||||||
handleClickForgotPassword: function () {
|
handleClickForgotPassword: function () {
|
||||||
shell.openExternal('https://hub.docker.com/account/forgot-password/');
|
shell.openExternal('https://hub.docker.com/reset-password/');
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
var validator = require('validator');
|
import validator from 'validator';
|
||||||
var accountActions = require('../actions/AccountActions');
|
import accountActions from '../actions/AccountActions';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [Router.Navigation, React.addons.LinkedStateMixin],
|
mixins: [Router.Navigation, React.addons.LinkedStateMixin],
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
var ContainerDetailsHeader = require('./ContainerDetailsHeader.react');
|
import ContainerDetailsHeader from './ContainerDetailsHeader.react';
|
||||||
var ContainerDetailsSubheader = require('./ContainerDetailsSubheader.react');
|
import ContainerDetailsSubheader from './ContainerDetailsSubheader.react';
|
||||||
var containerUtil = require('../utils/ContainerUtil');
|
import containerUtil from '../utils/ContainerUtil';
|
||||||
var util = require('../utils/Util');
|
import util from '../utils/Util';
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
|
|
||||||
var ContainerDetails = React.createClass({
|
var ContainerDetails = React.createClass({
|
||||||
contextTypes: {
|
contextTypes: {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
|
|
||||||
var ContainerDetailsHeader = React.createClass({
|
var ContainerDetailsHeader = React.createClass({
|
||||||
render: function () {
|
render: function () {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var React = require('react');
|
import React from 'react';
|
||||||
var shell = require('shell');
|
import shell from 'shell';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var ContainerUtil = require('../utils/ContainerUtil');
|
import ContainerUtil from '../utils/ContainerUtil';
|
||||||
var classNames = require('classnames');
|
import classNames from 'classnames';
|
||||||
var containerActions = require('../actions/ContainerActions');
|
import containerActions from '../actions/ContainerActions';
|
||||||
var dockerMachineUtil = require('../utils/DockerMachineUtil');
|
import dockerMachineUtil from '../utils/DockerMachineUtil';
|
||||||
|
|
||||||
var ContainerDetailsSubheader = React.createClass({
|
var ContainerDetailsSubheader = React.createClass({
|
||||||
contextTypes: {
|
contextTypes: {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var $ = require('jquery');
|
import $ from 'jquery';
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var Radial = require('./Radial.react');
|
import Radial from './Radial.react';
|
||||||
var ContainerProgress = require('./ContainerProgress.react');
|
import ContainerProgress from './ContainerProgress.react';
|
||||||
var ContainerHomePreview = require('./ContainerHomePreview.react');
|
import ContainerHomePreview from './ContainerHomePreview.react';
|
||||||
var ContainerHomeLogs = require('./ContainerHomeLogs.react');
|
import ContainerHomeLogs from './ContainerHomeLogs.react';
|
||||||
var ContainerHomeFolders = require('./ContainerHomeFolders.react');
|
import ContainerHomeFolders from './ContainerHomeFolders.react';
|
||||||
var shell = require('shell');
|
import shell from 'shell';
|
||||||
|
|
||||||
var ContainerHome = React.createClass({
|
var ContainerHome = React.createClass({
|
||||||
contextTypes: {
|
contextTypes: {
|
||||||
|
|
@ -39,11 +39,11 @@ var ContainerHome = React.createClass({
|
||||||
showWeb: function () {
|
showWeb: function () {
|
||||||
return _.keys(this.props.ports).length > 0;
|
return _.keys(this.props.ports).length > 0;
|
||||||
},
|
},
|
||||||
|
|
||||||
showFolders: function () {
|
showFolders: function () {
|
||||||
return this.props.container.Volumes && _.keys(this.props.container.Volumes).length > 0 && this.props.container.State.Running;
|
return this.props.container.Mounts && this.props.container.Mounts.length > 0 && this.props.container.State.Running;
|
||||||
},
|
},
|
||||||
|
|
||||||
render: function () {
|
render: function () {
|
||||||
if (!this.props.container) {
|
if (!this.props.container) {
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,49 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var RetinaImage = require('react-retina-image');
|
import RetinaImage from 'react-retina-image';
|
||||||
var path = require('path');
|
import path from 'path';
|
||||||
var shell = require('shell');
|
import shell from 'shell';
|
||||||
var util = require('../utils/Util');
|
import util from '../utils/Util';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var containerActions = require('../actions/ContainerActions');
|
import containerActions from '../actions/ContainerActions';
|
||||||
var dialog = require('remote').require('dialog');
|
import remote from 'remote';
|
||||||
var mkdirp = require('mkdirp');
|
var dialog = remote.require('dialog');
|
||||||
|
import mkdirp from 'mkdirp';
|
||||||
|
|
||||||
var ContainerHomeFolder = React.createClass({
|
var ContainerHomeFolder = React.createClass({
|
||||||
contextTypes: {
|
contextTypes: {
|
||||||
router: React.PropTypes.func
|
router: React.PropTypes.func
|
||||||
},
|
},
|
||||||
handleClickFolder: function (hostVolume, containerVolume) {
|
handleClickFolder: function (source, destination) {
|
||||||
metrics.track('Opened Volume Directory', {
|
metrics.track('Opened Volume Directory', {
|
||||||
from: 'home'
|
from: 'home'
|
||||||
});
|
});
|
||||||
|
|
||||||
if (hostVolume.indexOf(util.windowsToLinuxPath(util.home())) === -1) {
|
if (source.indexOf(util.windowsToLinuxPath(util.home())) === -1) {
|
||||||
dialog.showMessageBox({
|
dialog.showMessageBox({
|
||||||
message: 'Enable all volumes to edit files via Finder? This may not work with all database containers.',
|
message: `Enable all volumes to edit files? This may not work with all database containers.`,
|
||||||
buttons: ['Enable Volumes', 'Cancel']
|
buttons: ['Enable Volumes', 'Cancel']
|
||||||
}, (index) => {
|
}, (index) => {
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
var volumes = _.clone(this.props.container.Volumes);
|
var mounts = _.clone(this.props.container.Mounts);
|
||||||
var newHostVolume = util.escapePath(path.join(util.home(), util.documents(), 'Kitematic', this.props.container.Name, containerVolume));
|
var newSource = util.escapePath(path.join(util.home(), util.documents(), 'Kitematic', this.props.container.Name, destination));
|
||||||
volumes[containerVolume] = newHostVolume;
|
var binds = mounts.map(function (m) {
|
||||||
var binds = _.pairs(volumes).map(function (pair) {
|
let source = m.Source;
|
||||||
if(util.isWindows()) {
|
if (m.Destination === destination) {
|
||||||
return util.windowsToLinuxPath(pair[1]) + ':' + pair[0];
|
source = newSource;
|
||||||
}
|
}
|
||||||
return pair[1] + ':' + pair[0];
|
|
||||||
|
if(util.isWindows()) {
|
||||||
|
return util.windowsToLinuxPath(source) + ':' + m.Destination;
|
||||||
|
}
|
||||||
|
|
||||||
|
return source + ':' + m.Destination;
|
||||||
});
|
});
|
||||||
mkdirp(newHostVolume, function (err) {
|
|
||||||
|
mkdirp(newSource, function (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
if (!err) {
|
if (!err) {
|
||||||
shell.showItemInFolder(newHostVolume);
|
shell.showItemInFolder(newSource);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
@ -44,7 +51,7 @@ var ContainerHomeFolder = React.createClass({
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
let path = util.isWindows() ? util.linuxToWindowsPath(hostVolume) : hostVolume;
|
let path = util.isWindows() ? util.linuxToWindowsPath(source) : source;
|
||||||
shell.showItemInFolder(path);
|
shell.showItemInFolder(path);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
@ -59,12 +66,13 @@ var ContainerHomeFolder = React.createClass({
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
var folders = _.map(_.omit(this.props.container.Volumes, (v, k) => k.indexOf('/Users/') !== -1), (val, key) => {
|
var folders = _.map(this.props.container.Mounts, (m, i) => {
|
||||||
var firstFolder = key;
|
let destination = m.Destination;
|
||||||
|
let source = m.Source;
|
||||||
return (
|
return (
|
||||||
<div key={key} className="folder" onClick={this.handleClickFolder.bind(this, val, key)}>
|
<div key={i} className="folder" onClick={this.handleClickFolder.bind(this, source, destination)}>
|
||||||
<RetinaImage src="folder.png" />
|
<RetinaImage src="folder.png" />
|
||||||
<div className="text">{firstFolder}</div>
|
<div className="text">{destination}</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
var $ = require('jquery');
|
import $ from 'jquery';
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var LogStore = require('../stores/LogStore');
|
import LogStore from '../stores/LogStore';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
|
|
||||||
var _prevBottom = 0;
|
var _prevBottom = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var request = require('request');
|
import request from 'request';
|
||||||
var shell = require('shell');
|
import shell from 'shell';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
|
|
||||||
var ContainerHomePreview = React.createClass({
|
var ContainerHomePreview = React.createClass({
|
||||||
contextTypes: {
|
contextTypes: {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var ContainerListItem = require('./ContainerListItem.react');
|
import ContainerListItem from './ContainerListItem.react';
|
||||||
|
|
||||||
var ContainerList = React.createClass({
|
var ContainerList = React.createClass({
|
||||||
componentWillMount: function () {
|
componentWillMount: function () {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,11 @@
|
||||||
var $ = require('jquery');
|
import $ from 'jquery';
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
var remote = require('remote');
|
import remote from 'remote';
|
||||||
var dialog = remote.require('dialog');
|
var dialog = remote.require('dialog');
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var OverlayTrigger = require('react-bootstrap').OverlayTrigger;
|
import {OverlayTrigger, Tooltip} from 'react-bootstrap';
|
||||||
var Tooltip = require('react-bootstrap').Tooltip;
|
import containerActions from '../actions/ContainerActions';
|
||||||
var containerActions = require('../actions/ContainerActions');
|
|
||||||
|
|
||||||
var ContainerListItem = React.createClass({
|
var ContainerListItem = React.createClass({
|
||||||
handleItemMouseEnter: function () {
|
handleItemMouseEnter: function () {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
var $ = require('jquery');
|
import $ from 'jquery';
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var LogStore = require('../stores/LogStore');
|
import LogStore from '../stores/LogStore';
|
||||||
|
|
||||||
var _prevBottom = 0;
|
var _prevBottom = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
var React = require('react');
|
import React from 'react';
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
var $ = require('jquery');
|
import $ from 'jquery';
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
|
|
||||||
var ContainerSettings = React.createClass({
|
var ContainerSettings = React.createClass({
|
||||||
contextTypes: {
|
contextTypes: {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var ContainerUtil = require('../utils/ContainerUtil');
|
import ContainerUtil from '../utils/ContainerUtil';
|
||||||
var containerActions = require('../actions/ContainerActions');
|
import containerActions from '../actions/ContainerActions';
|
||||||
|
|
||||||
var ContainerSettingsAdvanced = React.createClass({
|
var ContainerSettingsAdvanced = React.createClass({
|
||||||
mixins: [React.addons.LinkedStateMixin],
|
mixins: [React.addons.LinkedStateMixin],
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var remote = require('remote');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import remote from 'remote';
|
||||||
var dialog = remote.require('dialog');
|
var dialog = remote.require('dialog');
|
||||||
var ContainerUtil = require('../utils/ContainerUtil');
|
import ContainerUtil from '../utils/ContainerUtil';
|
||||||
var containerActions = require('../actions/ContainerActions');
|
import containerActions from '../actions/ContainerActions';
|
||||||
var util = require('../utils/Util');
|
import util from '../utils/Util';
|
||||||
|
|
||||||
var ContainerSettingsGeneral = React.createClass({
|
var ContainerSettingsGeneral = React.createClass({
|
||||||
mixins: [React.addons.LinkedStateMixin],
|
mixins: [React.addons.LinkedStateMixin],
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var shell = require('shell');
|
import shell from 'shell';
|
||||||
var ContainerUtil = require('../utils/ContainerUtil');
|
import ContainerUtil from '../utils/ContainerUtil';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var webPorts = require('../utils/Util').webPorts;
|
import {webPorts} from '../utils/Util';
|
||||||
|
|
||||||
var ContainerSettingsPorts = React.createClass({
|
var ContainerSettingsPorts = React.createClass({
|
||||||
contextTypes: {
|
contextTypes: {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var remote = require('remote');
|
import remote from 'remote';
|
||||||
var dialog = remote.require('dialog');
|
var dialog = remote.require('dialog');
|
||||||
var shell = require('shell');
|
import shell from 'shell';
|
||||||
var util = require('../utils/Util');
|
import util from '../utils/Util';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var containerActions = require('../actions/ContainerActions');
|
import containerActions from '../actions/ContainerActions';
|
||||||
|
|
||||||
var ContainerSettingsVolumes = React.createClass({
|
var ContainerSettingsVolumes = React.createClass({
|
||||||
handleChooseVolumeClick: function (dockerVol) {
|
handleChooseVolumeClick: function (dockerVol) {
|
||||||
|
|
@ -26,16 +26,23 @@ var ContainerSettingsVolumes = React.createClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
metrics.track('Choose Directory for Volume');
|
metrics.track('Choose Directory for Volume');
|
||||||
|
|
||||||
if(util.isWindows()) {
|
if(util.isWindows()) {
|
||||||
directory = util.escapePath(util.windowsToLinuxPath(directory));
|
directory = util.escapePath(util.windowsToLinuxPath(directory));
|
||||||
}
|
}
|
||||||
var volumes = _.clone(this.props.container.Volumes);
|
|
||||||
volumes[dockerVol] = directory;
|
var mounts = _.clone(this.props.container.Mounts);
|
||||||
var binds = _.pairs(volumes).map(function (pair) {
|
_.each(mounts, m => {
|
||||||
return pair[1] + ':' + pair[0];
|
if (m.Destination === dockerVol) {
|
||||||
|
m.Source = directory;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
containerActions.update(this.props.container.Name, {Binds: binds, Volumes: volumes});
|
var binds = mounts.map(m => {
|
||||||
|
return m.Source + ':' + m.Destination;
|
||||||
|
});
|
||||||
|
|
||||||
|
containerActions.update(this.props.container.Name, {Binds: binds, Mounts: mounts});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleRemoveVolumeClick: function (dockerVol) {
|
handleRemoveVolumeClick: function (dockerVol) {
|
||||||
|
|
@ -45,13 +52,17 @@ var ContainerSettingsVolumes = React.createClass({
|
||||||
|
|
||||||
var hostConfig = _.clone(this.props.container.HostConfig);
|
var hostConfig = _.clone(this.props.container.HostConfig);
|
||||||
var binds = hostConfig.Binds;
|
var binds = hostConfig.Binds;
|
||||||
var volumes = _.clone(this.props.container.Volumes);
|
var mounts = _.clone(this.props.container.Mounts);
|
||||||
volumes[dockerVol] = null;
|
_.each(mounts, m => {
|
||||||
|
if (m.Destination === dockerVol) {
|
||||||
|
m.Source = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
var index = _.findIndex(binds, bind => bind.indexOf(`:${dockerVol}`) !== -1);
|
var index = _.findIndex(binds, bind => bind.indexOf(`:${dockerVol}`) !== -1);
|
||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
binds.splice(index, 1);
|
binds.splice(index, 1);
|
||||||
}
|
}
|
||||||
containerActions.update(this.props.container.Name, {HostConfig: hostConfig, Binds: binds, Volumes: volumes});
|
containerActions.update(this.props.container.Name, {HostConfig: hostConfig, Binds: binds, Mounts: mounts});
|
||||||
},
|
},
|
||||||
handleOpenVolumeClick: function (path) {
|
handleOpenVolumeClick: function (path) {
|
||||||
metrics.track('Opened Volume Directory', {
|
metrics.track('Opened Volume Directory', {
|
||||||
|
|
@ -69,24 +80,25 @@ var ContainerSettingsVolumes = React.createClass({
|
||||||
}
|
}
|
||||||
|
|
||||||
var homeDir = util.isWindows() ? util.windowsToLinuxPath(util.home()) : util.home();
|
var homeDir = util.isWindows() ? util.windowsToLinuxPath(util.home()) : util.home();
|
||||||
var volumes = _.map(this.props.container.Volumes, (val, key) => {
|
var mounts= _.map(this.props.container.Mounts, (m, i) => {
|
||||||
if (!val || val.indexOf(homeDir) === -1) {
|
let source = m.Source, destination = m.Destination;
|
||||||
val = (
|
if (!m.Source || m.Source.indexOf(homeDir) === -1) {
|
||||||
|
source = (
|
||||||
<span className="value-right">No Folder</span>
|
<span className="value-right">No Folder</span>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
let local = util.isWindows() ? util.linuxToWindowsPath(val) : val;
|
let local = util.isWindows() ? util.linuxToWindowsPath(source) : source;
|
||||||
val = (
|
source = (
|
||||||
<a className="value-right" onClick={this.handleOpenVolumeClick.bind(this, val)}>{local.replace(process.env.HOME, '~')}</a>
|
<a className="value-right" onClick={this.handleOpenVolumeClick.bind(this, source)}>{local.replace(process.env.HOME, '~')}</a>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<tr>
|
<tr>
|
||||||
<td>{key}</td>
|
<td>{destination}</td>
|
||||||
<td>{val}</td>
|
<td>{source}</td>
|
||||||
<td>
|
<td>
|
||||||
<a className="btn btn-action small" disabled={this.props.container.State.Updating} onClick={this.handleChooseVolumeClick.bind(this, key)}>Change</a>
|
<a className="btn btn-action small" disabled={this.props.container.State.Updating} onClick={this.handleChooseVolumeClick.bind(this, destination)}>Change</a>
|
||||||
<a className="btn btn-action small" disabled={this.props.container.State.Updating} onClick={this.handleRemoveVolumeClick.bind(this, key)}>Remove</a>
|
<a className="btn btn-action small" disabled={this.props.container.State.Updating} onClick={this.handleRemoveVolumeClick.bind(this, destination)}>Remove</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
);
|
);
|
||||||
|
|
@ -104,7 +116,7 @@ var ContainerSettingsVolumes = React.createClass({
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{volumes}
|
{mounts}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
var $ = require('jquery');
|
import $ from 'jquery';
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var React = require('react');
|
import React from 'react';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
var containerStore = require('../stores/ContainerStore');
|
import containerStore from '../stores/ContainerStore';
|
||||||
var ContainerList = require('./ContainerList.react');
|
import ContainerList from './ContainerList.react';
|
||||||
var Header = require('./Header.react');
|
import Header from './Header.react';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var shell = require('shell');
|
import shell from 'shell';
|
||||||
var machine = require('../utils/DockerMachineUtil');
|
import machine from '../utils/DockerMachineUtil';
|
||||||
|
|
||||||
var Containers = React.createClass({
|
var Containers = React.createClass({
|
||||||
contextTypes: {
|
contextTypes: {
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,16 @@
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var remote = require('remote');
|
import remote from 'remote';
|
||||||
var RetinaImage = require('react-retina-image');
|
import RetinaImage from 'react-retina-image';
|
||||||
var remote = require('remote');
|
import ipc from 'ipc';
|
||||||
var ipc = require('ipc');
|
|
||||||
var autoUpdater = remote.require('auto-updater');
|
var autoUpdater = remote.require('auto-updater');
|
||||||
var util = require('../utils/Util');
|
import util from '../utils/Util';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var Menu = remote.require('menu');
|
var Menu = remote.require('menu');
|
||||||
var MenuItem = remote.require('menu-item');
|
var MenuItem = remote.require('menu-item');
|
||||||
var accountStore = require('../stores/AccountStore');
|
import accountStore from '../stores/AccountStore';
|
||||||
var accountActions = require('../actions/AccountActions');
|
import accountActions from '../actions/AccountActions';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
var classNames = require('classnames');
|
import classNames from 'classnames';
|
||||||
|
|
||||||
var Header = React.createClass({
|
var Header = React.createClass({
|
||||||
mixins: [Router.Navigation],
|
mixins: [Router.Navigation],
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
var $ = require('jquery');
|
import $ from 'jquery';
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
var shell = require('shell');
|
import shell from 'shell';
|
||||||
var RetinaImage = require('react-retina-image');
|
import RetinaImage from 'react-retina-image';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var containerActions = require('../actions/ContainerActions');
|
import containerActions from '../actions/ContainerActions';
|
||||||
var containerStore = require('../stores/ContainerStore');
|
import containerStore from '../stores/ContainerStore';
|
||||||
var tagStore = require('../stores/TagStore');
|
import tagStore from '../stores/TagStore';
|
||||||
var tagActions = require('../actions/TagActions');
|
import tagActions from '../actions/TagActions';
|
||||||
|
|
||||||
var ImageCard = React.createClass({
|
var ImageCard = React.createClass({
|
||||||
mixins: [Router.Navigation],
|
mixins: [Router.Navigation],
|
||||||
|
|
@ -108,7 +108,8 @@ var ImageCard = React.createClass({
|
||||||
description = "No description.";
|
description = "No description.";
|
||||||
}
|
}
|
||||||
var logoStyle = {
|
var logoStyle = {
|
||||||
backgroundImage: `linear-gradient(-180deg, ${this.props.image.gradient_start} 4%, ${this.props.image.gradient_end} 100%)`
|
//backgroundImage: `linear-gradient(-180deg, ${this.props.image.gradient_start} 4%, ${this.props.image.gradient_end} 100%)`
|
||||||
|
backgroundColor: this.props.image.gradient_start
|
||||||
};
|
};
|
||||||
var imgsrc;
|
var imgsrc;
|
||||||
if (this.props.image.img) {
|
if (this.props.image.img) {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
var shell = require('shell');
|
import shell from 'shell';
|
||||||
var containerActions = require('../actions/ContainerActions');
|
import containerActions from '../actions/ContainerActions';
|
||||||
var containerStore = require('../stores/ContainerStore');
|
import containerStore from '../stores/ContainerStore';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
|
|
||||||
module.exports = React.createClass({
|
module.exports = React.createClass({
|
||||||
mixins: [Router.Navigation],
|
mixins: [Router.Navigation],
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,15 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
var RetinaImage = require('react-retina-image');
|
import RetinaImage from 'react-retina-image';
|
||||||
var ImageCard = require('./ImageCard.react');
|
import ImageCard from './ImageCard.react';
|
||||||
var Promise = require('bluebird');
|
import Promise from 'bluebird';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var classNames = require('classnames');
|
import classNames from 'classnames';
|
||||||
var repositoryActions = require('../actions/RepositoryActions');
|
import repositoryActions from '../actions/RepositoryActions';
|
||||||
var repositoryStore = require('../stores/RepositoryStore');
|
import repositoryStore from '../stores/RepositoryStore';
|
||||||
var accountStore = require('../stores/AccountStore');
|
import accountStore from '../stores/AccountStore';
|
||||||
var accountActions = require('../actions/AccountActions');
|
import accountActions from '../actions/AccountActions';
|
||||||
|
|
||||||
var _searchPromise = null;
|
var _searchPromise = null;
|
||||||
|
|
||||||
|
|
@ -222,7 +222,7 @@ module.exports = React.createClass({
|
||||||
<div className="new-container-header">
|
<div className="new-container-header">
|
||||||
<div className="search">
|
<div className="search">
|
||||||
<div className="search-bar">
|
<div className="search-bar">
|
||||||
<input type="search" ref="searchInput" className="form-control" placeholder="Search image on Docker Hub" onChange={this.handleChange}/>
|
<input type="search" ref="searchInput" className="form-control" placeholder="Search for Docker images from Docker Hub" onChange={this.handleChange}/>
|
||||||
<div className={magnifierClasses}></div>
|
<div className={magnifierClasses}></div>
|
||||||
<div className={loadingClasses}><div></div></div>
|
<div className={loadingClasses}><div></div></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
|
|
||||||
var Preferences = React.createClass({
|
var Preferences = React.createClass({
|
||||||
mixins: [Router.Navigation],
|
mixins: [Router.Navigation],
|
||||||
|
|
@ -42,7 +42,7 @@ var Preferences = React.createClass({
|
||||||
<div className="title">VM Settings</div>
|
<div className="title">VM Settings</div>
|
||||||
<div className="option">
|
<div className="option">
|
||||||
<div className="option-name">
|
<div className="option-name">
|
||||||
Shut Down Linux VM on closing Kitematic
|
Shutdown Linux VM on closing Kitematic
|
||||||
</div>
|
</div>
|
||||||
<div className="option-value">
|
<div className="option-value">
|
||||||
<input type="checkbox" checked={this.state.closeVMOnQuit} onChange={this.handleChangeCloseVMOnQuit}/>
|
<input type="checkbox" checked={this.state.closeVMOnQuit} onChange={this.handleChangeCloseVMOnQuit}/>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
var React = require('react');
|
import React from 'react';
|
||||||
var classNames = require('classnames');
|
import classNames from 'classnames';
|
||||||
|
|
||||||
var Radial = React.createClass({
|
var Radial = React.createClass({
|
||||||
render: function () {
|
render: function () {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var Router = require('react-router');
|
import Router from 'react-router';
|
||||||
var Radial = require('./Radial.react.js');
|
import Radial from './Radial.react.js';
|
||||||
var SetupStore = require('../stores/SetupStore');
|
import SetupStore from '../stores/SetupStore';
|
||||||
var RetinaImage = require('react-retina-image');
|
import RetinaImage from 'react-retina-image';
|
||||||
var Header = require('./Header.react');
|
import Header from './Header.react';
|
||||||
var Util = require('../utils/Util');
|
import Util from '../utils/Util';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
|
|
||||||
var Setup = React.createClass({
|
var Setup = React.createClass({
|
||||||
mixins: [ Router.Navigation ],
|
mixins: [ Router.Navigation ],
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,12 @@ var MenuTemplate = function () {
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
label: 'About Kitematic',
|
label: 'About Kitematic',
|
||||||
selector: 'orderFrontStandardAboutPanel:'
|
click: function () {
|
||||||
|
metrics.track('Opened About', {
|
||||||
|
from: 'menu'
|
||||||
|
});
|
||||||
|
router.get().transitionTo('about');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'separator'
|
type: 'separator'
|
||||||
|
|
@ -37,35 +42,9 @@ var MenuTemplate = function () {
|
||||||
type: 'separator'
|
type: 'separator'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Install Docker Commands',
|
type: 'separator'
|
||||||
enabled: true,
|
|
||||||
click: function () {
|
|
||||||
metrics.track('Installed Docker Commands');
|
|
||||||
if (!setupUtil.shouldUpdateBinaries()) {
|
|
||||||
dialog.showMessageBox({
|
|
||||||
message: 'Docker binaries are already installed in /usr/local/bin',
|
|
||||||
buttons: ['OK']
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let copy = setupUtil.needsBinaryFix() ?
|
|
||||||
util.exec(setupUtil.macSudoCmd(setupUtil.copyBinariesCmd() + ' && ' + setupUtil.fixBinariesCmd())) :
|
|
||||||
util.exec(setupUtil.copyBinariesCmd());
|
|
||||||
|
|
||||||
copy.then(() => {
|
|
||||||
dialog.showMessageBox({
|
|
||||||
message: 'Docker binaries have been installed under /usr/local/bin',
|
|
||||||
buttons: ['OK']
|
|
||||||
});
|
|
||||||
}).catch((err) => {
|
|
||||||
console.log(err);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'separator'
|
|
||||||
}, {
|
|
||||||
label: 'Hide Kitematic',
|
label: 'Hide Kitematic',
|
||||||
accelerator: util.CommandOrCtrl() + '+H',
|
accelerator: util.CommandOrCtrl() + '+H',
|
||||||
selector: 'hide:'
|
selector: 'hide:'
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,22 @@
|
||||||
var React = require('react/addons');
|
import React from 'react/addons';
|
||||||
var Setup = require('./components/Setup.react');
|
import Setup from './components/Setup.react';
|
||||||
var Account = require('./components/Account.react');
|
import Account from './components/Account.react';
|
||||||
var AccountSignup = require('./components/AccountSignup.react');
|
import AccountSignup from './components/AccountSignup.react';
|
||||||
var AccountLogin = require('./components/AccountLogin.react');
|
import AccountLogin from './components/AccountLogin.react';
|
||||||
var Containers = require('./components/Containers.react');
|
import Containers from './components/Containers.react';
|
||||||
var ContainerDetails = require('./components/ContainerDetails.react');
|
import ContainerDetails from './components/ContainerDetails.react';
|
||||||
var ContainerHome = require('./components/ContainerHome.react');
|
import ContainerHome from './components/ContainerHome.react';
|
||||||
var ContainerLogs = require('./components/ContainerLogs.react');
|
import ContainerLogs from './components/ContainerLogs.react';
|
||||||
var ContainerSettings = require('./components/ContainerSettings.react');
|
import ContainerSettings from './components/ContainerSettings.react';
|
||||||
var ContainerSettingsGeneral = require('./components/ContainerSettingsGeneral.react');
|
import ContainerSettingsGeneral from './components/ContainerSettingsGeneral.react';
|
||||||
var ContainerSettingsPorts = require('./components/ContainerSettingsPorts.react');
|
import ContainerSettingsPorts from './components/ContainerSettingsPorts.react';
|
||||||
var ContainerSettingsVolumes = require('./components/ContainerSettingsVolumes.react');
|
import ContainerSettingsVolumes from './components/ContainerSettingsVolumes.react';
|
||||||
var ContainerSettingsAdvanced = require('./components/ContainerSettingsAdvanced.react');
|
import ContainerSettingsAdvanced from './components/ContainerSettingsAdvanced.react';
|
||||||
var Preferences = require('./components/Preferences.react');
|
import Preferences from './components/Preferences.react';
|
||||||
var NewContainerSearch = require('./components/NewContainerSearch.react');
|
import About from './components/About.react';
|
||||||
var NewContainerPull = require('./components/NewContainerPull.react');
|
import NewContainerSearch from './components/NewContainerSearch.react';
|
||||||
var Router = require('react-router');
|
import NewContainerPull from './components/NewContainerPull.react';
|
||||||
|
import Router from 'react-router';
|
||||||
|
|
||||||
var Route = Router.Route;
|
var Route = Router.Route;
|
||||||
var DefaultRoute = Router.DefaultRoute;
|
var DefaultRoute = Router.DefaultRoute;
|
||||||
|
|
@ -51,6 +52,7 @@ var routes = (
|
||||||
<Route name="pull" path="containers/new/pull" handler={NewContainerPull}></Route>
|
<Route name="pull" path="containers/new/pull" handler={NewContainerPull}></Route>
|
||||||
</Route>
|
</Route>
|
||||||
<Route name="preferences" path="/preferences" handler={Preferences}/>
|
<Route name="preferences" path="/preferences" handler={Preferences}/>
|
||||||
|
<Route name="about" path="/about" handler={About}/>
|
||||||
</Route>
|
</Route>
|
||||||
<DefaultRoute name="setup" handler={Setup}/>
|
<DefaultRoute name="setup" handler={Setup}/>
|
||||||
</Route>
|
</Route>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
var EventEmitter = require('events').EventEmitter;
|
import {EventEmitter} from 'events';
|
||||||
var assign = require('object-assign');
|
import assign from 'object-assign';
|
||||||
var Convert = require('ansi-to-html');
|
import Convert from 'ansi-to-html';
|
||||||
var docker = require('../utils/DockerUtil');
|
import docker from '../utils/DockerUtil';
|
||||||
var stream = require('stream');
|
import stream from 'stream';
|
||||||
|
|
||||||
var _convert = new Convert();
|
var _convert = new Convert();
|
||||||
var _logs = {};
|
var _logs = {};
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
var EventEmitter = require('events').EventEmitter;
|
import {EventEmitter} from 'events';
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var path = require('path');
|
import path from 'path';
|
||||||
var fs = require('fs');
|
import fs from 'fs';
|
||||||
var Promise = require('bluebird');
|
import Promise from 'bluebird';
|
||||||
var machine = require('../utils/DockerMachineUtil');
|
import machine from '../utils/DockerMachineUtil';
|
||||||
var virtualBox = require('../utils/VirtualBoxUtil');
|
import virtualBox from '../utils/VirtualBoxUtil';
|
||||||
var setupUtil = require('../utils/SetupUtil');
|
import setupUtil from '../utils/SetupUtil';
|
||||||
var util = require('../utils/Util');
|
import util from '../utils/Util';
|
||||||
var assign = require('object-assign');
|
import assign from 'object-assign';
|
||||||
var metrics = require('../utils/MetricsUtil');
|
import metrics from '../utils/MetricsUtil';
|
||||||
var bugsnag = require('bugsnag-js');
|
import bugsnag from 'bugsnag-js';
|
||||||
var docker = require('../utils/DockerUtil');
|
import docker from '../utils/DockerUtil';
|
||||||
|
|
||||||
var _currentStep = null;
|
var _currentStep = null;
|
||||||
var _error = null;
|
var _error = null;
|
||||||
|
|
@ -73,7 +73,8 @@ var _steps = [{
|
||||||
|
|
||||||
var isoversion = machine.isoversion();
|
var isoversion = machine.isoversion();
|
||||||
var packagejson = util.packagejson();
|
var packagejson = util.packagejson();
|
||||||
if (!isoversion || util.compareVersions(isoversion, packagejson['docker-version']) < 0) {
|
var packagejsonVersion = packagejson['docker-version'].split('-')[0];
|
||||||
|
if (!isoversion || util.compareVersions(isoversion, packagejsonVersion) < 0) {
|
||||||
yield machine.start();
|
yield machine.start();
|
||||||
yield machine.upgrade();
|
yield machine.upgrade();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var docker = require('../utils/DockerUtil');
|
import docker from '../utils/DockerUtil';
|
||||||
|
|
||||||
var ContainerUtil = {
|
var ContainerUtil = {
|
||||||
env: function (container) {
|
env: function (container) {
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,20 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var path = require('path');
|
import path from 'path';
|
||||||
var Promise = require('bluebird');
|
import Promise from 'bluebird';
|
||||||
var fs = require('fs');
|
import fs from 'fs';
|
||||||
var util = require('./Util');
|
import util from './Util';
|
||||||
var resources = require('./ResourcesUtil');
|
import resources from './ResourcesUtil';
|
||||||
|
|
||||||
var NAME = util.isWindows () ? 'kitematic' : 'dev';
|
|
||||||
|
|
||||||
var DockerMachine = {
|
var DockerMachine = {
|
||||||
command: function () {
|
command: function () {
|
||||||
return resources.dockerMachine();
|
return resources.dockerMachine();
|
||||||
},
|
},
|
||||||
name: function () {
|
name: function () {
|
||||||
return NAME;
|
return 'default';
|
||||||
},
|
},
|
||||||
isoversion: function () {
|
isoversion: function (machineName = this.name()) {
|
||||||
try {
|
try {
|
||||||
var data = fs.readFileSync(path.join(util.home(), '.docker', 'machine', 'machines', NAME, 'boot2docker.iso'), 'utf8');
|
var data = fs.readFileSync(path.join(util.home(), '.docker', 'machine', 'machines', machineName, 'boot2docker.iso'), 'utf8');
|
||||||
var match = data.match(/Boot2Docker-v(\d+\.\d+\.\d+)/);
|
var match = data.match(/Boot2Docker-v(\d+\.\d+\.\d+)/);
|
||||||
if (match) {
|
if (match) {
|
||||||
return match[1];
|
return match[1];
|
||||||
|
|
@ -27,7 +25,7 @@ var DockerMachine = {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
info: function () {
|
info: function (machineName = this.name()) {
|
||||||
return util.exec([this.command(), 'ls']).then(stdout => {
|
return util.exec([this.command(), 'ls']).then(stdout => {
|
||||||
var lines = stdout.trim().split('\n').filter(line => line.indexOf('time=') === -1);
|
var lines = stdout.trim().split('\n').filter(line => line.indexOf('time=') === -1);
|
||||||
var machines = {};
|
var machines = {};
|
||||||
|
|
@ -41,54 +39,50 @@ var DockerMachine = {
|
||||||
};
|
};
|
||||||
machines[machine.name] = machine;
|
machines[machine.name] = machine;
|
||||||
});
|
});
|
||||||
if (machines[NAME]) {
|
if (machines[machineName]) {
|
||||||
return Promise.resolve(machines[NAME]);
|
return Promise.resolve(machines[machineName]);
|
||||||
} else {
|
} else {
|
||||||
return Promise.reject(new Error('Machine does not exist.'));
|
return Promise.reject(new Error('Machine does not exist.'));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
exists: function () {
|
exists: function (machineName = this.name()) {
|
||||||
return this.info().then(() => {
|
return this.info(machineName).then(() => {
|
||||||
return true;
|
return true;
|
||||||
}).catch(() => {
|
}).catch(() => {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
create: function () {
|
create: function (machineName = this.name()) {
|
||||||
if (util.isWindows()) {
|
return util.exec([this.command(), '-D', 'create', '-d', 'virtualbox', '--virtualbox-memory', '2048', machineName]);
|
||||||
return util.exec([this.command(), '-D', 'create', '-d', 'virtualbox', '--virtualbox-memory', '2048', NAME]);
|
|
||||||
} else {
|
|
||||||
return util.exec([this.command(), '-D', 'create', '-d', 'virtualbox' ,'--virtualbox-boot2docker-url', path.join(process.env.RESOURCES_PATH, 'boot2docker.iso'), '--virtualbox-memory', '2048', NAME]);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
start: function () {
|
start: function (machineName = this.name()) {
|
||||||
return util.exec([this.command(), '-D', 'start', NAME]);
|
return util.exec([this.command(), '-D', 'start', machineName]);
|
||||||
},
|
},
|
||||||
stop: function () {
|
stop: function (machineName = this.name()) {
|
||||||
return util.exec([this.command(), 'stop', NAME]);
|
return util.exec([this.command(), 'stop', machineName]);
|
||||||
},
|
},
|
||||||
upgrade: function () {
|
upgrade: function (machineName = this.name()) {
|
||||||
return util.exec([this.command(), 'upgrade', NAME]);
|
return util.exec([this.command(), 'upgrade', machineName]);
|
||||||
},
|
},
|
||||||
rm: function () {
|
rm: function (machineName = this.name()) {
|
||||||
return util.exec([this.command(), 'rm', '-f', NAME]);
|
return util.exec([this.command(), 'rm', '-f', machineName]);
|
||||||
},
|
},
|
||||||
ip: function () {
|
ip: function (machineName = this.name()) {
|
||||||
return util.exec([this.command(), 'ip', NAME]).then(stdout => {
|
return util.exec([this.command(), 'ip', machineName]).then(stdout => {
|
||||||
return Promise.resolve(stdout.trim().replace('\n', ''));
|
return Promise.resolve(stdout.trim().replace('\n', ''));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
regenerateCerts: function () {
|
regenerateCerts: function (machineName = this.name()) {
|
||||||
return util.exec([this.command(), 'tls-regenerate-certs', '-f', NAME]);
|
return util.exec([this.command(), 'tls-regenerate-certs', '-f', machineName]);
|
||||||
},
|
},
|
||||||
state: function () {
|
state: function (machineName = this.name()) {
|
||||||
return this.info().then(info => {
|
return this.info(machineName).then(info => {
|
||||||
return info ? info.state : null;
|
return info ? info.state : null;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
disk: function () {
|
disk: function (machineName = this.name()) {
|
||||||
return util.exec([this.command(), 'ssh', NAME, 'df']).then(stdout => {
|
return util.exec([this.command(), 'ssh', machineName, 'df']).then(stdout => {
|
||||||
try {
|
try {
|
||||||
var lines = stdout.split('\n');
|
var lines = stdout.split('\n');
|
||||||
var dataline = _.find(lines, function (line) {
|
var dataline = _.find(lines, function (line) {
|
||||||
|
|
@ -111,8 +105,8 @@ var DockerMachine = {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
memory: function () {
|
memory: function (machineName = this.name()) {
|
||||||
return util.exec([this.command(), 'ssh', NAME, 'free -m']).then(stdout => {
|
return util.exec([this.command(), 'ssh', machineName, 'free -m']).then(stdout => {
|
||||||
try {
|
try {
|
||||||
var lines = stdout.split('\n');
|
var lines = stdout.split('\n');
|
||||||
var dataline = _.find(lines, function (line) {
|
var dataline = _.find(lines, function (line) {
|
||||||
|
|
@ -137,8 +131,8 @@ var DockerMachine = {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
stats: function () {
|
stats: function (machineName = this.name()) {
|
||||||
this.state().then(state => {
|
this.state(machineName).then(state => {
|
||||||
if (state === 'Stopped') {
|
if (state === 'Stopped') {
|
||||||
return Promise.resolve({state: state});
|
return Promise.resolve({state: state});
|
||||||
}
|
}
|
||||||
|
|
@ -152,10 +146,10 @@ var DockerMachine = {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
dockerTerminal: function (cmd) {
|
dockerTerminal: function (cmd, machineName = this.name()) {
|
||||||
if(util.isWindows()) {
|
if(util.isWindows()) {
|
||||||
cmd = cmd || '';
|
cmd = cmd || '';
|
||||||
this.info().then(machine => {
|
this.info(machineName).then(machine => {
|
||||||
util.exec('start powershell.exe ' + cmd,
|
util.exec('start powershell.exe ' + cmd,
|
||||||
{env: {
|
{env: {
|
||||||
'DOCKER_HOST' : machine.url,
|
'DOCKER_HOST' : machine.url,
|
||||||
|
|
@ -166,7 +160,7 @@ var DockerMachine = {
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
cmd = cmd || process.env.SHELL;
|
cmd = cmd || process.env.SHELL;
|
||||||
this.info().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([resources.terminal(), `DOCKER_HOST=${machine.url} DOCKER_CERT_PATH=${path.join(util.home(), '.docker/machine/machines/' + machine.name)} DOCKER_TLS_VERIFY=1 ${cmd}`]).then(() => {});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -120,9 +120,9 @@ export default {
|
||||||
},
|
},
|
||||||
|
|
||||||
fetchContainer (id) {
|
fetchContainer (id) {
|
||||||
this.client.getContainer(id).inspect((error, container) => {
|
this.client.getContainer(id).inspect((error, container) => {
|
||||||
if (error) {
|
if (error) {
|
||||||
containerServerActions.error({name: id, error});
|
containerServerActions.error({name: id, error});
|
||||||
} else {
|
} else {
|
||||||
container.Name = container.Name.replace('/', '');
|
container.Name = container.Name.replace('/', '');
|
||||||
containerServerActions.updated({container});
|
containerServerActions.updated({container});
|
||||||
|
|
@ -135,26 +135,23 @@ export default {
|
||||||
if (err) {
|
if (err) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
async.map(containers, (container, callback) => {
|
||||||
let modifiedContainers = _.map(containers, container => {
|
this.client.getContainer(container.Id).inspect((error, container) => {
|
||||||
container.Name = container.Names[0].replace('/', '');
|
if (error) {
|
||||||
delete container.Names;
|
callback(null, null);
|
||||||
|
return;
|
||||||
// HACK: fill in some data based on simple list data
|
}
|
||||||
container.State = {};
|
container.Name = container.Name.replace('/', '');
|
||||||
container.Config = {
|
callback(null, container);
|
||||||
Image: container.Image
|
});
|
||||||
};
|
}, (err, containers) => {
|
||||||
if (container.Status.indexOf('Exited') !== -1) {
|
containers = containers.filter(c => c !== null);
|
||||||
container.State.Stopped = true;
|
if (err) {
|
||||||
} else if (container.Status.indexOf('Paused') !== -1) {
|
// TODO: add a global error handler for this
|
||||||
container.State.Stopped = true;
|
return;
|
||||||
} else if (container.Status.indexOf('Up') !== -1) {
|
|
||||||
container.State.Running = true;
|
|
||||||
}
|
}
|
||||||
return container;
|
containerServerActions.allUpdated({containers: _.indexBy(containers.concat(_.values(this.placeholders)), 'Name')});
|
||||||
});
|
});
|
||||||
containerServerActions.allUpdated({containers: _.indexBy(modifiedContainers.concat(_.values(this.placeholders)), 'Name')});
|
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -223,6 +220,11 @@ export default {
|
||||||
existingData.Env = existingData.Config.Env;
|
existingData.Env = existingData.Config.Env;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((!existingData.Tty || !existingData.OpenStdin) && existingData.Config && (existingData.Config.Tty || existingData.Config.OpenStdin)) {
|
||||||
|
existingData.Tty = existingData.Config.Tty;
|
||||||
|
existingData.OpenStdin = existingData.Config.OpenStdin;
|
||||||
|
}
|
||||||
|
|
||||||
var fullData = _.extend(existingData, data);
|
var fullData = _.extend(existingData, data);
|
||||||
this.createContainer(name, fullData);
|
this.createContainer(name, fullData);
|
||||||
});
|
});
|
||||||
|
|
@ -305,12 +307,12 @@ export default {
|
||||||
|
|
||||||
let container = this.client.getContainer(name);
|
let container = this.client.getContainer(name);
|
||||||
container.unpause(function () {
|
container.unpause(function () {
|
||||||
container.kill(function (error) {
|
container.kill(function () {
|
||||||
if (error) {
|
container.remove(function (error) {
|
||||||
containerServerActions.error({name, error});
|
if (error) {
|
||||||
return;
|
containerServerActions.error({name, error});
|
||||||
}
|
return;
|
||||||
container.remove(function () {
|
}
|
||||||
containerServerActions.destroyed({id: name});
|
containerServerActions.destroyed({id: name});
|
||||||
var volumePath = path.join(util.home(), 'Kitematic', name);
|
var volumePath = path.join(util.home(), 'Kitematic', name);
|
||||||
if (fs.existsSync(volumePath)) {
|
if (fs.existsSync(volumePath)) {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var request = require('request');
|
import request from 'request';
|
||||||
var accountServerActions = require('../actions/AccountServerActions');
|
import accountServerActions from '../actions/AccountServerActions';
|
||||||
var metrics = require('./MetricsUtil');
|
import metrics from './MetricsUtil';
|
||||||
|
|
||||||
let HUB2_ENDPOINT = process.env.HUB2_ENDPOINT || 'https://hub.docker.com/v2';
|
let HUB2_ENDPOINT = process.env.HUB2_ENDPOINT || 'https://hub.docker.com/v2';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
var assign = require('object-assign');
|
import assign from 'object-assign';
|
||||||
var Mixpanel = require('mixpanel');
|
import Mixpanel from 'mixpanel';
|
||||||
var uuid = require('node-uuid');
|
import uuid from 'node-uuid';
|
||||||
var fs = require('fs');
|
import fs from 'fs';
|
||||||
var path = require('path');
|
import path from 'path';
|
||||||
var util = require('./Util');
|
import util from './Util';
|
||||||
var os = require('os');
|
import os from 'os';
|
||||||
var osxRelease = require('osx-release');
|
import osxRelease from 'osx-release';
|
||||||
var settings;
|
var settings;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var request = require('request');
|
import request from 'request';
|
||||||
var async = require('async');
|
import async from 'async';
|
||||||
var util = require('../utils/Util');
|
import util from '../utils/Util';
|
||||||
var hubUtil = require('../utils/HubUtil');
|
import hubUtil from '../utils/HubUtil';
|
||||||
var repositoryServerActions = require('../actions/RepositoryServerActions');
|
import repositoryServerActions from '../actions/RepositoryServerActions';
|
||||||
var tagServerActions = require('../actions/TagServerActions');
|
import tagServerActions from '../actions/TagServerActions';
|
||||||
|
|
||||||
let REGHUB2_ENDPOINT = process.env.REGHUB2_ENDPOINT || 'https://registry.hub.docker.com/v2';
|
let REGHUB2_ENDPOINT = process.env.REGHUB2_ENDPOINT || 'https://registry.hub.docker.com/v2';
|
||||||
let searchReq = null;
|
let searchReq = null;
|
||||||
|
|
@ -103,11 +103,11 @@ module.exports = {
|
||||||
}, (error, response, body) => {
|
}, (error, response, body) => {
|
||||||
if (response.statusCode === 200) {
|
if (response.statusCode === 200) {
|
||||||
let data = JSON.parse(body);
|
let data = JSON.parse(body);
|
||||||
tagServerActions.tagsUpdated({repo, tags: data});
|
tagServerActions.tagsUpdated({repo, tags: data.results || []});
|
||||||
if (callback) { callback(null, data); }
|
if (callback) { callback(null, data.results || []); }
|
||||||
} else if (error || response.statusCode === 401) {
|
} else {
|
||||||
repositoryServerActions.error({repo});
|
repositoryServerActions.error({repo});
|
||||||
if (callback) { callback(new Error('Failed to fetch repos')); }
|
if (callback) { callback(new Error('Failed to fetch tags for repo')); }
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
var util = require('./Util');
|
import util from './Util';
|
||||||
var path = require('path');
|
import path from 'path';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
resourceDir: function () {
|
resourceDir: function () {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,12 @@
|
||||||
var _ = require('underscore');
|
import _ from 'underscore';
|
||||||
var crypto = require('crypto');
|
import crypto from 'crypto';
|
||||||
var fs = require('fs');
|
import fs from 'fs';
|
||||||
var path = require('path');
|
import path from 'path';
|
||||||
var request = require('request');
|
import request from 'request';
|
||||||
var progress = require('request-progress');
|
import progress from 'request-progress';
|
||||||
var Promise = require('bluebird');
|
import Promise from 'bluebird';
|
||||||
var util = require('./Util');
|
import util from './Util';
|
||||||
var resources = require('./ResourcesUtil');
|
import resources from './ResourcesUtil';
|
||||||
var virtualBox = require ('./VirtualBoxUtil');
|
var virtualBox = require ('./VirtualBoxUtil');
|
||||||
|
|
||||||
var SetupUtil = {
|
var SetupUtil = {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
var util = require('./Util');
|
import util from './Util';
|
||||||
var parseUri = require('parseUri');
|
import parseUri from 'parseUri';
|
||||||
var containerServerActions = require('../actions/ContainerServerActions');
|
import containerServerActions from '../actions/ContainerServerActions';
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
TYPE_WHITELIST: ['repository'],
|
TYPE_WHITELIST: ['repository'],
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,10 @@
|
||||||
var exec = require('exec');
|
import exec from 'exec';
|
||||||
var child_process = require('child_process');
|
import child_process from 'child_process';
|
||||||
var Promise = require('bluebird');
|
import Promise from 'bluebird';
|
||||||
var fs = require('fs');
|
import fs from 'fs';
|
||||||
var path = require('path');
|
import path from 'path';
|
||||||
var crypto = require('crypto');
|
import crypto from 'crypto';
|
||||||
var remote = require('remote');
|
import remote from 'remote';
|
||||||
var app = remote.require('app');
|
var app = remote.require('app');
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
|
@ -71,7 +71,8 @@ module.exports = {
|
||||||
}
|
}
|
||||||
return str.replace(/-----BEGIN CERTIFICATE-----.*-----END CERTIFICATE-----/mg, '<redacted>')
|
return str.replace(/-----BEGIN CERTIFICATE-----.*-----END CERTIFICATE-----/mg, '<redacted>')
|
||||||
.replace(/-----BEGIN RSA PRIVATE KEY-----.*-----END RSA PRIVATE KEY-----/mg, '<redacted>')
|
.replace(/-----BEGIN RSA PRIVATE KEY-----.*-----END RSA PRIVATE KEY-----/mg, '<redacted>')
|
||||||
.replace(/\/Users\/[^\/]*\//mg, '/Users/<redacted>/');
|
.replace(/\/Users\/[^\/]*\//mg, '/Users/<redacted>/')
|
||||||
|
.replace(/\\Users\\[^\/]*\\/mg, '\\Users\\<redacted>\\');
|
||||||
},
|
},
|
||||||
packagejson: function () {
|
packagejson: function () {
|
||||||
return JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
|
return JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'package.json'), 'utf8'));
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
var fs = require('fs');
|
import fs from 'fs';
|
||||||
var util = require('./Util');
|
import util from './Util';
|
||||||
var Promise = require('bluebird');
|
import Promise from 'bluebird';
|
||||||
|
|
||||||
var VirtualBox = {
|
var VirtualBox = {
|
||||||
command: function () {
|
command: function () {
|
||||||
if(util.isWindows()) {
|
if(util.isWindows()) {
|
||||||
return 'C:\\Program Files\\Oracle\\VirtualBox\\VBoxManage.exe';
|
return 'C:\\Program Files\\Oracle\\VirtualBox\\VBoxManage.exe';
|
||||||
} else {
|
} else {
|
||||||
return '/usr/bin/VBoxManage';
|
return '/Applications/VirtualBox.app/Contents/MacOS/VBoxManage';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
filename: function () {
|
filename: function () {
|
||||||
|
|
@ -23,7 +23,7 @@ var VirtualBox = {
|
||||||
if(util.isWindows()) {
|
if(util.isWindows()) {
|
||||||
return fs.existsSync('C:\\Program Files\\Oracle\\VirtualBox\\VBoxManage.exe') && fs.existsSync('C:\\Program Files\\Oracle\\VirtualBox\\VirtualBox.exe');
|
return fs.existsSync('C:\\Program Files\\Oracle\\VirtualBox\\VBoxManage.exe') && fs.existsSync('C:\\Program Files\\Oracle\\VirtualBox\\VirtualBox.exe');
|
||||||
} else {
|
} else {
|
||||||
return fs.existsSync('/usr/bin/VBoxManage') && fs.existsSync('/Applications/VirtualBox.app') && fs.existsSync('/Applications/VirtualBox.app/Contents/MacOS/VBoxManage');
|
return fs.existsSync('/Applications/VirtualBox.app') && fs.existsSync('/Applications/VirtualBox.app/Contents/MacOS/VBoxManage');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
active: function () {
|
active: function () {
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,10 @@
|
||||||
var app = require('remote').require('app');
|
import remote from 'remote';
|
||||||
var fs = require('fs');
|
var app = remote.require('app');
|
||||||
var util = require('./Util');
|
import fs from 'fs';
|
||||||
var path = require('path');
|
import util from './Util';
|
||||||
var bugsnag = require('bugsnag-js');
|
import path from 'path';
|
||||||
var metrics = require('./MetricsUtil');
|
import bugsnag from 'bugsnag-js';
|
||||||
|
import metrics from './MetricsUtil';
|
||||||
|
|
||||||
var WebUtil = {
|
var WebUtil = {
|
||||||
addWindowSizeSaving: function () {
|
addWindowSizeSaving: function () {
|
||||||
|
|
|
||||||
|
|
@ -284,7 +284,7 @@
|
||||||
border-bottom-left-radius: @border-radius;
|
border-bottom-left-radius: @border-radius;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
box-shadow: inset 0px 0px 0px 1px rgba(0,0,0,0.2);
|
box-shadow: inset 0px 0px 0px 1px rgba(0,0,0,0.1);
|
||||||
img {
|
img {
|
||||||
width: 35px;
|
width: 35px;
|
||||||
height: auto;
|
height: auto;
|
||||||
|
|
@ -293,7 +293,7 @@
|
||||||
}
|
}
|
||||||
.card {
|
.card {
|
||||||
position: relative;
|
position: relative;
|
||||||
border: 1px solid darken(@gray-lightest, 5%);
|
border: 1px solid darken(@gray-lightest, 0%);
|
||||||
border-left: 0;
|
border-left: 0;
|
||||||
border-top-right-radius: @border-radius;
|
border-top-right-radius: @border-radius;
|
||||||
border-bottom-right-radius: @border-radius;
|
border-bottom-right-radius: @border-radius;
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
|
||||||
.preferences-content {
|
.preferences-content, .about-content {
|
||||||
flex: 1 auto;
|
flex: 1 auto;
|
||||||
margin-top: 45px;
|
margin-top: 45px;
|
||||||
padding: 50px;
|
padding: 50px;
|
||||||
|
|
@ -37,4 +37,34 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.about-content {
|
||||||
|
margin-top: 0px;
|
||||||
|
height: 100%;
|
||||||
|
overflow: auto;
|
||||||
|
.items {
|
||||||
|
display: flex;
|
||||||
|
.item {
|
||||||
|
flex: 1 auto;
|
||||||
|
margin-right: 1rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h3 {
|
||||||
|
color: @gray-normal;
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 18px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
height: 100px;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
h4 {
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
color: @gray-light;
|
||||||
|
font-size: 1.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -197,6 +197,7 @@
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
max-height: 400px;
|
max-height: 400px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
-webkit-user-select: initial;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.setup-actions {
|
.setup-actions {
|
||||||
|
|
|
||||||