diff --git a/index.js b/index.js index 9838f3c374..66f0e4c857 100644 --- a/index.js +++ b/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(); diff --git a/meteor/.meteor/release b/meteor/.meteor/release index 7057f80807..87bf495278 100755 --- a/meteor/.meteor/release +++ b/meteor/.meteor/release @@ -1 +1 @@ -METEOR@0.9.4 +METEOR@1.0 diff --git a/meteor/.meteor/versions b/meteor/.meteor/versions index 7664d0329a..c821689bcb 100644 --- a/meteor/.meteor/versions +++ b/meteor/.meteor/versions @@ -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 diff --git a/meteor/client/lib/apputil.js b/meteor/client/lib/apputil.js index 8546070511..db389f0c43 100644 --- a/meteor/client/lib/apputil.js +++ b/meteor/client/lib/apputil.js @@ -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); diff --git a/meteor/client/lib/boot2docker.js b/meteor/client/lib/boot2docker.js index 4b9f7cf782..40d0f92ade 100644 --- a/meteor/client/lib/boot2docker.js +++ b/meteor/client/lib/boot2docker.js @@ -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) { diff --git a/meteor/client/lib/docker.js b/meteor/client/lib/docker.js index 30f9285640..00128f473f 100644 --- a/meteor/client/lib/docker.js +++ b/meteor/client/lib/docker.js @@ -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); - }); -}; diff --git a/meteor/client/lib/imageutil.js b/meteor/client/lib/imageutil.js index 705710e409..83618ab27f 100644 --- a/meteor/client/lib/imageutil.js +++ b/meteor/client/lib/imageutil.js @@ -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); } }); diff --git a/meteor/client/lib/router.js b/meteor/client/lib/router.js index 4279a7756a..33db518057 100755 --- a/meteor/client/lib/router.js +++ b/meteor/client/lib/router.js @@ -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'); } }); diff --git a/meteor/client/lib/setup.js b/meteor/client/lib/setup.js index fec4e28276..0b688b34c2 100644 --- a/meteor/client/lib/setup.js +++ b/meteor/client/lib/setup.js @@ -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) { diff --git a/meteor/client/lib/startup.js b/meteor/client/lib/startup.js index b4fefc155d..c53faaee3e 100644 --- a/meteor/client/lib/startup.js +++ b/meteor/client/lib/startup.js @@ -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); + } + }); }); diff --git a/meteor/client/lib/util.js b/meteor/client/lib/util.js index 074a266937..8d8c54a33f 100755 --- a/meteor/client/lib/util.js +++ b/meteor/client/lib/util.js @@ -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')); }; diff --git a/meteor/client/main.js b/meteor/client/main.js index 9a8f4ec0e8..a35249fa19 100755 --- a/meteor/client/main.js +++ b/meteor/client/main.js @@ -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); +}; \ No newline at end of file diff --git a/meteor/client/stylesheets/dashboard.import.less b/meteor/client/stylesheets/dashboard.import.less index 81413260dd..2bbb30aeea 100755 --- a/meteor/client/stylesheets/dashboard.import.less +++ b/meteor/client/stylesheets/dashboard.import.less @@ -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; } diff --git a/meteor/client/views/dashboard/apps/dashboard-apps-logs.html b/meteor/client/views/dashboard/apps/dashboard-apps-logs.html index 193d2db951..3d4f47645b 100644 --- a/meteor/client/views/dashboard/apps/dashboard-apps-logs.html +++ b/meteor/client/views/dashboard/apps/dashboard-apps-logs.html @@ -1,4 +1,4 @@ -