mirror of https://github.com/docker/docs.git
Fixing outstanding installer & port mapping bugs
This commit is contained in:
parent
d1c6928321
commit
0357ce7b0e
5
index.js
5
index.js
|
@ -124,7 +124,10 @@ app.on('ready', function() {
|
||||||
width: 800,
|
width: 800,
|
||||||
height: 578,
|
height: 578,
|
||||||
resizable: false,
|
resizable: false,
|
||||||
frame: false
|
frame: false,
|
||||||
|
'web-preferences': {
|
||||||
|
'web-security': false
|
||||||
|
}
|
||||||
};
|
};
|
||||||
mainWindow = new BrowserWindow(windowOptions);
|
mainWindow = new BrowserWindow(windowOptions);
|
||||||
mainWindow.hide();
|
mainWindow.hide();
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
var exec = require('exec');
|
var exec = require('exec');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
var async = require('async');
|
||||||
var Convert = require('ansi-to-html');
|
var Convert = require('ansi-to-html');
|
||||||
var convert = new Convert();
|
var convert = new Convert();
|
||||||
|
|
||||||
|
@ -8,9 +9,10 @@ AppUtil = {};
|
||||||
|
|
||||||
AppUtil.run = function (app, callback) {
|
AppUtil.run = function (app, callback) {
|
||||||
var image = Images.findOne({_id: app.imageId});
|
var image = Images.findOne({_id: app.imageId});
|
||||||
// Delete old container if one already exists
|
Apps.update(app._id, {$set: {
|
||||||
|
status: 'STARTING'
|
||||||
|
}});
|
||||||
Docker.removeContainer(app.name, function (err) {
|
Docker.removeContainer(app.name, function (err) {
|
||||||
if (err) { callback(err); }
|
|
||||||
Docker.runContainer(app, image, function (err, container) {
|
Docker.runContainer(app, image, function (err, container) {
|
||||||
if (err) { callback(err); }
|
if (err) { callback(err); }
|
||||||
Docker.getContainerData(container.id, function (err, data) {
|
Docker.getContainerData(container.id, function (err, data) {
|
||||||
|
@ -26,22 +28,6 @@ AppUtil.run = function (app, callback) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
AppUtil.restartHelper = function (app) {
|
|
||||||
if (app.docker && app.docker.Id) {
|
|
||||||
var container = Docker.client().getContainer(app.docker.Id);
|
|
||||||
container.restart(function (err) {
|
|
||||||
if (err) { console.error(err); }
|
|
||||||
Docker.getContainerData(app.docker.Id, function (err, data) {
|
|
||||||
if (err) { console.error(err); }
|
|
||||||
Apps.update(app._id, {$set: {
|
|
||||||
status: 'READY',
|
|
||||||
docker: data
|
|
||||||
}});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
AppUtil.start = function (appId) {
|
AppUtil.start = function (appId) {
|
||||||
var app = Apps.findOne(appId);
|
var app = Apps.findOne(appId);
|
||||||
if (app && app.docker) {
|
if (app && app.docker) {
|
||||||
|
@ -78,16 +64,6 @@ AppUtil.stop = function (appId) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
AppUtil.restart = function (appId) {
|
|
||||||
var app = Apps.findOne(appId);
|
|
||||||
if (app && app.docker) {
|
|
||||||
Apps.update(app._id, {$set: {
|
|
||||||
status: 'STARTING'
|
|
||||||
}});
|
|
||||||
AppUtil.restartHelper(app);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
AppUtil.remove = function (appId) {
|
AppUtil.remove = function (appId) {
|
||||||
var app = Apps.findOne(appId);
|
var app = Apps.findOne(appId);
|
||||||
Apps.remove({_id: appId});
|
Apps.remove({_id: appId});
|
||||||
|
@ -153,35 +129,14 @@ AppUtil.recover = function () {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
AppUtil.sync = function () {
|
AppUtil.sync = function (callback) {
|
||||||
Docker.listContainers(function (err, containers) {
|
Docker.listContainers(function (err, containers) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
callback(err);
|
||||||
} else {
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var apps = Apps.find({}).fetch();
|
var apps = Apps.find({}).fetch();
|
||||||
_.each(apps, function (app) {
|
|
||||||
var app = Apps.findOne(app._id);
|
|
||||||
if (app && app.docker && app.docker.Id) {
|
|
||||||
var duplicateApps = Apps.find({'docker.Id': app.docker.Id, _id: {$ne: app._id}}).fetch();
|
|
||||||
_.each(duplicateApps, function (duplicateApp) {
|
|
||||||
Apps.remove(duplicateApp._id);
|
|
||||||
});
|
|
||||||
Docker.getContainerData(app.docker.Id, function (err, data) {
|
|
||||||
var status = 'STARTING';
|
|
||||||
if (data && data.State && data.State.Running) {
|
|
||||||
status = 'READY';
|
|
||||||
} else if (data && data.State && !data.State.Running) {
|
|
||||||
status = 'ERROR';
|
|
||||||
}
|
|
||||||
Apps.update(app._id, {
|
|
||||||
$set: {
|
|
||||||
docker: data,
|
|
||||||
status: status
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var dockerIds = _.map(apps, function (app) {
|
var dockerIds = _.map(apps, function (app) {
|
||||||
if (app.docker && app.docker.Id) {
|
if (app.docker && app.docker.Id) {
|
||||||
return app.docker.Id;
|
return app.docker.Id;
|
||||||
|
@ -235,12 +190,42 @@ AppUtil.sync = function () {
|
||||||
path: appPath,
|
path: appPath,
|
||||||
logs: [],
|
logs: [],
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
volumesEnabled: true
|
|
||||||
};
|
};
|
||||||
|
if (container.HostConfig.Binds && container.HostConfig.Binds.length) {
|
||||||
|
appObj.volumesEnabled = true;
|
||||||
|
} else {
|
||||||
|
appObj.volumesEnabled = false;
|
||||||
|
}
|
||||||
console.log(appObj);
|
console.log(appObj);
|
||||||
Apps.insert(appObj);
|
Apps.insert(appObj);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async.each(apps, function (app, callback) {
|
||||||
|
if (app && app.docker && app.docker.Id) {
|
||||||
|
var duplicateApps = Apps.find({'docker.Id': app.docker.Id, _id: {$ne: app._id}}).fetch();
|
||||||
|
_.each(duplicateApps, function (duplicateApp) {
|
||||||
|
Apps.remove(duplicateApp._id);
|
||||||
|
});
|
||||||
|
Docker.getContainerData(app.docker.Id, function (err, data) {
|
||||||
|
if (err) {callback(err); return;}
|
||||||
|
var status = 'STARTING';
|
||||||
|
if (data && data.State && data.State.Running) {
|
||||||
|
status = 'READY';
|
||||||
|
} else if (data && data.State && !data.State.Running) {
|
||||||
|
status = 'ERROR';
|
||||||
|
}
|
||||||
|
Apps.update(app._id, {
|
||||||
|
$set: {
|
||||||
|
docker: data,
|
||||||
|
status: status
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, function (err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -2,11 +2,12 @@ var exec = require('exec');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
var async = require('async');
|
||||||
|
var pkginfo = require('pkginfo')(module);
|
||||||
|
|
||||||
|
|
||||||
Boot2Docker = {};
|
Boot2Docker = {};
|
||||||
|
Boot2Docker.VERSION = module.exports['boot2docker-version'];
|
||||||
Boot2Docker.REQUIRED_IP = '192.168.60.103';
|
|
||||||
Boot2Docker.VERSION = '1.3.1';
|
|
||||||
|
|
||||||
Boot2Docker.command = function () {
|
Boot2Docker.command = function () {
|
||||||
return path.join(Util.getBinDir(), 'boot2docker-' + Boot2Docker.VERSION);
|
return path.join(Util.getBinDir(), 'boot2docker-' + Boot2Docker.VERSION);
|
||||||
|
@ -252,7 +253,43 @@ Boot2Docker.vmUpToDate = function (callback) {
|
||||||
if (err) {
|
if (err) {
|
||||||
callback(err); return;
|
callback(err); return;
|
||||||
}
|
}
|
||||||
var index = data.indexOf('Boot2Docker-v' + Boot2Docker.VERSION);
|
var match = data.match(/Boot2Docker-v(\d+\.\d+\.\d+)/);
|
||||||
callback(null, index !== -1);
|
if (!match) {
|
||||||
});
|
callback('Could not parse boot2docker iso version');
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
callback (null, Util.compareVersions(match[1], Boot2Docker.VERSION) < 0);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Boot2Docker.status = function (callback) {
|
||||||
|
this.exec('status', function (stderr, stdout, code) {
|
||||||
|
if (code) {callback(stderr); return;}
|
||||||
|
callback(null, stdout.trim());
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Boot2Docker.portAvailable = function (port, protocol, callback) {
|
||||||
|
this.exec('ssh netstat -lntu | grep LISTEN | grep ' + protocol + ' | grep -c ":::' + port + '\\s"', function (stdout, stderr, code) {
|
||||||
|
if (stderr.trim() === '0') {
|
||||||
|
callback(true);
|
||||||
|
} else {
|
||||||
|
callback(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
Boot2Docker.waitWhileStatus = function (status, callback) {
|
||||||
|
var current = status;
|
||||||
|
async.whilst(function () {
|
||||||
|
return current === status;
|
||||||
|
}, function (innerCallback) {
|
||||||
|
Boot2Docker.status(function (err, vmStatus) {
|
||||||
|
if (err) {innerCallback(err); return;}
|
||||||
|
current = vmStatus.trim();
|
||||||
|
innerCallback();
|
||||||
|
});
|
||||||
|
}, function (err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
};
|
|
@ -95,13 +95,23 @@ Docker.runContainer = function (app, image, callback) {
|
||||||
var builtStr = key + '=' + app.config[key];
|
var builtStr = key + '=' + app.config[key];
|
||||||
envParam.push(builtStr);
|
envParam.push(builtStr);
|
||||||
});
|
});
|
||||||
Docker.client().createContainer({
|
|
||||||
|
var containerOpts = {
|
||||||
Image: image.docker.Id,
|
Image: image.docker.Id,
|
||||||
Tty: false,
|
Tty: false,
|
||||||
Env: envParam,
|
Env: envParam,
|
||||||
Hostname: app.name,
|
Hostname: app.name,
|
||||||
name: app.name
|
name: app.name
|
||||||
}, function (err, container) {
|
};
|
||||||
|
|
||||||
|
|
||||||
|
if (app.docker && app.docker.NetworkSettings.Ports) {
|
||||||
|
containerOpts.ExposedPorts = app.docker.NetworkSettings.Ports;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(containerOpts);
|
||||||
|
|
||||||
|
Docker.client().createContainer(containerOpts, function (err, container) {
|
||||||
if (err) { callback(err, null); return; }
|
if (err) { callback(err, null); return; }
|
||||||
console.log('Created container: ' + container.id);
|
console.log('Created container: ' + container.id);
|
||||||
// Bind volumes
|
// Bind volumes
|
||||||
|
@ -111,11 +121,19 @@ Docker.runContainer = function (app, image, callback) {
|
||||||
binds.push([Util.getHomePath(), 'Kitematic', app.name, vol.Path].join('/') + ':' + vol.Path);
|
binds.push([Util.getHomePath(), 'Kitematic', app.name, vol.Path].join('/') + ':' + vol.Path);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
// Start the container
|
|
||||||
container.start({
|
var startOpts = {
|
||||||
PublishAllPorts: true,
|
|
||||||
Binds: binds
|
Binds: binds
|
||||||
}, function (err) {
|
};
|
||||||
|
|
||||||
|
if (app.docker && app.docker.NetworkSettings.Ports) {
|
||||||
|
startOpts.PortBindings = app.docker.NetworkSettings.Ports;
|
||||||
|
} else {
|
||||||
|
startOpts.PublishAllPorts = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(startOpts);
|
||||||
|
container.start(startOpts, function (err) {
|
||||||
if (err) { callback(err, null); return; }
|
if (err) { callback(err, null); return; }
|
||||||
console.log('Started container: ' + container.id);
|
console.log('Started container: ' + container.id);
|
||||||
callback(null, container);
|
callback(null, container);
|
||||||
|
|
|
@ -2,11 +2,11 @@ FormSchema = {
|
||||||
|
|
||||||
formCreateApp: {
|
formCreateApp: {
|
||||||
name: {
|
name: {
|
||||||
label: 'app name',
|
label: 'container name',
|
||||||
required: true,
|
required: true,
|
||||||
transforms: ['clean', 'slugify'],
|
transforms: ['clean', 'slugify'],
|
||||||
messages: {
|
messages: {
|
||||||
'uniqueAppName': "This app name is already being used."
|
'uniqueAppName': "This container name is already being used."
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
uniqueAppName: true
|
uniqueAppName: true
|
||||||
|
|
|
@ -3,6 +3,7 @@ var convert = new Convert();
|
||||||
var exec = require('exec');
|
var exec = require('exec');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
|
var async = require('async');
|
||||||
|
|
||||||
ImageUtil = {};
|
ImageUtil = {};
|
||||||
|
|
||||||
|
@ -239,55 +240,34 @@ ImageUtil.remove = function (imageId) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ImageUtil.sync = function () {
|
ImageUtil.sync = function (callback) {
|
||||||
Docker.listImages(function (err, dockerImages) {
|
Docker.listImages(function (err, dockerImages) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
} else {
|
return;
|
||||||
|
}
|
||||||
var images = Images.find({}).fetch();
|
var images = Images.find({}).fetch();
|
||||||
_.each(images, function (image) {
|
|
||||||
var image = Images.findOne(image._id);
|
// Delete missing GUI images
|
||||||
if (image && image.docker && image.docker.Id) {
|
var kitematicIds = _.map(images, function (image) {
|
||||||
var duplicateImages = Images.find({'docker.Id': image.docker.Id, _id: {$ne: image._id}}).fetch();
|
|
||||||
_.each(duplicateImages, function (duplicateImage) {
|
|
||||||
Images.remove(duplicateImage._id);
|
|
||||||
});
|
|
||||||
var imageData = _.find(dockerImages, function (dockerImage) {
|
|
||||||
return dockerImage.Id === image.docker.Id;
|
|
||||||
});
|
|
||||||
if (imageData && imageData.RepoTags) {
|
|
||||||
Images.update(image._id, {
|
|
||||||
$set: {
|
|
||||||
tags: imageData.RepoTags
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Docker.getImageData(image.docker.Id, function (err, data) {
|
|
||||||
Images.update(image._id, {
|
|
||||||
$set: {
|
|
||||||
docker: data
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var dockerIds = _.map(images, function (image) {
|
|
||||||
if (image.docker && image.docker.Id) {
|
if (image.docker && image.docker.Id) {
|
||||||
return image.docker.Id;
|
return image.docker.Id;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
var imageIds = _.map(dockerImages, function (image) {
|
var daemonIds = _.map(daemonIds, function (image) {
|
||||||
return image.Id;
|
return image.Id;
|
||||||
});
|
});
|
||||||
var diffImages = _.difference(dockerIds, imageIds);
|
var diffImages = _.difference(kitematicIds, daemonIds);
|
||||||
_.each(diffImages, function (imageId) {
|
_.each(diffImages, function (imageId) {
|
||||||
var image = Images.findOne({'docker.Id': imageId});
|
var image = Images.findOne({'docker.Id': imageId});
|
||||||
if (image && image.status !== 'BUILDING') {
|
if (image && image.status !== 'BUILDING') {
|
||||||
ImageUtil.remove(image._id);
|
Images.remove(image._id);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Add missing Daemon images
|
||||||
var diffDockerImages = _.reject(dockerImages, function (image) {
|
var diffDockerImages = _.reject(dockerImages, function (image) {
|
||||||
return _.contains(dockerIds, image.Id);
|
return _.contains(kitematicIds, image.Id);
|
||||||
});
|
});
|
||||||
_.each(diffDockerImages, function (image) {
|
_.each(diffDockerImages, function (image) {
|
||||||
var repoTag = _.first(image.RepoTags);
|
var repoTag = _.first(image.RepoTags);
|
||||||
|
@ -312,6 +292,36 @@ ImageUtil.sync = function () {
|
||||||
Images.insert(imageObj);
|
Images.insert(imageObj);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async.each(images, function (image, callback) {
|
||||||
|
var image = Images.findOne(image._id);
|
||||||
|
if (image && image.docker && image.docker.Id) {
|
||||||
|
var duplicateImages = Images.find({'docker.Id': image.docker.Id, _id: {$ne: image._id}}).fetch();
|
||||||
|
_.each(duplicateImages, function (duplicateImage) {
|
||||||
|
Images.remove(duplicateImage._id);
|
||||||
|
});
|
||||||
|
var imageData = _.find(dockerImages, function (dockerImage) {
|
||||||
|
return dockerImage.Id === image.docker.Id;
|
||||||
|
});
|
||||||
|
if (imageData && imageData.RepoTags) {
|
||||||
|
Images.update(image._id, {
|
||||||
|
$set: {
|
||||||
|
tags: imageData.RepoTags
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
Docker.getImageData(image.docker.Id, function (err, data) {
|
||||||
|
if (err) {callback(err); return;}
|
||||||
|
Images.update(image._id, {
|
||||||
|
$set: {
|
||||||
|
docker: data
|
||||||
|
}
|
||||||
|
});
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, function (err) {
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
|
@ -52,7 +52,7 @@ Router.map(function () {
|
||||||
}
|
}
|
||||||
Session.set('onIntro', false);
|
Session.set('onIntro', false);
|
||||||
startUpdatingBoot2DockerUtilization();
|
startUpdatingBoot2DockerUtilization();
|
||||||
// startSyncingAppState();
|
startSyncingAppState();
|
||||||
Router.go('dashboard_apps');
|
Router.go('dashboard_apps');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -67,6 +67,17 @@ Setup.steps = [
|
||||||
},
|
},
|
||||||
message: 'Downloading VirtualBox...'
|
message: 'Downloading VirtualBox...'
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
run: function (callback) {
|
||||||
|
VirtualBox.shutdownVM('kitematic-vm', function (err, removed) {
|
||||||
|
if (err) {
|
||||||
|
console.log(err);
|
||||||
|
}
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
message: 'Cleaning up existing Docker VM...'
|
||||||
|
},
|
||||||
|
|
||||||
// Initialize Boot2Docker if necessary.
|
// Initialize Boot2Docker if necessary.
|
||||||
{
|
{
|
||||||
|
@ -74,10 +85,6 @@ Setup.steps = [
|
||||||
Boot2Docker.exists(function (err, exists) {
|
Boot2Docker.exists(function (err, exists) {
|
||||||
if (err) { callback(err); return; }
|
if (err) { callback(err); return; }
|
||||||
if (!exists) {
|
if (!exists) {
|
||||||
var vmFilesPath = path.join(Util.getHomePath(), 'VirtualBox\ VMs', 'boot2docker-vm');
|
|
||||||
if (fs.existsSync(vmFilesPath)) {
|
|
||||||
Util.deleteFolder(vmFilesPath);
|
|
||||||
}
|
|
||||||
Boot2Docker.init(function (err) {
|
Boot2Docker.init(function (err) {
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
|
@ -105,9 +112,10 @@ Setup.steps = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
run: function (callback) {
|
run: function (callback) {
|
||||||
Boot2Docker.state(function (err, state) {
|
Boot2Docker.waitWhileStatus('saving', function (err) {
|
||||||
|
Boot2Docker.status(function (err, status) {
|
||||||
if (err) {callback(err); return;}
|
if (err) {callback(err); return;}
|
||||||
if (state !== 'running') {
|
if (status !== 'running') {
|
||||||
Boot2Docker.start(function (err) {
|
Boot2Docker.start(function (err) {
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
|
@ -115,6 +123,7 @@ Setup.steps = [
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
});
|
||||||
},
|
},
|
||||||
message: 'Starting the Docker VM...'
|
message: 'Starting the Docker VM...'
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var exec = require('exec');
|
var exec = require('exec');
|
||||||
var path = require('path');
|
var path = require('path');
|
||||||
|
var async = require('async');
|
||||||
|
|
||||||
VirtualBox = {};
|
VirtualBox = {};
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ VirtualBox.version = function (callback) {
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
VirtualBox.shutDownRunningVMs = function (callback) {
|
VirtualBox.saveRunningVMs = function (callback) {
|
||||||
if (!this.installed()) {
|
if (!this.installed()) {
|
||||||
callback('VirtualBox not installed.');
|
callback('VirtualBox not installed.');
|
||||||
return;
|
return;
|
||||||
|
@ -66,7 +67,7 @@ VirtualBox.shutDownRunningVMs = function (callback) {
|
||||||
};
|
};
|
||||||
|
|
||||||
VirtualBox.killAllProcesses = function (callback) {
|
VirtualBox.killAllProcesses = function (callback) {
|
||||||
this.shutDownRunningVMs(function (err) {
|
this.saveRunningVMs(function (err) {
|
||||||
if (err) {callback(err); return;}
|
if (err) {callback(err); return;}
|
||||||
exec('pkill VirtualBox', function (stderr, stdout, code) {
|
exec('pkill VirtualBox', function (stderr, stdout, code) {
|
||||||
if (code) {callback(stderr); return;}
|
if (code) {callback(stderr); return;}
|
||||||
|
@ -77,3 +78,41 @@ VirtualBox.killAllProcesses = function (callback) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
VirtualBox.vmState = function (name, callback) {
|
||||||
|
VirtualBox.exec('showvminfo ' + name + ' --machinereadable', function (stderr, stdout, code) {
|
||||||
|
if (code) { callback(stderr); return; }
|
||||||
|
var match = stdout.match(/VMState="(\w+)"/);
|
||||||
|
if (!match) {
|
||||||
|
callback('Could not parse VMState');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
callback(null, match[1]);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
VirtualBox.shutdownVM = function (name, callback) {
|
||||||
|
VirtualBox.vmState(name, function (err, state) {
|
||||||
|
// No VM found
|
||||||
|
if (err) { callback(null, false); return; }
|
||||||
|
VirtualBox.exec('controlvm ' + name + ' acpipowerbutton', function (stderr, stdout, code) {
|
||||||
|
if (code) { callback(stderr, false); return; }
|
||||||
|
var state = null;
|
||||||
|
|
||||||
|
async.until(function () {
|
||||||
|
return state === 'poweroff';
|
||||||
|
}, function (callback) {
|
||||||
|
VirtualBox.vmState(name, function (err, newState) {
|
||||||
|
if (err) { callback(err); return; }
|
||||||
|
state = newState;
|
||||||
|
setTimeout(callback, 250);
|
||||||
|
});
|
||||||
|
}, function (err) {
|
||||||
|
VirtualBox.exec('unregistervm ' + name + ' --delete', function (stderr, stdout, code) {
|
||||||
|
if (code) { callback(err); return; }
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
};
|
|
@ -100,10 +100,11 @@ startUpdatingBoot2DockerUtilization = function () {
|
||||||
};
|
};
|
||||||
|
|
||||||
startSyncingAppState = function () {
|
startSyncingAppState = function () {
|
||||||
ImageUtil.sync();
|
ImageUtil.sync(function (err) {
|
||||||
AppUtil.sync();
|
if (err) {console.log(err);}
|
||||||
Meteor.setTimeout(function () {
|
AppUtil.sync(function (err) {
|
||||||
ImageUtil.sync();
|
if (err) {console.log(err);}
|
||||||
AppUtil.sync();
|
Meteor.setTimeout(startSyncingAppState, 5000);
|
||||||
}, 5000);
|
});
|
||||||
|
});
|
||||||
};
|
};
|
|
@ -30,8 +30,11 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.ports {
|
.ports {
|
||||||
|
position: relative;
|
||||||
|
top: -2px;
|
||||||
.dropdown-menu {
|
.dropdown-menu {
|
||||||
min-width: 241px;
|
min-width: 241px;
|
||||||
|
padding: 10px 15px 3px;
|
||||||
}
|
}
|
||||||
.btn-group {
|
.btn-group {
|
||||||
top: -2px;
|
top: -2px;
|
||||||
|
@ -62,7 +65,6 @@
|
||||||
&.open + .tooltip {
|
&.open + .tooltip {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
position: relative;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -281,10 +283,18 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.form-env-vars {
|
||||||
|
label {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
font-size: 13px;
|
||||||
|
padding: 5px 9px;
|
||||||
|
}
|
||||||
.env-var-pair {
|
.env-var-pair {
|
||||||
.make-row();
|
.make-row();
|
||||||
margin-bottom: 0.2em;
|
margin-bottom: 0.2em;
|
||||||
font-size: 12px;
|
font-size: 13px;
|
||||||
.env-var-key {
|
.env-var-key {
|
||||||
.make-xs-column(5);
|
.make-xs-column(5);
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
|
@ -301,10 +311,10 @@
|
||||||
.make-xs-column(2);
|
.make-xs-column(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.app-ports {
|
.app-ports {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
padding: 10px 15px 3px;
|
|
||||||
min-width: 240px;
|
min-width: 240px;
|
||||||
li {
|
li {
|
||||||
padding-bottom: 7px;
|
padding-bottom: 7px;
|
||||||
|
|
|
@ -1,15 +1,6 @@
|
||||||
<template name="dashboardAppsPorts">
|
<template name="dashboardAppsPorts">
|
||||||
<div class="app-ports">
|
<div class="app-ports">
|
||||||
{{#each ports}}
|
{{#each ports}}
|
||||||
{{#if this.web}}
|
|
||||||
<li role="menuitem">
|
|
||||||
<span class="port-wrapper">Port {{this.port}}</span>
|
|
||||||
<span class="arrow-wrapper"></span>
|
|
||||||
<span class="open-button-wrapper">
|
|
||||||
<a href="{{this.url}}" onclick="trackLink('view container')" class="btn btn-action btn-xs btn-view-port">Open in Browser</a>
|
|
||||||
</span>
|
|
||||||
</li>
|
|
||||||
{{else}}
|
|
||||||
<li role="menuitem">
|
<li role="menuitem">
|
||||||
<span class="port-wrapper">Port {{this.port}}</span>
|
<span class="port-wrapper">Port {{this.port}}</span>
|
||||||
<span class="arrow-wrapper">
|
<span class="arrow-wrapper">
|
||||||
|
@ -17,7 +8,6 @@
|
||||||
</span>
|
</span>
|
||||||
<span class="host-address-wrapper">{{this.hostIp}}:{{this.hostPort}}</span>
|
<span class="host-address-wrapper">{{this.hostIp}}:{{this.hostPort}}</span>
|
||||||
</li>
|
</li>
|
||||||
{{/if}}
|
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
|
@ -1,4 +1,14 @@
|
||||||
<template name="dashboardAppsSettings">
|
<template name="dashboardAppsSettings">
|
||||||
|
<div class="section">
|
||||||
|
<div class="left-section">
|
||||||
|
<h4>Ports</h4>
|
||||||
|
</div>
|
||||||
|
<div class="right-section">
|
||||||
|
<ul class="list-unstyled">
|
||||||
|
{{> dashboardAppsPorts}}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="section">
|
<div class="section">
|
||||||
<div class="left-section">
|
<div class="left-section">
|
||||||
<h4>Environment Variables</h4>
|
<h4>Environment Variables</h4>
|
||||||
|
|
|
@ -45,7 +45,7 @@ Template.dashboardAppsSettings.events({
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var appId = this._id;
|
var appId = this._id;
|
||||||
dialog.showMessageBox({
|
dialog.showMessageBox({
|
||||||
message: 'Are you sure you want to delete this app?',
|
message: 'Are you sure you want to delete this container?',
|
||||||
buttons: ['Delete', 'Cancel']
|
buttons: ['Delete', 'Cancel']
|
||||||
}, function (index) {
|
}, function (index) {
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
</h5>
|
</h5>
|
||||||
<div class="options">
|
<div class="options">
|
||||||
{{#if $eq status 'READY'}}
|
{{#if $eq status 'READY'}}
|
||||||
|
{{#if ports}}
|
||||||
{{#if viewPort}}
|
{{#if viewPort}}
|
||||||
<div class="ports btn-group btn-icon" title="View" data-placement="bottom">
|
<div class="ports btn-group btn-icon" title="View" data-placement="bottom">
|
||||||
<a href="{{viewPort.url}}" onclick="trackLink('view container')" class="btn btn-action btn-xs btn-view btn-globe">
|
<a href="{{viewPort.url}}" onclick="trackLink('view container')" class="btn btn-action btn-xs btn-view btn-globe">
|
||||||
|
@ -50,10 +51,11 @@
|
||||||
</span>
|
</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
<a href="#" onclick="trackLink('open container folder')" class="btn-icon btn-folder" data-toggle="tooltip" data-placement="bottom" title="Volumes"><span class="typcn typcn-folder"></span></a>
|
<a href="#" onclick="trackLink('open container folder')" class="btn-icon btn-folder" data-toggle="tooltip" data-placement="bottom" title="Volumes"><span class="typcn typcn-folder"></span></a>
|
||||||
{{#if $eq status 'READY'}}
|
{{#if $eq status 'READY'}}
|
||||||
<a href="#" onclick="trackLink('terminal into container')" class="btn-icon btn-terminal" data-toggle="tooltip" data-placement="bottom" title="Terminal"><span class="typcn typcn-device-laptop"></span></a>
|
<a href="#" onclick="trackLink('terminal into container')" class="btn-icon btn-terminal" data-toggle="tooltip" data-placement="bottom" title="Terminal"><span class="typcn typcn-device-laptop"></span></a>
|
||||||
<a href="#" onclick="trackLink('stop container')" class="btn-icon btn-stop" data-toggle="tooltip" data-placement="bottom" title="Stop"><span class="typcn typcn-media-pause-outline"></span></a>
|
<a href="#" onclick="trackLink('stop container')" class="btn-icon btn-stop" data-toggle="tooltip" data-placement="bottom" title="Stop"><span class="typcn typcn-media-stop-outline"></span></a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if $eq status 'STOPPED'}}
|
{{#if $eq status 'STOPPED'}}
|
||||||
<a href="#" onclick="trackLink('start container')" class="btn-icon btn-start" data-toggle="tooltip" data-placement="bottom" title="Start"><span class="typcn typcn-media-play-outline"></span></a>
|
<a href="#" onclick="trackLink('start container')" class="btn-icon btn-start" data-toggle="tooltip" data-placement="bottom" title="Start"><span class="typcn typcn-media-play-outline"></span></a>
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
var remote = require('remote');
|
var remote = require('remote');
|
||||||
var dialog = remote.require('dialog');
|
var dialog = remote.require('dialog');
|
||||||
var exec = require('child_process').exec;
|
var exec = require('child_process').exec;
|
||||||
|
var path = require('path');
|
||||||
|
|
||||||
Template.dashboardSingleApp.rendered = function () {
|
Template.dashboardSingleApp.rendered = function () {
|
||||||
Meteor.setInterval(function () {
|
Meteor.setInterval(function () {
|
||||||
|
@ -48,22 +49,39 @@ Template.dashboardSingleApp.events({
|
||||||
},
|
},
|
||||||
'click .btn-restart': function (e) {
|
'click .btn-restart': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
AppUtil.restart(this._id);
|
AppUtil.run(this, function (err) {});
|
||||||
},
|
},
|
||||||
'click .btn-folder': function (e) {
|
'click .btn-folder': function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
var appId = this._id;
|
var app = this;
|
||||||
|
|
||||||
var app = Apps.findOne(appId);
|
|
||||||
if (!app) {
|
if (!app) {
|
||||||
throw new Error('Cannot find app with id: ' + appId);
|
throw new Error('Cannot find app with id: ' + app._id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (app.volumesEnabled) {
|
var openDirectory = function () {
|
||||||
exec('open ' + this.path, function (err) {
|
var appPath = path.join(Util.KITE_PATH, app.name);
|
||||||
|
if (app.docker.Volumes.length) {
|
||||||
|
if (app.docker.Volumes[0].Value.indexOf(path.join(Util.getHomePath(), 'Kitematic')) !== -1) {
|
||||||
|
exec('open ' + appPath, function (err) {
|
||||||
if (err) { throw err; }
|
if (err) { throw err; }
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
} else {
|
||||||
|
exec('open ' + app.docker.Volumes[0].Value, function (err) {
|
||||||
|
if (err) { throw err; }
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
exec('open ' + appPath, function (err) {
|
||||||
|
if (err) { throw err; }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (app.volumesEnabled) {
|
||||||
|
openDirectory();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dialog.showMessageBox({
|
dialog.showMessageBox({
|
||||||
|
@ -71,14 +89,12 @@ Template.dashboardSingleApp.events({
|
||||||
buttons: ['Enable Volumes', 'Cancel']
|
buttons: ['Enable Volumes', 'Cancel']
|
||||||
}, function (index) {
|
}, function (index) {
|
||||||
if (index === 0) {
|
if (index === 0) {
|
||||||
Apps.update(appId, {
|
Apps.update(app._id, {
|
||||||
$set: {volumesEnabled: true}
|
$set: {volumesEnabled: true}
|
||||||
});
|
});
|
||||||
AppUtil.run(Apps.findOne(appId), function (err) {
|
AppUtil.run(Apps.findOne(app._id), function (err) {
|
||||||
if (err) { throw err; }
|
if (err) { throw err; }
|
||||||
exec('open ' + this.path, function (err) {
|
openDirectory();
|
||||||
if (err) { throw err; }
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -31,7 +31,6 @@ Template.modalCreateApp.events({
|
||||||
imageId: cleaned.imageId,
|
imageId: cleaned.imageId,
|
||||||
status: 'STARTING',
|
status: 'STARTING',
|
||||||
config: {},
|
config: {},
|
||||||
path: appPath,
|
|
||||||
logs: [],
|
logs: [],
|
||||||
createdAt: new Date(),
|
createdAt: new Date(),
|
||||||
volumesEnabled: true
|
volumesEnabled: true
|
||||||
|
|
|
@ -59,7 +59,7 @@ Template.modalCreateImage.events({
|
||||||
if (imageObj.meta.logo) {
|
if (imageObj.meta.logo) {
|
||||||
Images.update(imageId, {
|
Images.update(imageId, {
|
||||||
$set: {
|
$set: {
|
||||||
logoPath: path.join(imagePath, imageObj.meta.logo)
|
logoPath: path.join(directory, imageObj.meta.logo)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,8 @@ Template.dashboardAppsLayout.events({
|
||||||
},
|
},
|
||||||
'click .btn-folder': function () {
|
'click .btn-folder': function () {
|
||||||
var exec = require('child_process').exec;
|
var exec = require('child_process').exec;
|
||||||
exec('open ' + this.path, function (err) {
|
var appPath = path.join(Util.KITE_PATH, this.name);
|
||||||
|
exec('open ' + appPath, function (err) {
|
||||||
if (err) { throw err; }
|
if (err) { throw err; }
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
Apps = new Meteor.Collection('apps');
|
Apps = new Meteor.Collection('apps');
|
||||||
|
|
||||||
Apps.COMMON_WEB_PORTS = [
|
Apps.COMMON_WEB_PORTS = [
|
||||||
80,
|
'80',
|
||||||
8000,
|
'8000',
|
||||||
8080,
|
'8080',
|
||||||
3000,
|
'3000',
|
||||||
5000,
|
'5000',
|
||||||
2368,
|
'2368',
|
||||||
443
|
'443'
|
||||||
];
|
];
|
||||||
|
|
||||||
Apps.allow({
|
Apps.allow({
|
||||||
|
@ -35,22 +35,27 @@ Apps.helpers({
|
||||||
if (!app.docker || !app.docker.NetworkSettings.Ports) {
|
if (!app.docker || !app.docker.NetworkSettings.Ports) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
var results = _.map(app.docker.NetworkSettings.Ports, function (value, key) {
|
var results = _.map(app.docker.NetworkSettings.Ports, function (value, key) {
|
||||||
var portProtocolPair = key.split('/');
|
var portProtocolPair = key.split('/');
|
||||||
var res = {
|
var res = {
|
||||||
'port': parseInt(portProtocolPair[0]),
|
'port': portProtocolPair[0],
|
||||||
'protocol': portProtocolPair[1]
|
'protocol': portProtocolPair[1]
|
||||||
};
|
};
|
||||||
if (value.length) {
|
if (value && value.length) {
|
||||||
var port = value[0].HostPort;
|
var port = value[0].HostPort;
|
||||||
res['hostIp'] = Docker.hostIp;
|
res['hostIp'] = Docker.hostIp;
|
||||||
res['hostPort'] = port;
|
res['hostPort'] = port;
|
||||||
res['web'] = Apps.COMMON_WEB_PORTS.indexOf(res.port) !== -1;
|
res['web'] = Apps.COMMON_WEB_PORTS.indexOf(res.port) !== -1;
|
||||||
res['url'] = 'http://' + Docker.hostIp + ':' + port;
|
res['url'] = 'http://' + Docker.hostIp + ':' + port;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
results = _.filter(results, function (res) { return res !== null; });
|
||||||
|
|
||||||
results.sort(function (a, b) {
|
results.sort(function (a, b) {
|
||||||
// prefer lower ports
|
// prefer lower ports
|
||||||
if (a.web && b.web) {
|
if (a.web && b.web) {
|
||||||
|
|
|
@ -12,12 +12,12 @@
|
||||||
"type": "GNU",
|
"type": "GNU",
|
||||||
"url": "https://raw.githubusercontent.com/kitematic/kitematic/master/LICENSE"
|
"url": "https://raw.githubusercontent.com/kitematic/kitematic/master/LICENSE"
|
||||||
}],
|
}],
|
||||||
|
"boot2docker-version": "1.3.2",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-to-html": "0.2.0",
|
"ansi-to-html": "0.2.0",
|
||||||
"async": "^0.9.0",
|
"async": "^0.9.0",
|
||||||
"chokidar": "git+https://github.com/usekite/chokidar.git",
|
|
||||||
"dockerode": "2.0.4",
|
"dockerode": "2.0.4",
|
||||||
"exec": "^0.1.2",
|
"exec": "^0.1.2",
|
||||||
"moment": "2.8.1",
|
"moment": "2.8.1",
|
||||||
|
@ -25,6 +25,7 @@
|
||||||
"open": "0.0.5",
|
"open": "0.0.5",
|
||||||
"request": "2.42.0",
|
"request": "2.42.0",
|
||||||
"request-progress": "0.3.1",
|
"request-progress": "0.3.1",
|
||||||
"tar": "0.1.20"
|
"tar": "0.1.20",
|
||||||
|
"pkginfo": "0.3.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,35 +2,31 @@
|
||||||
set -e # Auto exit on error
|
set -e # Auto exit on error
|
||||||
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
source $DIR/colors.sh
|
|
||||||
|
|
||||||
BASE=$DIR/..
|
BASE=$DIR/..
|
||||||
NPM="$BASE/cache/node/bin/npm"
|
NPM="$BASE/cache/node/bin/npm"
|
||||||
NODE="$BASE/cache/node/bin/node"
|
NODE="$BASE/cache/node/bin/node"
|
||||||
VERSION=$($NODE -pe 'JSON.parse(process.argv[1]).version' "$(cat package.json)")
|
VERSION=$($NODE -pe 'JSON.parse(process.argv[1]).version' "$(cat package.json)")
|
||||||
|
|
||||||
pushd $BASE/meteor
|
source $DIR/colors.sh
|
||||||
|
|
||||||
$BASE/script/setup.sh
|
$BASE/script/setup.sh
|
||||||
rm -rf ../bundle
|
rm -rf ./bundle
|
||||||
|
|
||||||
cecho "-----> Building bundle from Meteor app, this may take a few minutes..." $blue
|
cecho "-----> Building bundle from Meteor app, this may take a few minutes..." $blue
|
||||||
|
|
||||||
|
cd $BASE/meteor
|
||||||
meteor bundle --directory ../bundle
|
meteor bundle --directory ../bundle
|
||||||
|
|
||||||
cd ../bundle
|
cd $BASE/bundle
|
||||||
|
|
||||||
cecho "-----> Installing bundle npm packages." $blue
|
cecho "-----> Installing bundle npm packages." $blue
|
||||||
pushd programs/server
|
cd programs/server
|
||||||
$NPM install
|
$NPM install
|
||||||
popd
|
|
||||||
|
|
||||||
cecho "Bundle created." $green
|
cecho "Bundle created." $green
|
||||||
|
|
||||||
popd
|
cd $BASE
|
||||||
|
|
||||||
pushd $BASE
|
rm -Rf ./dist/osx/
|
||||||
|
|
||||||
rm -rf ./dist/osx
|
|
||||||
mkdir -p ./dist/osx/
|
mkdir -p ./dist/osx/
|
||||||
|
|
||||||
DIST_APP=Kitematic.app
|
DIST_APP=Kitematic.app
|
||||||
|
@ -39,6 +35,7 @@ cecho "-----> Creating $DIST_APP..." $blue
|
||||||
find cache/atom-shell -name "debug\.log" -print0 | xargs -0 rm -rf
|
find cache/atom-shell -name "debug\.log" -print0 | xargs -0 rm -rf
|
||||||
cp -R cache/atom-shell/Atom.app dist/osx/
|
cp -R cache/atom-shell/Atom.app dist/osx/
|
||||||
mv dist/osx/Atom.app dist/osx/$DIST_APP
|
mv dist/osx/Atom.app dist/osx/$DIST_APP
|
||||||
|
mv dist/osx/$DIST_APP/Contents/MacOS/Atom dist/osx/$DIST_APP/Contents/MacOS/Kitematic
|
||||||
mkdir -p dist/osx/$DIST_APP/Contents/Resources/app
|
mkdir -p dist/osx/$DIST_APP/Contents/Resources/app
|
||||||
|
|
||||||
cecho "-----> Copying meteor bundle into $DIST_APP..." $blue
|
cecho "-----> Copying meteor bundle into $DIST_APP..." $blue
|
||||||
|
@ -58,7 +55,6 @@ cp kitematic.icns dist/osx/$DIST_APP/Contents/Resources/atom.icns
|
||||||
|
|
||||||
chmod +x dist/osx/$DIST_APP/Contents/Resources/app/resources/terminal
|
chmod +x dist/osx/$DIST_APP/Contents/Resources/app/resources/terminal
|
||||||
chmod +x dist/osx/$DIST_APP/Contents/Resources/app/resources/node
|
chmod +x dist/osx/$DIST_APP/Contents/Resources/app/resources/node
|
||||||
|
|
||||||
chmod -R u+w dist/osx/$DIST_APP/Contents/Resources/app/bundle
|
chmod -R u+w dist/osx/$DIST_APP/Contents/Resources/app/bundle
|
||||||
|
|
||||||
cecho "-----> Updating Info.plist version to $VERSION" $blue
|
cecho "-----> Updating Info.plist version to $VERSION" $blue
|
||||||
|
@ -66,19 +62,17 @@ cecho "-----> Updating Info.plist version to $VERSION" $blue
|
||||||
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName Kitematic" $BASE/dist/osx/$DIST_APP/Contents/Info.plist
|
/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName Kitematic" $BASE/dist/osx/$DIST_APP/Contents/Info.plist
|
||||||
/usr/libexec/PlistBuddy -c "Set :CFBundleName Kitematic" $BASE/dist/osx/$DIST_APP/Contents/Info.plist
|
/usr/libexec/PlistBuddy -c "Set :CFBundleName Kitematic" $BASE/dist/osx/$DIST_APP/Contents/Info.plist
|
||||||
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier com.kitematic.kitematic" $BASE/dist/osx/$DIST_APP/Contents/Info.plist
|
/usr/libexec/PlistBuddy -c "Set :CFBundleIdentifier com.kitematic.kitematic" $BASE/dist/osx/$DIST_APP/Contents/Info.plist
|
||||||
|
/usr/libexec/PlistBuddy -c "Set :CFBundleExecutable Kitematic" $BASE/dist/osx/$DIST_APP/Contents/Info.plist
|
||||||
|
|
||||||
if [ -f $DIR/sign.sh ]; then
|
if [ -f $DIR/sign.sh ]; then
|
||||||
cecho "-----> Signing app file...." $blue
|
cecho "-----> Signing app file...." $blue
|
||||||
$DIR/sign.sh $BASE/dist/osx/$DIST_APP
|
$DIR/sign.sh $BASE/dist/osx/$DIST_APP
|
||||||
fi
|
fi
|
||||||
|
|
||||||
pushd dist/osx
|
cd $BASE/dist/osx
|
||||||
cecho "-----> Creating disributable zip file...." $blue
|
cecho "-----> Creating disributable zip file...." $blue
|
||||||
ditto -c -k --sequesterRsrc --keepParent $DIST_APP Kitematic-$VERSION.zip
|
ditto -c -k --sequesterRsrc --keepParent $DIST_APP Kitematic-$VERSION.zip
|
||||||
popd
|
|
||||||
|
|
||||||
cecho "Done." $green
|
cecho "Done." $green
|
||||||
cecho "Kitematic app available at dist/osx/$DIST_APP" $green
|
cecho "Kitematic app available at dist/osx/$DIST_APP" $green
|
||||||
cecho "Kitematic zip distribution available at dist/osx/Kitematic.zip" $green
|
cecho "Kitematic zip distribution available at dist/osx/Kitematic.zip" $green
|
||||||
|
|
||||||
popd
|
|
||||||
|
|
|
@ -1,22 +1,16 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
set -e # Auto exit on error
|
set -e
|
||||||
|
|
||||||
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
||||||
source $DIR/colors.sh
|
|
||||||
|
|
||||||
BASE=$DIR/..
|
|
||||||
pushd $BASE
|
|
||||||
|
|
||||||
mkdir -p cache
|
|
||||||
|
|
||||||
pushd cache
|
|
||||||
|
|
||||||
BOOT2DOCKER_CLI_VERSION=1.3.1
|
|
||||||
BOOT2DOCKER_CLI_VERSION_FILE=boot2docker-$BOOT2DOCKER_CLI_VERSION
|
|
||||||
BOOT2DOCKER_CLI_FILE=boot2docker
|
|
||||||
|
|
||||||
ATOM_SHELL_VERSION=0.19.1
|
ATOM_SHELL_VERSION=0.19.1
|
||||||
ATOM_SHELL_FILE=atom-shell-v$ATOM_SHELL_VERSION-darwin-x64.zip
|
ATOM_SHELL_FILE=atom-shell-v$ATOM_SHELL_VERSION-darwin-x64.zip
|
||||||
|
BASE=$DIR/..
|
||||||
|
|
||||||
|
source $DIR/colors.sh
|
||||||
|
cd $BASE
|
||||||
|
|
||||||
|
mkdir -p cache
|
||||||
|
cd cache
|
||||||
|
|
||||||
if [ ! -f $ATOM_SHELL_FILE ]; then
|
if [ ! -f $ATOM_SHELL_FILE ]; then
|
||||||
cecho "-----> Downloading Atom Shell..." $purple
|
cecho "-----> Downloading Atom Shell..." $purple
|
||||||
|
@ -42,9 +36,13 @@ if [ ! -f "node-v0.10.29-darwin-x64.tar.gz" ]; then
|
||||||
cp node/LICENSE $BASE/resources/NODE_LICENSE.txt
|
cp node/LICENSE $BASE/resources/NODE_LICENSE.txt
|
||||||
fi
|
fi
|
||||||
|
|
||||||
popd
|
cd $BASE
|
||||||
|
|
||||||
pushd resources
|
NODE="$BASE/cache/node/bin/node"
|
||||||
|
BOOT2DOCKER_CLI_VERSION=$($NODE -pe "JSON.parse(process.argv[1])['boot2dockerversion']" "$(cat package.json)")
|
||||||
|
BOOT2DOCKER_CLI_VERSION_FILE=boot2docker-$BOOT2DOCKER_CLI_VERSION
|
||||||
|
|
||||||
|
cd resources
|
||||||
|
|
||||||
if [ ! -f $BOOT2DOCKER_CLI_VERSION_FILE ]; then
|
if [ ! -f $BOOT2DOCKER_CLI_VERSION_FILE ]; then
|
||||||
cecho "-----> Downloading Boot2docker CLI..." $purple
|
cecho "-----> Downloading Boot2docker CLI..." $purple
|
||||||
|
@ -53,13 +51,12 @@ fi
|
||||||
|
|
||||||
chmod +x $BOOT2DOCKER_CLI_VERSION_FILE
|
chmod +x $BOOT2DOCKER_CLI_VERSION_FILE
|
||||||
|
|
||||||
popd
|
cd $BASE
|
||||||
|
|
||||||
|
# Build NPM modules
|
||||||
NPM="$BASE/cache/node/bin/npm"
|
NPM="$BASE/cache/node/bin/npm"
|
||||||
|
|
||||||
export npm_config_disturl=https://gh-contractor-zcbenz.s3.amazonaws.com/atom-shell/dist
|
export npm_config_disturl=https://gh-contractor-zcbenz.s3.amazonaws.com/atom-shell/dist
|
||||||
export npm_config_target=0.16.2
|
export npm_config_target=ATOM_SHELL_VERSION
|
||||||
export npm_config_arch=ia32
|
export npm_config_arch=ia32
|
||||||
HOME=~/.atom-shell-gyp $NPM install
|
HOME=~/.atom-shell-gyp $NPM install
|
||||||
|
|
||||||
popd
|
|
||||||
|
|
Loading…
Reference in New Issue