mirror of https://github.com/docker/docs.git
Working ports update
This commit is contained in:
parent
4ee1e4ecda
commit
54a123ef94
9
index.js
9
index.js
|
@ -124,10 +124,7 @@ app.on('ready', function() {
|
|||
width: 800,
|
||||
height: 578,
|
||||
resizable: false,
|
||||
frame: false,
|
||||
'web-preferences': {
|
||||
'web-security': false
|
||||
}
|
||||
frame: false
|
||||
};
|
||||
mainWindow = new BrowserWindow(windowOptions);
|
||||
mainWindow.hide();
|
||||
|
@ -146,6 +143,10 @@ app.on('ready', function() {
|
|||
exec('VBoxManage controlvm boot2docker-vm savestate', function (stderr, stdout, code) {});
|
||||
});
|
||||
|
||||
mainWindow.webContents.on('new-window', function (e) {
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
mainWindow.webContents.on('did-finish-load', function() {
|
||||
mainWindow.show();
|
||||
mainWindow.focus();
|
||||
|
|
|
@ -1 +1 @@
|
|||
METEOR@0.9.4
|
||||
METEOR@1.0
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
application-configuration@1.0.3
|
||||
autoupdate@1.1.2
|
||||
autoupdate@1.1.3
|
||||
base64@1.0.1
|
||||
binary-heap@1.0.1
|
||||
blaze-tools@1.0.1
|
||||
blaze@2.0.2
|
||||
blaze@2.0.3
|
||||
boilerplate-generator@1.0.1
|
||||
callback-hook@1.0.1
|
||||
check@1.0.2
|
||||
ctl-helper@1.0.4
|
||||
ctl@1.0.2
|
||||
dburles:collection-helpers@1.0.1
|
||||
ddp@1.0.10
|
||||
ddp@1.0.11
|
||||
deps@1.0.5
|
||||
ejson@1.0.4
|
||||
fastclick@1.0.1
|
||||
|
@ -18,23 +18,28 @@ follower-livedata@1.0.2
|
|||
geojson-utils@1.0.1
|
||||
html-tools@1.0.2
|
||||
htmljs@1.0.2
|
||||
http@1.0.7
|
||||
http@1.0.8
|
||||
id-map@1.0.1
|
||||
iron:core@0.3.4
|
||||
iron:dynamic-template@0.4.1
|
||||
iron:layout@0.4.1
|
||||
iron:router@0.9.4
|
||||
iron:controller@1.0.2
|
||||
iron:core@1.0.2
|
||||
iron:dynamic-template@1.0.2
|
||||
iron:layout@1.0.2
|
||||
iron:location@1.0.2
|
||||
iron:middleware-stack@1.0.2
|
||||
iron:router@1.0.2
|
||||
iron:url@1.0.2
|
||||
jquery@1.0.1
|
||||
json@1.0.1
|
||||
less@1.0.10
|
||||
launch-screen@1.0.0
|
||||
less@1.0.11
|
||||
livedata@1.0.11
|
||||
logging@1.0.4
|
||||
meteor-platform@1.1.2
|
||||
meteor@1.1.2
|
||||
minifiers@1.1.1
|
||||
minimongo@1.0.4
|
||||
logging@1.0.5
|
||||
meteor-platform@1.2.0
|
||||
meteor@1.1.3
|
||||
minifiers@1.1.2
|
||||
minimongo@1.0.5
|
||||
mobile-status-bar@1.0.1
|
||||
mongo@1.0.7
|
||||
mongo@1.0.8
|
||||
mrt:underscore-string-latest@2.3.3
|
||||
observe-sequence@1.0.3
|
||||
ordered-dict@1.0.1
|
||||
|
@ -44,17 +49,17 @@ reactive-dict@1.0.4
|
|||
reactive-var@1.0.3
|
||||
reload@1.1.1
|
||||
retry@1.0.1
|
||||
reywood:iron-router-ga@0.3.2
|
||||
reywood:iron-router-ga@0.4.1
|
||||
routepolicy@1.0.2
|
||||
session@1.0.3
|
||||
session@1.0.4
|
||||
simison:bootstrap3-less@0.3.0
|
||||
spacebars-compiler@1.0.3
|
||||
spacebars@1.0.3
|
||||
standard-app-packages@1.0.3
|
||||
templating@1.0.8
|
||||
templating@1.0.9
|
||||
tracker@1.0.3
|
||||
ui@1.0.4
|
||||
underscore@1.0.1
|
||||
url@1.0.1
|
||||
url@1.0.2
|
||||
webapp-hashing@1.0.1
|
||||
webapp@1.1.3
|
||||
webapp@1.1.4
|
||||
|
|
|
@ -6,22 +6,21 @@ var convert = new Convert();
|
|||
|
||||
AppUtil = {};
|
||||
|
||||
AppUtil.run = function (app) {
|
||||
AppUtil.run = function (app, callback) {
|
||||
var image = Images.findOne({_id: app.imageId});
|
||||
// Delete old container if one already exists
|
||||
Docker.removeContainer(app.name, function (err) {
|
||||
if (err) { console.error(err); }
|
||||
if (err) { callback(err); }
|
||||
Docker.runContainer(app, image, function (err, container) {
|
||||
if (err) { throw err; }
|
||||
if (err) { callback(err); }
|
||||
Docker.getContainerData(container.id, function (err, data) {
|
||||
if (err) { console.error(err); }
|
||||
if (err) { callback(err); }
|
||||
// Set a delay for app to spin up
|
||||
Meteor.setTimeout(function () {
|
||||
Apps.update(app._id, {$set: {
|
||||
docker: data,
|
||||
status: 'READY'
|
||||
}});
|
||||
}, 2500);
|
||||
Apps.update(app._id, {$set: {
|
||||
docker: data,
|
||||
status: 'READY'
|
||||
}});
|
||||
callback();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -29,7 +28,8 @@ AppUtil.run = function (app) {
|
|||
|
||||
AppUtil.restartHelper = function (app) {
|
||||
if (app.docker && app.docker.Id) {
|
||||
Docker.restartContainer(app.docker.Id, function (err) {
|
||||
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); }
|
||||
|
@ -96,9 +96,6 @@ AppUtil.remove = function (appId) {
|
|||
if (err) { console.error(err); }
|
||||
var appPath = path.join(Util.KITE_PATH, app.name);
|
||||
Util.deleteFolder(appPath);
|
||||
Docker.removeBindFolder(app.name, function () {
|
||||
console.log('Deleted Kite ' + app.name + ' directory.');
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -237,7 +234,8 @@ AppUtil.sync = function () {
|
|||
config: config,
|
||||
path: appPath,
|
||||
logs: [],
|
||||
createdAt: new Date()
|
||||
createdAt: new Date(),
|
||||
volumesEnabled: true
|
||||
};
|
||||
console.log(appObj);
|
||||
Apps.insert(appObj);
|
||||
|
|
|
@ -69,6 +69,12 @@ Boot2Docker.ip = function (callback) {
|
|||
});
|
||||
};
|
||||
|
||||
Boot2Docker.portOpen = function (port, callback) {
|
||||
this.exec('nc -vz 127.0.0.1 ' + port, function (stderr, stdout, code) {
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
Boot2Docker.setIp = function (ifname, ip, callback) {
|
||||
Boot2Docker.exec('ssh "sudo ifconfig ' + ifname + ' ' + ip + ' netmask 255.255.255.0"', function (stderr, stdout) {
|
||||
Boot2Docker.exec('ssh "sudo rm -rf /var/lib/boot2docker/tls/* && sudo /etc/init.d/docker restart"', function (stderr, stdout) {
|
||||
|
|
|
@ -95,7 +95,6 @@ Docker.runContainer = function (app, image, callback) {
|
|||
var builtStr = key + '=' + app.config[key];
|
||||
envParam.push(builtStr);
|
||||
});
|
||||
console.log(envParam);
|
||||
Docker.client().createContainer({
|
||||
Image: image.docker.Id,
|
||||
Tty: false,
|
||||
|
@ -107,9 +106,9 @@ Docker.runContainer = function (app, image, callback) {
|
|||
console.log('Created container: ' + container.id);
|
||||
// Bind volumes
|
||||
var binds = [];
|
||||
if (image.docker.Config.Volumes && image.docker.Config.Volumes.length > 0) {
|
||||
if (app.volumesEnabled && image.docker.Config.Volumes && image.docker.Config.Volumes.length > 0) {
|
||||
_.each(image.docker.Config.Volumes, function (vol) {
|
||||
binds.push('/var/lib/docker/binds/' + app.name + vol.Path + ':' + vol.Path);
|
||||
binds.push([Util.getHomePath(), 'Kitematic', app.name, vol.Path].join('/') + ':' + vol.Path);
|
||||
});
|
||||
}
|
||||
// Start the container
|
||||
|
@ -150,19 +149,6 @@ Docker.stopContainer = function (containerId, callback) {
|
|||
});
|
||||
};
|
||||
|
||||
Docker.restartContainer = function (containerId, callback) {
|
||||
var container = Docker.client().getContainer(containerId);
|
||||
container.restart(function (err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
callback(err);
|
||||
return;
|
||||
}
|
||||
console.log('Restarted container: ' + containerId);
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
|
||||
var convertVolumeObjToArray = function (obj) {
|
||||
var result = [];
|
||||
if (obj !== null && typeof obj === 'object') {
|
||||
|
@ -241,9 +227,3 @@ Docker.removeImage = function (imageId, callback) {
|
|||
callback(null);
|
||||
});
|
||||
};
|
||||
|
||||
Docker.removeBindFolder = function (name, callback) {
|
||||
exec(Boot2Docker.command() + ' ssh "sudo rm -rf /var/lib/docker/binds/' + name + '"', function (err, stdout) {
|
||||
callback(err, stdout);
|
||||
});
|
||||
};
|
||||
|
|
|
@ -6,15 +6,6 @@ var fs = require('fs');
|
|||
|
||||
ImageUtil = {};
|
||||
|
||||
var createTarFile = function (image, callback) {
|
||||
var TAR_PATH = path.join(Util.KITE_TAR_PATH, image._id + '.tar');
|
||||
exec('tar czf ' + TAR_PATH + ' -C ' + image.path + ' .', function (err) {
|
||||
if (err) { callback(err, null); return; }
|
||||
console.log('Created tar file: ' + TAR_PATH);
|
||||
callback(null, TAR_PATH);
|
||||
});
|
||||
};
|
||||
|
||||
var getFromImage = function (dockerfile) {
|
||||
var patternString = "(FROM)(.*)";
|
||||
var regex = new RegExp(patternString, "g");
|
||||
|
@ -54,23 +45,8 @@ ImageUtil.getMetaData = function (directory) {
|
|||
return kiteJSON;
|
||||
};
|
||||
|
||||
ImageUtil.saveFolder = function (directory, imageId, callback) {
|
||||
var destinationPath = path.join(Util.KITE_IMAGES_PATH, imageId);
|
||||
if (!fs.existsSync(destinationPath)) {
|
||||
fs.mkdirSync(destinationPath, function (err) {
|
||||
if (err) { callback(err); return; }
|
||||
});
|
||||
Util.copyFolder(directory, destinationPath, function (err) {
|
||||
if (err) { callback(err); return; }
|
||||
console.log('Copied image folder for: ' + imageId);
|
||||
callback(null);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
ImageUtil.rebuildHelper = function (image, callback) {
|
||||
Util.deleteFolder(image.path);
|
||||
var imageMetaData = ImageUtil.getMetaData(image.originPath);
|
||||
var imageMetaData = ImageUtil.getMetaData(image.path);
|
||||
if (imageMetaData.logo) {
|
||||
Images.update(image._id, {
|
||||
$set: {
|
||||
|
@ -91,14 +67,11 @@ ImageUtil.rebuildHelper = function (image, callback) {
|
|||
}
|
||||
});
|
||||
image = Images.findOne(image._id);
|
||||
ImageUtil.saveFolder(image.originPath, image._id, function (err) {
|
||||
if (err) { console.error(err); }
|
||||
ImageUtil.pull(fs.readFileSync(path.join(image.path, 'Dockerfile'), 'utf8'), image._id, function (err) {
|
||||
if (err) { callback(err, null); return; }
|
||||
ImageUtil.build(image, function (err) {
|
||||
if (err) { console.error(err); }
|
||||
callback(null, null);
|
||||
});
|
||||
ImageUtil.pull(fs.readFileSync(path.join(image.path, 'Dockerfile'), 'utf8'), image._id, function (err) {
|
||||
if (err) { callback(err, null); return; }
|
||||
ImageUtil.build(image, function (err) {
|
||||
if (err) { console.error(err); }
|
||||
callback(null, null);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
@ -146,7 +119,6 @@ ImageUtil.pull = function (dockerfile, imageId, callback) {
|
|||
console.log('From image: ' + fromImage);
|
||||
var installedImage = null;
|
||||
Docker.getImageData(imageId, function (err, data) {
|
||||
if (err) { console.error(err); }
|
||||
installedImage = data;
|
||||
if (fromImage && !installedImage) {
|
||||
Images.update(imageId, {
|
||||
|
@ -191,7 +163,7 @@ ImageUtil.pull = function (dockerfile, imageId, callback) {
|
|||
};
|
||||
|
||||
ImageUtil.build = function (image, callback) {
|
||||
createTarFile(image, function (err, tarFilePath) {
|
||||
Util.createTarFile(image.path, path.join(Util.KITE_TAR_PATH, image._id + '.tar'), function (err, tarFilePath) {
|
||||
if (err) { console.error(err); }
|
||||
Images.update(image._id, {
|
||||
$set: {
|
||||
|
@ -199,7 +171,7 @@ ImageUtil.build = function (image, callback) {
|
|||
}
|
||||
});
|
||||
Docker.client().buildImage(tarFilePath, {t: image.meta.name + ':' + image.meta.version}, function (err, response) {
|
||||
if (err) { callback(err); }
|
||||
if (err) { callback(err); return; }
|
||||
console.log('Building Docker image...');
|
||||
response.setEncoding('utf8');
|
||||
response.on('data', function (data) {
|
||||
|
@ -265,11 +237,6 @@ ImageUtil.remove = function (imageId) {
|
|||
if (err) { console.error(err); }
|
||||
});
|
||||
}
|
||||
try {
|
||||
Util.deleteFolder(image.path);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
|
||||
ImageUtil.sync = function () {
|
||||
|
@ -342,7 +309,6 @@ ImageUtil.sync = function () {
|
|||
version: version
|
||||
}
|
||||
};
|
||||
console.log(imageObj);
|
||||
Images.insert(imageObj);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -6,25 +6,26 @@ Router.configure({
|
|||
var currentPath = Router.current().path;
|
||||
ga('send', 'pageview', currentPath);
|
||||
}
|
||||
this.next();
|
||||
}
|
||||
});
|
||||
|
||||
DashboardController = RouteController.extend({
|
||||
layoutTemplate: 'dashboard_layout',
|
||||
layoutTemplate: 'dashboardLayout',
|
||||
waitOn: function () {
|
||||
return [Meteor.subscribe('apps'), Meteor.subscribe('images'), Meteor.subscribe('settings')];
|
||||
}
|
||||
});
|
||||
|
||||
AppController = DashboardController.extend({
|
||||
layoutTemplate: 'dashboard_apps_layout',
|
||||
layoutTemplate: 'dashboardAppsLayout',
|
||||
data: function () {
|
||||
return Apps.findOne({name: this.params.name});
|
||||
}
|
||||
});
|
||||
|
||||
ImageController = DashboardController.extend({
|
||||
layoutTemplate: 'dashboard_images_layout',
|
||||
layoutTemplate: 'dashboardImagesLayout',
|
||||
data: function () {
|
||||
return Images.findOne({_id: this.params.id});
|
||||
}
|
||||
|
@ -50,6 +51,8 @@ Router.map(function () {
|
|||
Settings.insert({tracking: true});
|
||||
}
|
||||
Session.set('onIntro', false);
|
||||
startUpdatingBoot2DockerUtilization();
|
||||
// startSyncingAppState();
|
||||
Router.go('dashboard_apps');
|
||||
}
|
||||
});
|
||||
|
|
|
@ -101,10 +101,8 @@ Setup.steps = [
|
|||
}
|
||||
});
|
||||
},
|
||||
message: 'Setting up the Docker VM...',
|
||||
message: 'Setting up the Docker VM...'
|
||||
},
|
||||
|
||||
// Start the Docker VM
|
||||
{
|
||||
run: function (callback) {
|
||||
Boot2Docker.state(function (err, state) {
|
||||
|
@ -118,9 +116,8 @@ Setup.steps = [
|
|||
}
|
||||
});
|
||||
},
|
||||
message: 'Starting the Docker VM...',
|
||||
message: 'Starting the Docker VM...'
|
||||
},
|
||||
|
||||
{
|
||||
run: function (callback) {
|
||||
Boot2Docker.ip(function (err, ip) {
|
||||
|
|
|
@ -17,4 +17,11 @@ Meteor.startup(function () {
|
|||
if (!fs.existsSync(Util.getResourceDir())) {
|
||||
fs.mkdirSync(Util.getResourceDir());
|
||||
}
|
||||
|
||||
Boot2Docker.ip(function (err, ip) {
|
||||
if (!err) {
|
||||
console.log('Setting host IP to: ' + ip);
|
||||
Docker.setHost(ip);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -77,6 +77,14 @@ Util.copyVolumes = function (directory, appName, callback) {
|
|||
}
|
||||
};
|
||||
|
||||
Util.createTarFile = function (sourcePath, destinationFile, callback) {
|
||||
exec('tar czf ' + destinationFile + ' -C ' + sourcePath + ' .', function (err) {
|
||||
if (err) {callback(err, null); return;}
|
||||
console.log('Created tar file: ' + destinationFile);
|
||||
callback(null, destinationFile);
|
||||
});
|
||||
};
|
||||
|
||||
Util.hasDockerfile = function (directory) {
|
||||
return fs.existsSync(path.join(directory, 'Dockerfile'));
|
||||
};
|
||||
|
|
|
@ -69,50 +69,41 @@ Handlebars.registerHelper('displayTags', function (tags, delimiter) {
|
|||
}
|
||||
});
|
||||
|
||||
var fixBoot2DockerVM = function (callback) {
|
||||
Boot2Docker.check(function (err) {
|
||||
if (err) {
|
||||
Session.set('available', false);
|
||||
Boot2Docker.resolve(function (err) {
|
||||
if (err) {
|
||||
callback(err);
|
||||
updateBoot2DockerUtilization = function (callback) {
|
||||
Boot2Docker.exists(function (err, exists) {
|
||||
if (err) { callback(err); return; }
|
||||
if (exists) {
|
||||
Boot2Docker.state(function (err, state) {
|
||||
if (err) { callback(err); return; }
|
||||
Session.set('boot2dockerState', state);
|
||||
if (state === 'running') {
|
||||
Boot2Docker.stats(function (err, stats) {
|
||||
if (err) { callback(err); return; }
|
||||
if (stats.state !== 'poweroff' && stats.memory && stats.disk) {
|
||||
Session.set('boot2dockerMemoryUsage', stats.memory);
|
||||
Session.set('boot2dockerDiskUsage', stats.disk);
|
||||
callback();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Session.set('available', true);
|
||||
callback();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
Meteor.setInterval(function () {
|
||||
if (!Session.get('onIntro')) {
|
||||
Boot2Docker.exists(function (err, exists) {
|
||||
if (err) { console.log(err); return; }
|
||||
if (exists) {
|
||||
Boot2Docker.state(function (err, state) {
|
||||
if (err) { console.log(err); return; }
|
||||
Session.set('boot2dockerState', state);
|
||||
if (state === 'running') {
|
||||
Boot2Docker.stats(function (err, stats) {
|
||||
if (err) { console.log(err); return; }
|
||||
if (stats.state !== 'poweroff' && stats.memory && stats.disk) {
|
||||
Session.set('boot2dockerMemoryUsage', stats.memory);
|
||||
Session.set('boot2dockerDiskUsage', stats.disk);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 5000);
|
||||
startUpdatingBoot2DockerUtilization = function () {
|
||||
updateBoot2DockerUtilization(function (err) {
|
||||
Meteor.setTimeout(updateBoot2DockerUtilization, 5000);
|
||||
});
|
||||
};
|
||||
|
||||
Meteor.setInterval(function () {
|
||||
if (!Session.get('onIntro')) {
|
||||
startSyncingAppState = function () {
|
||||
ImageUtil.sync();
|
||||
AppUtil.sync();
|
||||
Meteor.setTimeout(function () {
|
||||
ImageUtil.sync();
|
||||
AppUtil.sync();
|
||||
}
|
||||
}, 5000);
|
||||
}, 5000);
|
||||
};
|
|
@ -20,6 +20,49 @@
|
|||
.btn-icon {
|
||||
font-size: 20px;
|
||||
margin-left: 0.4em;
|
||||
cursor: pointer;
|
||||
}
|
||||
.dropdown {
|
||||
&.open {
|
||||
.tooltip {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
.ports {
|
||||
.dropdown-menu {
|
||||
min-width: 241px;
|
||||
}
|
||||
.btn-group {
|
||||
top: -2px;
|
||||
}
|
||||
.btn-globe {
|
||||
line-height: 22px;
|
||||
padding: 0 5px;
|
||||
.typcn {
|
||||
font-size: 18px;
|
||||
top: 2px;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
.btn-ports {
|
||||
.caret {
|
||||
margin-left: 3px;
|
||||
margin-right: 1px;
|
||||
margin-top: -2px
|
||||
}
|
||||
}
|
||||
.btn-caret {
|
||||
padding-top: 3px;
|
||||
padding-bottom: 3px;
|
||||
border-width: 1px;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
}
|
||||
&.open + .tooltip {
|
||||
display: none !important;
|
||||
}
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
&:hover {
|
||||
|
@ -259,6 +302,39 @@
|
|||
}
|
||||
}
|
||||
|
||||
.app-ports {
|
||||
cursor: default;
|
||||
padding: 10px 15px 3px;
|
||||
min-width: 240px;
|
||||
li {
|
||||
padding-bottom: 7px;
|
||||
white-space: nowrap;
|
||||
|
||||
.port-wrapper {
|
||||
display: inline-block;
|
||||
min-width: 72px;
|
||||
font-weight: bold;
|
||||
font-size: 13px;
|
||||
}
|
||||
.arrow-wrapper {
|
||||
text-align: center;
|
||||
display: inline-block;
|
||||
min-width: 28px;
|
||||
font-size: 15px;
|
||||
color: #999;
|
||||
}
|
||||
.open-button-wrapper {
|
||||
display: inline-block;
|
||||
}
|
||||
.host-address-wrapper {
|
||||
font-family: Monaco, monospace;
|
||||
font-size: 12px;
|
||||
cursor: text;
|
||||
.text-select();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.utilization {
|
||||
font-size: 12px;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template name="dashboard_apps_logs">
|
||||
<template name="dashboardAppsLogs">
|
||||
<div class="logs">
|
||||
{{#each logs}}
|
||||
<h6>{{{this}}}</h6>
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
<template name="dashboardAppsPorts">
|
||||
<div class="app-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">
|
||||
<span class="port-wrapper">Port {{this.port}}</span>
|
||||
<span class="arrow-wrapper">
|
||||
<span class="typcn typcn-arrow-right"></span>
|
||||
</span>
|
||||
<span class="host-address-wrapper">{{this.hostIp}}:{{this.hostPort}}</span>
|
||||
</li>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</template>
|
|
@ -1,41 +1,7 @@
|
|||
<template name="dashboard_apps_settings">
|
||||
<template name="dashboardAppsSettings">
|
||||
<div class="section">
|
||||
<div class="left-section">
|
||||
<h4>Container Details</h4>
|
||||
<p class="help-block">This section lists more information about this container.</p>
|
||||
</div>
|
||||
<div class="right-section">
|
||||
<div class="row">
|
||||
<div class="col-xs-3">
|
||||
<label>Host URL</label>
|
||||
</div>
|
||||
<div class="col-xs-8">
|
||||
{{url}}
|
||||
</div>
|
||||
</div>
|
||||
{{#if ports}}
|
||||
<div class="row">
|
||||
<div class="col-xs-3">
|
||||
<label>Ports</label>
|
||||
</div>
|
||||
<div class="col-xs-8">
|
||||
{{ports}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
<div class="row">
|
||||
<div class="col-xs-3">
|
||||
<label>Status</label>
|
||||
</div>
|
||||
<div class="col-xs-8">
|
||||
{{status}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="left-section">
|
||||
<h4>Config Variables</h4>
|
||||
<h4>Environment Variables</h4>
|
||||
<p class="help-block">You can update your container's environment variables here.</p>
|
||||
</div>
|
||||
<div class="right-section">
|
||||
|
@ -69,6 +35,19 @@
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="left-section">
|
||||
<h4>Volumes</h4>
|
||||
<p class="help-block">When enabled, this container's volume data will be available under ~/Kitematic/{{name}}.</p>
|
||||
</div>
|
||||
<div class="right-section">
|
||||
{{#if volumesEnabled}}
|
||||
<a onclick="trackLink('enable container volumes')" class="btn btn-negative btn-disable-volumes btn-sm">Disable Volumes</a>
|
||||
{{else}}
|
||||
<a onclick="trackLink('disable container volumes')" class="btn btn-positive btn-enable-volumes btn-sm">Enable Volumes</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="section">
|
||||
<div class="left-section">
|
||||
<h4>Delete Container</h4>
|
||||
|
|
|
@ -13,7 +13,7 @@ var getConfigVars = function ($form) {
|
|||
return configVars;
|
||||
};
|
||||
|
||||
Template.dashboard_apps_settings.events({
|
||||
Template.dashboardAppsSettings.events({
|
||||
'click .btn-delete-var': function (e) {
|
||||
var $button = $(e.currentTarget);
|
||||
$button.attr("disabled", "disabled");
|
||||
|
@ -41,7 +41,8 @@ Template.dashboard_apps_settings.events({
|
|||
e.stopPropagation();
|
||||
return false;
|
||||
},
|
||||
'click .btn-delete-app': function () {
|
||||
'click .btn-delete-app': function (e) {
|
||||
e.preventDefault();
|
||||
var appId = this._id;
|
||||
dialog.showMessageBox({
|
||||
message: 'Are you sure you want to delete this app?',
|
||||
|
@ -52,5 +53,29 @@ Template.dashboard_apps_settings.events({
|
|||
Router.go('dashboard_apps');
|
||||
}
|
||||
});
|
||||
},
|
||||
'click .btn-enable-volumes': function (e) {
|
||||
e.preventDefault();
|
||||
var appId = this._id;
|
||||
Apps.update(appId, {
|
||||
$set: {volumesEnabled: true}
|
||||
});
|
||||
AppUtil.run(Apps.findOne(appId), function (err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
},
|
||||
'click .btn-disable-volumes': function (e) {
|
||||
e.preventDefault();
|
||||
var appId = this._id;
|
||||
Apps.update(appId, {
|
||||
$set: {volumesEnabled: false}
|
||||
});
|
||||
AppUtil.run(Apps.findOne(appId), function (err) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template name="dashboard_apps">
|
||||
<template name="dashboardApps">
|
||||
<div class="header">
|
||||
<h3>Containers</h3>
|
||||
<div class="options">
|
||||
|
@ -14,7 +14,7 @@
|
|||
{{#if hasItem apps}}
|
||||
<div class="apps line-item-collection">
|
||||
{{#each apps}}
|
||||
{{> dashboard_single_app}}
|
||||
{{> dashboardSingleApp}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{else}}
|
||||
|
@ -30,6 +30,6 @@
|
|||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{> modal_create_app}}
|
||||
{{> modal_create_image}}
|
||||
{{> modalCreateApp}}
|
||||
{{> modalCreateImage}}
|
||||
</template>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Template.dashboard_apps.helpers({
|
||||
Template.dashboardApps.helpers({
|
||||
apps: function () {
|
||||
return Apps.find({}, {sort: {createdAt: -1}});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
Template.dashboardSingleApp.events({
|
||||
'click .btn-view-port': function (e) {
|
||||
try {
|
||||
var open = require('open');
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var $btn = $(e.currentTarget);
|
||||
var url = $btn.attr('href');
|
||||
open(url);
|
||||
} catch (exception) {
|
||||
console.log(exception);
|
||||
}
|
||||
},
|
||||
'click .host-address-wrapper': function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
}
|
||||
});
|
|
@ -1,4 +1,4 @@
|
|||
<template name="dashboard_single_app">
|
||||
<template name="dashboardSingleApp">
|
||||
<div class="app">
|
||||
<h5>
|
||||
{{#if $eq status 'READY'}}
|
||||
|
@ -23,19 +23,42 @@
|
|||
</h5>
|
||||
<div class="options">
|
||||
{{#if $eq status 'READY'}}
|
||||
{{#if url}}
|
||||
<a href="{{url}}" onclick="trackLink('view container')" class="btn-icon btn-view" target="_blank" data-toggle="tooltip" data-placement="bottom" title="View"><span class="typcn typcn-eye-outline"></span></a>
|
||||
{{#if viewPort}}
|
||||
<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">
|
||||
<span class="typcn typcn-world-outline"></span>
|
||||
</a>
|
||||
<a href="#" class="btn btn-action btn-xs btn-caret dropdown-toggle" id="dashboardAppsPorts" data-toggle="dropdown">
|
||||
<span class="caret"></span>
|
||||
<span class="sr-only">Toggle Dropdown</span>
|
||||
</a>
|
||||
<ul class="dropdown-menu pull-right" role="menu" aria-labelledby="dashboardAppsPorts">
|
||||
{{> dashboardAppsPorts}}
|
||||
</ul>
|
||||
</div>
|
||||
{{else}}
|
||||
<span class="ports dropdown">
|
||||
<div class="dropdown btn-group btn-icon dropdown-toggle" id="dashboardAppsPorts" data-toggle="dropdown" data-placement="bottom" title="View">
|
||||
<a href="#" onclick="trackLink('view container')" class="btn btn-action btn-xs btn-globe btn-ports">
|
||||
<span class="typcn typcn-world-outline"></span>
|
||||
<span class="caret"></span>
|
||||
</a>
|
||||
</div>
|
||||
<ul class="dropdown-menu pull-right" role="menu" aria-labelledby="dashboardAppsPorts">
|
||||
{{> dashboardAppsPorts}}
|
||||
</ul>
|
||||
</span>
|
||||
{{/if}}
|
||||
<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>
|
||||
{{/if}}
|
||||
<a href="#" onclick="trackLink('open container folder')" class="btn-icon btn-folder" target="_blank" data-toggle="tooltip" data-placement="bottom" title="Folder"><span class="typcn typcn-folder-open"></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'}}
|
||||
<a href="#" onclick="trackLink('stop container')" class="btn-icon btn-stop" target="_blank" data-toggle="tooltip" data-placement="bottom" title="Stop"><span class="typcn typcn-media-pause-outline"></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>
|
||||
{{/if}}
|
||||
{{#if $eq status 'STOPPED'}}
|
||||
<a href="#" onclick="trackLink('start container')" class="btn-icon btn-start" target="_blank" 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>
|
||||
{{/if}}
|
||||
<a href="#" onclick="trackLink('restart container')" class="btn-icon btn-restart" target="_blank" data-toggle="tooltip" data-placement="bottom" title="Restart"><span class="typcn typcn-refresh-outline"></span></a>
|
||||
<a href="#" onclick="trackLink('restart container')" class="btn-icon btn-restart" data-toggle="tooltip" data-placement="bottom" title="Restart"><span class="typcn typcn-refresh-outline"></span></a>
|
||||
<a href="/apps/{{name}}/logs" onclick="trackLink('container logs')" class="btn-icon btn-logs" data-toggle="tooltip" data-placement="bottom" title="Logs"><span class="typcn typcn-document-text"></span></a>
|
||||
<a href="/apps/{{name}}/settings" onclick="trackLink('container settings')" class="btn-icon" data-toggle="tooltip" data-placement="bottom" title="Settings"><span class="typcn typcn-cog-outline"></span></a>
|
||||
</div>
|
||||
|
|
|
@ -1,10 +1,24 @@
|
|||
Template.dashboard_single_app.rendered = function () {
|
||||
var remote = require('remote');
|
||||
var dialog = remote.require('dialog');
|
||||
var exec = require('child_process').exec;
|
||||
|
||||
Template.dashboardSingleApp.rendered = function () {
|
||||
Meteor.setInterval(function () {
|
||||
$('.btn-icon').tooltip();
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
Template.dashboard_single_app.events({
|
||||
Template.dashboardSingleApp.helpers({
|
||||
viewPort: function () {
|
||||
var ports = this.ports();
|
||||
if (ports[0] && ports[0].web) {
|
||||
return ports[0];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
Template.dashboardSingleApp.events({
|
||||
'click .btn-view': function (e) {
|
||||
try {
|
||||
var open = require('open');
|
||||
|
@ -22,24 +36,54 @@ Template.dashboard_single_app.events({
|
|||
var cmd = Boot2Docker.command() + ' ssh -t "sudo docker exec -i -t ' + app.docker.Id + ' bash"';
|
||||
Util.openTerminal(cmd);
|
||||
},
|
||||
'click .btn-start': function () {
|
||||
'click .btn-start': function (e) {
|
||||
e.preventDefault();
|
||||
AppUtil.start(this._id);
|
||||
$('.btn-icon').tooltip('hide');
|
||||
},
|
||||
'click .btn-stop': function () {
|
||||
'click .btn-stop': function (e) {
|
||||
e.preventDefault();
|
||||
AppUtil.stop(this._id);
|
||||
$('.btn-icon').tooltip('hide');
|
||||
},
|
||||
'click .btn-restart': function () {
|
||||
'click .btn-restart': function (e) {
|
||||
e.preventDefault();
|
||||
AppUtil.restart(this._id);
|
||||
},
|
||||
'click .btn-folder': function () {
|
||||
var exec = require('child_process').exec;
|
||||
exec('open ' + this.path, function (err) {
|
||||
if (err) { throw err; }
|
||||
'click .btn-folder': function (e) {
|
||||
e.preventDefault();
|
||||
var appId = this._id;
|
||||
|
||||
var app = Apps.findOne(appId);
|
||||
if (!app) {
|
||||
throw new Error('Cannot find app with id: ' + appId);
|
||||
}
|
||||
|
||||
if (app.volumesEnabled) {
|
||||
exec('open ' + this.path, function (err) {
|
||||
if (err) { throw err; }
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
dialog.showMessageBox({
|
||||
message: 'Volumes need to be enabled to view their contents via Finder. Enable volumes for this container?',
|
||||
buttons: ['Enable Volumes', 'Cancel']
|
||||
}, function (index) {
|
||||
if (index === 0) {
|
||||
Apps.update(appId, {
|
||||
$set: {volumesEnabled: true}
|
||||
});
|
||||
AppUtil.run(Apps.findOne(appId), function (err) {
|
||||
if (err) { throw err; }
|
||||
exec('open ' + this.path, function (err) {
|
||||
if (err) { throw err; }
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
'click .btn-logs': function () {
|
||||
'click .btn-logs': function (e) {
|
||||
AppUtil.logs(this._id);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template name="dashboard_menu">
|
||||
<template name="dashboardMenu">
|
||||
<div class="dashboard-menu">
|
||||
<div class="mac-window-options">
|
||||
<div class="mac-close"><i class="fa fa-times no-display"></i></div>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
var remote = require('remote');
|
||||
|
||||
Template.dashboard_menu.events({
|
||||
Template.dashboardMenu.events({
|
||||
'click .mac-close': function () {
|
||||
remote.getCurrentWindow().hide();
|
||||
},
|
||||
|
@ -19,7 +19,7 @@ Template.dashboard_menu.events({
|
|||
}
|
||||
});
|
||||
|
||||
Template.dashboard_menu.rendered = function () {
|
||||
Template.dashboardMenu.rendered = function () {
|
||||
$('.nav a').attr('tabIndex', '-1');
|
||||
$('.nav a').attr('onfocus', 'this.blur()');
|
||||
$('.nav a').tooltip();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template name="menu_header">
|
||||
<template name="menuHeader">
|
||||
<div class="mac-window-header"><a href="#">Kitematic</a></div>
|
||||
{{> update_notification}}
|
||||
{{> updateNotification}}
|
||||
</template>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template name="modal_create_app">
|
||||
<template name="modalCreateApp">
|
||||
<div class="modal fade" id="modal-create-app" tabindex="-1" role="dialog" aria-labelledby="modal-create-app" aria-hidden="true">
|
||||
<div class="modal-dialog modal-small">
|
||||
<div class="modal-content">
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
Template.modal_create_app.helpers({
|
||||
Template.modalCreateApp.helpers({
|
||||
images: function () {
|
||||
return Images.find({status: 'READY', 'docker.Config.ExposedPorts': {$ne: null}}, {sort: {createdAt: -1}});
|
||||
}
|
||||
});
|
||||
|
||||
Template.modal_create_app.events({
|
||||
Template.modalCreateApp.events({
|
||||
'submit #form-create-app': function (e) {
|
||||
var $form = $(e.currentTarget);
|
||||
var formData = $form.serializeObject();
|
||||
|
@ -33,18 +33,16 @@ Template.modal_create_app.events({
|
|||
config: {},
|
||||
path: appPath,
|
||||
logs: [],
|
||||
createdAt: new Date()
|
||||
createdAt: new Date(),
|
||||
volumesEnabled: true
|
||||
};
|
||||
var appId = Apps.insert(appObj);
|
||||
var app = Apps.findOne(appId);
|
||||
var image = Images.findOne(app.imageId);
|
||||
Util.copyVolumes(image.path, app.name, function (err) {
|
||||
if (err) { console.error(err); }
|
||||
Docker.removeBindFolder(app.name, function (err) {
|
||||
AppUtil.run(app, function (err) {
|
||||
if (err) { console.error(err); }
|
||||
AppUtil.run(app, function (err) {
|
||||
if (err) { console.error(err); }
|
||||
});
|
||||
});
|
||||
});
|
||||
$('#modal-create-app').bind('hidden.bs.modal', function () {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template name="modal_create_image">
|
||||
<template name="modalCreateImage">
|
||||
<div class="modal fade" id="modal-create-image" tabindex="-1" role="dialog" aria-labelledby="modal-create-image" aria-hidden="true">
|
||||
<div class="modal-dialog modal-small">
|
||||
<div class="modal-content">
|
||||
|
|
|
@ -3,13 +3,13 @@ var fs = require('fs');
|
|||
var remote = require('remote');
|
||||
var dialog = remote.require('dialog');
|
||||
|
||||
Template.modal_create_image.rendered = function () {
|
||||
Template.modalCreateImage.rendered = function () {
|
||||
$('#modal-create-image').bind('hidden.bs.modal', function () {
|
||||
Router.go('dashboard_images');
|
||||
});
|
||||
};
|
||||
|
||||
Template.modal_create_image.events({
|
||||
Template.modalCreateImage.events({
|
||||
'click #btn-pick-directory': function () {
|
||||
dialog.showOpenDialog({properties: ['openDirectory']}, function (filenames) {
|
||||
if (!filenames) {
|
||||
|
@ -40,10 +40,9 @@ Template.modal_create_image.events({
|
|||
$('#picked-directory-error').html('');
|
||||
$('#picked-directory').html('');
|
||||
$('#btn-create-image').attr('disabled', 'disabled');
|
||||
$('#modal-create-image').modal('hide');
|
||||
var imageObj = {
|
||||
status: 'BUILDING',
|
||||
originPath: directory,
|
||||
path: directory,
|
||||
buildLogs: [],
|
||||
createdAt: new Date()
|
||||
};
|
||||
|
@ -51,12 +50,12 @@ Template.modal_create_image.events({
|
|||
imageObj.meta = imageMetaData;
|
||||
imageObj.tags = [imageMetaData.name + ':' + imageMetaData.version];
|
||||
var imageId = Images.insert(imageObj);
|
||||
var imagePath = path.join(Util.KITE_IMAGES_PATH, imageId);
|
||||
Images.update(imageId, {
|
||||
$set: {
|
||||
path: imagePath
|
||||
}
|
||||
|
||||
$('#modal-create-image').modal('hide');
|
||||
$('#modal-create-image').on('hidden.bs.modal', function () {
|
||||
Router.go('dashboard_images_logs', {id: imageId});
|
||||
});
|
||||
|
||||
if (imageObj.meta.logo) {
|
||||
Images.update(imageId, {
|
||||
$set: {
|
||||
|
@ -65,13 +64,10 @@ Template.modal_create_image.events({
|
|||
});
|
||||
}
|
||||
var image = Images.findOne(imageId);
|
||||
ImageUtil.saveFolder(image.originPath, imageId, function (err) {
|
||||
if (err) { console.error(err); }
|
||||
ImageUtil.pull(fs.readFileSync(path.join(image.path, 'Dockerfile'), 'utf8'), imageId, function (err) {
|
||||
if (err) { throw err; }
|
||||
ImageUtil.build(image, function (err) {
|
||||
if (err) { console.error(err); }
|
||||
});
|
||||
ImageUtil.pull(fs.readFileSync(path.join(image.path, 'Dockerfile'), 'utf8'), imageId, function (err) {
|
||||
if (err) { throw err; }
|
||||
ImageUtil.build(image, function (err) {
|
||||
if (err) { console.error(err); }
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
Handlebars.registerHelper('activeDashboardMenuItem', function (page) {
|
||||
var currentPage = Router.current(true).path.split('/')[1];
|
||||
var currentPage = Router.current(true).url.split('/')[1];
|
||||
return page === currentPage ? 'active' : '';
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('activeDashboardSubMenuItem', function (page) {
|
||||
var currentPage = Router.current(true).path.split('/')[3];
|
||||
var currentPage = Router.current(true).url.split('/')[3];
|
||||
return page === currentPage ? 'active' : '';
|
||||
});
|
||||
|
||||
Handlebars.registerHelper('currentDashboardPage', function () {
|
||||
var currentPage = Router.current(true).path.split('/')[1];
|
||||
var currentPage = Router.current(true).url.split('/')[1];
|
||||
return currentPage;
|
||||
});
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template name="dashboard_images_logs">
|
||||
<template name="dashboardImagesLogs">
|
||||
<div class="download-status">
|
||||
<div class="progress">
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: {{this.downloadPercentage}};">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template name="dashboard_images_settings">
|
||||
<template name="dashboardImagesSettings">
|
||||
<div class="section">
|
||||
<div class="left-section">
|
||||
<h4>Image Details</h4>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
var remote = require('remote');
|
||||
var dialog = remote.require('dialog');
|
||||
|
||||
Template.dashboard_images_settings.events({
|
||||
Template.dashboardImagesSettings.events({
|
||||
'click .btn-delete-image': function () {
|
||||
var imageId = this._id;
|
||||
dialog.showMessageBox({
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template name="dashboard_images">
|
||||
<template name="dashboardImages">
|
||||
<div class="header">
|
||||
<h3>Images</h3>
|
||||
<div class="options">
|
||||
|
@ -14,7 +14,7 @@
|
|||
{{#if hasItem images}}
|
||||
<div class="images line-item-collection">
|
||||
{{#each images}}
|
||||
{{> dashboard_single_image}}
|
||||
{{> dashboardSingleImage}}
|
||||
{{/each}}
|
||||
</div>
|
||||
{{else}}
|
||||
|
@ -30,6 +30,6 @@
|
|||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{> modal_create_app}}
|
||||
{{> modal_create_image}}
|
||||
{{> modalCreateApp}}
|
||||
{{> modalCreateImage}}
|
||||
</template>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
Template.dashboard_images.helpers({
|
||||
Template.dashboardImages.helpers({
|
||||
images: function () {
|
||||
return Images.find({}, {sort: {createdAt: -1}});
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template name="dashboard_single_image">
|
||||
<template name="dashboardSingleImage">
|
||||
<div class="image">
|
||||
<h5>
|
||||
{{#if $eq status 'READY'}}
|
||||
|
@ -35,7 +35,7 @@
|
|||
<a onclick="trackLink('open image folder')" href="#" class="btn-icon btn-folder" target="_blank" data-toggle="tooltip" data-placement="bottom" title="Folder"><span class="typcn typcn-folder-open"></span></a>
|
||||
{{/if}}
|
||||
{{#if $neq status 'BUILDING'}}
|
||||
{{#if originPath}}
|
||||
{{#if $or path originPath}}
|
||||
<a onclick="trackLink('rebuild image')" href="#" class="btn-icon btn-rebuild" target="_blank" data-toggle="tooltip" data-placement="bottom" title="Rebuild"><span class="typcn typcn-refresh-outline"></span></a>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
Template.dashboard_single_image.rendered = function () {
|
||||
Template.dashboardSingleImage.rendered = function () {
|
||||
Meteor.setInterval(function () {
|
||||
$('.btn-icon').tooltip();
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
Template.dashboard_single_image.events({
|
||||
Template.dashboardSingleImage.events({
|
||||
'click .btn-create-app': function () {
|
||||
$('#modal-create-app').modal('show');
|
||||
$('#form-create-app').find('input[name="imageId"]').val(this._id);
|
||||
|
@ -16,7 +16,8 @@ Template.dashboard_single_image.events({
|
|||
if (err) { throw err; }
|
||||
});
|
||||
},
|
||||
'click .btn-rebuild': function () {
|
||||
'click .btn-rebuild': function (e) {
|
||||
e.preventDefault();
|
||||
$('.btn-icon').tooltip('hide');
|
||||
ImageUtil.rebuild(this._id, function (err) {
|
||||
if (err) { console.error(err); }
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
<div class="container text-left">
|
||||
<div class="content">
|
||||
{{#if currentSetupFailedError}}
|
||||
{{> radial_progress progress=100 class="radial-negative"}}
|
||||
{{> radialProgress progress=100 class="radial-negative"}}
|
||||
<p>Error: {{currentSetupFailedError}}</p>
|
||||
{{else}}
|
||||
{{#if currentSetupStepProgress}}
|
||||
{{> radial_progress progress=currentSetupStepProgress}}
|
||||
{{> radialProgress progress=currentSetupStepProgress}}
|
||||
{{else}}
|
||||
{{> radial_spinner }}
|
||||
{{> radialSpinner }}
|
||||
{{/if}}
|
||||
<p>{{currentSetupStepMessage}}</p>
|
||||
{{/if}}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<template name="dashboard_apps_layout">
|
||||
<template name="dashboardAppsLayout">
|
||||
{{setTitle this.name}}
|
||||
<input id="appId" type="hidden" value="{{this._id}}">
|
||||
<div class="dashboard">
|
||||
<div class="container">
|
||||
<div class="dashboard-row">
|
||||
{{> dashboard_menu}}
|
||||
{{> dashboardMenu}}
|
||||
<div class="dashboard-body">
|
||||
{{> menu_header}}
|
||||
{{> menuHeader}}
|
||||
<div class="header">
|
||||
<h3>
|
||||
<a href="/apps" onclick="trackLink('back to containers')">Containers</a> » {{this.name}}
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
Template.dashboard_apps_layout.rendered = function () {
|
||||
Template.dashboardAppsLayout.rendered = function () {
|
||||
Meteor.setInterval(function () {
|
||||
$('.header .icons a').tooltip();
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
Template.dashboard_apps_layout.events({
|
||||
Template.dashboardAppsLayout.events({
|
||||
'click .btn-view': function (e) {
|
||||
try {
|
||||
var open = require('open');
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<template name="dashboard_images_layout">
|
||||
<template name="dashboardImagesLayout">
|
||||
{{setTitle this.meta.name}}
|
||||
<input id="imageId" type="hidden" value="{{this._id}}">
|
||||
<div class="dashboard">
|
||||
<div class="container">
|
||||
<div class="dashboard-row">
|
||||
{{> dashboard_menu}}
|
||||
{{> dashboardMenu}}
|
||||
<div class="dashboard-body">
|
||||
{{> menu_header}}
|
||||
{{> menuHeader}}
|
||||
<div class="header">
|
||||
<h3>
|
||||
<a href="/images" onclick="trackLink('back to images')">Images</a> » {{this.meta.name}}
|
||||
|
@ -37,6 +37,6 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{> modal_create_app}}
|
||||
{{> modalCreateApp}}
|
||||
</div>
|
||||
</template>
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
Template.dashboard_images_layout.rendered = function () {
|
||||
Template.dashboardImagesLayout.rendered = function () {
|
||||
Meteor.setInterval(function () {
|
||||
$('.header .icons a').tooltip();
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
Template.dashboard_images_layout.events({
|
||||
Template.dashboardImagesLayout.events({
|
||||
'click .btn-create-app': function () {
|
||||
$('#modal-create-app').modal('show');
|
||||
$('#form-create-app').find('input[name="imageId"]').val(this._id);
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
<template name="dashboard_layout">
|
||||
<template name="dashboardLayout">
|
||||
<div class="dashboard">
|
||||
{{setTitle}}
|
||||
<div class="container">
|
||||
<div class="dashboard-row">
|
||||
{{> dashboard_menu}}
|
||||
{{> dashboardMenu}}
|
||||
<div class="dashboard-body">
|
||||
<div class="mac-window-header"><a href="#">Kitematic</a></div>
|
||||
{{> update_notification}}
|
||||
{{> updateNotification}}
|
||||
{{> yield}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template name="dashboard_settings">
|
||||
<template name="dashboardSettings">
|
||||
<div class="header">
|
||||
<h3>Settings</h3>
|
||||
</div>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
var remote = require('remote');
|
||||
var dialog = remote.require('dialog');
|
||||
|
||||
Template.dashboard_settings.events({
|
||||
Template.dashboardSettings.events({
|
||||
'click .btn-start-boot2docker': function (e) {
|
||||
var $btn = $(e.currentTarget);
|
||||
$btn.html('Starting Boot2Docker...');
|
||||
|
@ -53,7 +53,7 @@ Template.dashboard_settings.events({
|
|||
}
|
||||
});
|
||||
|
||||
Template.dashboard_settings.helpers({
|
||||
Template.dashboardSettings.helpers({
|
||||
settings: function () {
|
||||
return Settings.findOne({});
|
||||
},
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template name="radial_progress">
|
||||
<template name="radialProgress">
|
||||
<div class="radial-progress {{class}}" data-progress="{{progress}}">
|
||||
<div class="circle">
|
||||
<div class="mask full">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template name="radial_spinner">
|
||||
<template name="radialSpinner">
|
||||
<div class="radial-spinner radial-progress" data-progress="90">
|
||||
<div class="circle">
|
||||
<div class="mask full">
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<template name="update_notification">
|
||||
<template name="updateNotification">
|
||||
{{#if updateAvailable}}
|
||||
<div class="update-alert" role="alert"><span class="update-text">A new version of Kitematic is available.</span> <a href="#" class="btn btn-action-inverse btn-inverse btn-xs btn-update">Restart to Update</a></div>
|
||||
{{/if}}
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
var ipc = require('ipc');
|
||||
|
||||
Template.update_notification.helpers({
|
||||
Template.updateNotification.helpers({
|
||||
updateAvailable: function () {
|
||||
return Session.get('updateAvailable');
|
||||
}
|
||||
});
|
||||
|
||||
Template.update_notification.events({
|
||||
Template.updateNotification.events({
|
||||
'click .btn-update': function (e) {
|
||||
ipc.send('command', 'application:quit-install');
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ Apps.COMMON_WEB_PORTS = [
|
|||
3000,
|
||||
5000,
|
||||
2368,
|
||||
443
|
||||
];
|
||||
|
||||
Apps.allow({
|
||||
|
@ -31,17 +32,37 @@ Apps.helpers({
|
|||
},
|
||||
ports: function () {
|
||||
var app = this;
|
||||
if (app.docker && app.docker.NetworkSettings.Ports) {
|
||||
var ports = _.map(_.keys(app.docker.NetworkSettings.Ports), function (portObj) {
|
||||
var port = parseInt(portObj.split('/')[0], 10);
|
||||
return port;
|
||||
});
|
||||
return ports.join(', ');
|
||||
} else {
|
||||
return null;
|
||||
if (!app.docker || !app.docker.NetworkSettings.Ports) {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
url: function () {
|
||||
return 'http://localhost:80'; // CHANGE ME
|
||||
var results = _.map(app.docker.NetworkSettings.Ports, function (value, key) {
|
||||
var portProtocolPair = key.split('/');
|
||||
var res = {
|
||||
'port': parseInt(portProtocolPair[0]),
|
||||
'protocol': portProtocolPair[1]
|
||||
};
|
||||
if (value.length) {
|
||||
var port = value[0].HostPort;
|
||||
res['hostIp'] = Docker.hostIp;
|
||||
res['hostPort'] = port;
|
||||
res['web'] = Apps.COMMON_WEB_PORTS.indexOf(res.port) !== -1;
|
||||
res['url'] = 'http://' + Docker.hostIp + ':' + port;
|
||||
}
|
||||
return res;
|
||||
});
|
||||
|
||||
results.sort(function (a, b) {
|
||||
// prefer lower ports
|
||||
if (a.web && b.web) {
|
||||
return b.port - a.port;
|
||||
}
|
||||
|
||||
if (a.web) {
|
||||
return -1;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
});
|
||||
return results;
|
||||
}
|
||||
});
|
||||
|
|
|
@ -13,12 +13,12 @@
|
|||
"url": "https://raw.githubusercontent.com/kitematic/kitematic/master/LICENSE"
|
||||
}],
|
||||
"main": "index.js",
|
||||
"version": "0.3.0",
|
||||
"version": "0.4.0",
|
||||
"dependencies": {
|
||||
"ansi-to-html": "0.2.0",
|
||||
"async": "^0.9.0",
|
||||
"chokidar": "git+https://github.com/usekite/chokidar.git",
|
||||
"dockerode": "2.0.3",
|
||||
"dockerode": "2.0.4",
|
||||
"exec": "^0.1.2",
|
||||
"moment": "2.8.1",
|
||||
"ncp": "0.6.0",
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This script must be run as root and sets up Mac OS X to route all .kite domains to the virtual box VM with the name
|
||||
# 'boot2docker-vm'. It does the following:
|
||||
# 1) Adds a file under /etc/resolver/kite
|
||||
# 2) Sets up a LaunchAgent for adding entries to the route table to route all requests to the Docker subnet (172.17.0.0/16)
|
||||
# And expects the $IFNAME variable to contain the interface on which to send traffic to the boot2docker VM.
|
||||
|
||||
mkdir -p /etc/resolver
|
||||
echo "nameserver 172.17.42.1" > /etc/resolver/kite
|
||||
|
||||
DIR=$(dirname "$0")
|
||||
USER=`w -h | sort -u -t' ' -k1,1 | awk '{print $1}'`
|
||||
|
||||
/bin/rm -rf /Library/LaunchDaemons/com.kitematic.route.plist
|
||||
echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
||||
<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
|
||||
<plist version=\"1.0\">
|
||||
<dict>
|
||||
<key>Label</key>
|
||||
<string>com.kitematic.route</string>
|
||||
<key>ProgramArguments</key>
|
||||
<array>
|
||||
<string>bash</string>
|
||||
<string>-c</string>
|
||||
<string>/usr/sbin/scutil -w State:/Network/Interface/$IFNAME/IPv4 -t 0;sudo /sbin/route -n add -net 172.17.0.0 -netmask 255.255.0.0 -gateway $GATEWAY</string>
|
||||
</array>
|
||||
<key>KeepAlive</key>
|
||||
<false/>
|
||||
<key>RunAtLoad</key>
|
||||
<true/>
|
||||
<key>LaunchOnlyOnce</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>" > /Library/LaunchAgents/com.kitematic.route.plist
|
||||
|
||||
# Add entries to routing table for Kitematic boot2docker-vms
|
||||
/sbin/route delete -net 172.17.0.0 -netmask 255.255.0.0 -gateway $GATEWAY > /dev/null 2>&1 || true
|
||||
/sbin/route -n add -net 172.17.0.0 -netmask 255.255.0.0 -gateway $GATEWAY
|
|
@ -34,17 +34,14 @@ end tell
|
|||
EOF
|
||||
|
||||
else
|
||||
osascript > /dev/null <<EOF
|
||||
|
||||
tell application "Terminal"
|
||||
activate
|
||||
end tell
|
||||
tell application "System Events"
|
||||
tell process "Terminal" to keystroke "t" using command down
|
||||
end
|
||||
osascript > /dev/null <<EOF
|
||||
tell application "Terminal" to activate
|
||||
delay 0.4
|
||||
tell application "System Events" to keystroke "t" using command down
|
||||
tell application "Terminal"
|
||||
do script "clear && $*" in window 1
|
||||
end tell
|
||||
|
||||
EOF
|
||||
|
||||
fi
|
||||
|
|
|
@ -30,8 +30,8 @@ popd
|
|||
|
||||
pushd $BASE
|
||||
|
||||
rm -rf dist/osx
|
||||
mkdir -p dist/osx/
|
||||
rm -rf ./dist/osx
|
||||
mkdir -p ./dist/osx/
|
||||
|
||||
DIST_APP=Kitematic.app
|
||||
|
||||
|
@ -56,9 +56,7 @@ cp -v resources/* dist/osx/$DIST_APP/Contents/Resources/app/resources/ || :
|
|||
cecho "-----> Copying icon to $DIST_APP" $blue
|
||||
cp kitematic.icns dist/osx/$DIST_APP/Contents/Resources/atom.icns
|
||||
|
||||
chmod +x dist/osx/$DIST_APP/Contents/Resources/app/resources/install
|
||||
chmod +x dist/osx/$DIST_APP/Contents/Resources/app/resources/terminal
|
||||
chmod +x dist/osx/$DIST_APP/Contents/Resources/app/resources/unison
|
||||
chmod +x dist/osx/$DIST_APP/Contents/Resources/app/resources/node
|
||||
|
||||
chmod -R u+w dist/osx/$DIST_APP/Contents/Resources/app/bundle
|
||||
|
|
|
@ -4,11 +4,12 @@ DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
|
|||
BASE=$DIR/..
|
||||
|
||||
export ROOT_URL=https://localhost:3000
|
||||
export DOCKER_HOST=http://192.168.59.103
|
||||
export DOCKER_PORT=2375
|
||||
export DIR=$BASE
|
||||
|
||||
cd $BASE/meteor
|
||||
exec 3< <(meteor --settings $BASE/meteor/settings_dev.json)
|
||||
sed '/App running at/q' <&3 ; cat <&3 &
|
||||
NODE_ENV=development $BASE/cache/atom-shell/Atom.app/Contents/MacOS/Atom $BASE
|
||||
kill $(ps aux | grep '.*node.*kitematic' | awk '{print $2}')
|
||||
kill $(ps aux | grep '.*mongod.*kitematic' | awk '{print $2}')
|
||||
|
||||
|
|
Loading…
Reference in New Issue