From a656151a3fa2e5858e82e00da722ee995b930f39 Mon Sep 17 00:00:00 2001 From: Justin Smith Date: Sat, 30 Aug 2014 11:19:28 -0700 Subject: [PATCH 01/12] Small text change in settings --- meteor/client/views/dashboard/settings/dashboard-settings.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/meteor/client/views/dashboard/settings/dashboard-settings.html b/meteor/client/views/dashboard/settings/dashboard-settings.html index 9b3f6adc3f..cf615b4d5b 100644 --- a/meteor/client/views/dashboard/settings/dashboard-settings.html +++ b/meteor/client/views/dashboard/settings/dashboard-settings.html @@ -8,7 +8,7 @@ {{#if $.Session.equals 'boot2dockerState' 'poweroff'}}

Please start Boot2Docker for Kitematic to work properly!

{{else}} -

All apps run in a Linux VM included with Kitematic. It needs to be turned to run apps.

+

All apps run in a Linux VM included with Kitematic. It needs to be turned on to run apps.

{{/if}}
From bff96466971f49fc70b7241239798462087d1c42 Mon Sep 17 00:00:00 2001 From: Michael Chiang Date: Sat, 30 Aug 2014 16:26:05 -0700 Subject: [PATCH 02/12] Emergency log submission update. --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 26c362617f..1e4205d50b 100755 --- a/README.md +++ b/README.md @@ -1,5 +1,10 @@ # [Kitematic](https://kitematic.com) +**Note:** If the installer gets stuck at any step for more than 1 minute, there is probably an error. Please help us troubleshoot by running it from the command line, and submit the logs to [contact@kitematic.com](mailto:contact@kitematic.com). + +1. `cd ` +2. Run `./Kitematic.app/Contents/MacOS/node-webkit` + Kitematic is still in Beta. Any effort in helping us find issues and improving the experience is greatly appreciated! [Fixes for Known Issues](http://kitematic.com/docs/known-issue-fixes) From 8955d6bcda8e94a3c3839189ae124ad612a8db3b Mon Sep 17 00:00:00 2001 From: Michael Chiang Date: Sat, 30 Aug 2014 17:05:47 -0700 Subject: [PATCH 03/12] Updated contact information. --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index 1e4205d50b..c0559fd0ba 100755 --- a/README.md +++ b/README.md @@ -78,20 +78,28 @@ For transparency into our release cycle and in striving to maintain backward com ## Creators +Team E-mail: [contact@kitematic.com](mailto:contact@kitematic.com) + **Sean Li** - - +- Email: [sean@kitematic.com](mailto:sean@kitematic.com) +- [LinkedIn](https://www.linkedin.com/in/lishang) **Jeffrey Morgan** - - +- Email: [jeff@kitematic.com](mailto:jeff@kitematic.com) +- [LinkedIn](https://www.linkedin.com/in/jeffdmorgan) **Michael Chiang** - - +- Email: [mike@kitematic.com](mailto:mike@kitematic.com) +- [LinkedIn](https://www.linkedin.com/in/mchiang0610) ## Copyright and License From 9d5fa7ad6963b0fce06d31bf2e11f4ede9225cf7 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Sun, 31 Aug 2014 19:18:11 -0700 Subject: [PATCH 04/12] Moved basic Docker operations to namespace. --- meteor/.jshintrc | 16 ++--------- meteor/server/docker.js | 64 +++++++++++++++++++++-------------------- 2 files changed, 36 insertions(+), 44 deletions(-) diff --git a/meteor/.jshintrc b/meteor/.jshintrc index e2c8f682e4..2f77f05ffa 100755 --- a/meteor/.jshintrc +++ b/meteor/.jshintrc @@ -128,7 +128,7 @@ // Packages "Fiber": true, "moment": true, - "Docker": true, + "Dockerode": true, "byline": true, "fs": true, "zlib": true, @@ -142,6 +142,7 @@ "chokidar": true, "docker": true, "async": true, + "child_process": true, // Collections "SimpleSchema": false, @@ -161,6 +162,7 @@ "SetupController": true, // Server and Client + "Docker": true, "boot2dockerexec": true, "getBinDir": true, "getBoot2DockerIp": true, @@ -202,16 +204,8 @@ "loadKiteVolumes": true, "getAppLogs": true, "hasDockerfile": true, - "runContainer": true, - "runContainerSync": true, - "restartContainer": true, - "restartContainerSync": true, "createTarFile": true, "createTarFileSync": true, - "getImageData": true, - "getImageDataSync": true, - "removeImage": true, - "removeImageSync": true, "deleteImage": true, "checkDefaultImages": true, "resolveDefaultImages": true, @@ -239,11 +233,7 @@ "FormSchema": true, "showFormSuccess": true, "resetForm": true, - "removeContainer": true, - "removeContainerSync": true, "deleteAppSync": true, - "getContainerData": true, - "getContainerDataSync": true, // Testing "require": false, diff --git a/meteor/server/docker.js b/meteor/server/docker.js index d71b12688b..f5a3a022fe 100755 --- a/meteor/server/docker.js +++ b/meteor/server/docker.js @@ -1,16 +1,18 @@ -Docker = Meteor.require('dockerode'); +Dockerode = Meteor.require('dockerode'); var Convert = Meteor.require('ansi-to-html'); var convert = new Convert(); var DOCKER_HOST='192.168.59.103'; -docker = new Docker({host: '192.168.59.103', port: '2375'}); +docker = new Dockerode({host: '192.168.59.103', port: '2375'}); + +Docker = {}; hasDockerfile = function (directory) { return fs.existsSync(path.join(directory, 'Dockerfile')); }; -removeContainer = function (containerId, callback) { +Docker.removeContainer = function (containerId, callback) { var container = docker.getContainer(containerId); container.kill(function (err) { if (err) { callback(err); return; } @@ -22,8 +24,8 @@ removeContainer = function (containerId, callback) { }); }; -removeContainerSync = function (containerId) { - return Meteor._wrapAsync(removeContainer)(containerId); +Docker.removeContainerSync = function (containerId) { + return Meteor._wrapAsync(Docker.removeContainer)(containerId); }; deleteApp = function (app, callback) { @@ -32,7 +34,7 @@ deleteApp = function (app, callback) { return; } try { - removeContainerSync(app.docker.Id); + Docker.removeContainerSync(app.docker.Id); } catch (e) { console.error(e); } @@ -43,7 +45,7 @@ deleteAppSync = function (app) { return Meteor._wrapAsync(deleteApp)(app); }; -getContainerData = function (containerId, callback) { +Docker.getContainerData = function (containerId, callback) { var container = docker.getContainer(containerId); container.inspect(function (err, data) { if (err) { @@ -59,11 +61,11 @@ getContainerData = function (containerId, callback) { }); }; -getContainerDataSync = function (containerId) { - return Meteor._wrapAsync(getContainerData)(containerId); +Docker.getContainerDataSync = function (containerId) { + return Meteor._wrapAsync(Docker.getContainerData)(containerId); }; -runContainer = function (app, image, callback) { +Docker.runContainer = function (app, image, callback) { var envParam = []; _.each(_.keys(app.config), function (key) { var builtStr = key + '=' + app.config[key]; @@ -100,11 +102,11 @@ runContainer = function (app, image, callback) { }); }; -runContainerSync = function (app, image) { - return Meteor._wrapAsync(runContainer)(app, image); +Docker.runContainerSync = function (app, image) { + return Meteor._wrapAsync(Docker.runContainer)(app, image); }; -restartContainer = function (containerId, callback) { +Docker.restartContainer = function (containerId, callback) { var container = docker.getContainer(containerId); container.restart(function (err) { if (err) { @@ -117,8 +119,8 @@ restartContainer = function (containerId, callback) { }); }; -restartContainerSync = function (containerId) { - return Meteor._wrapAsync(restartContainer)(containerId); +Docker.restartContainerSync = function (containerId) { + return Meteor._wrapAsync(Docker.restartContainer)(containerId); }; var getFromImage = function (dockerfile) { @@ -135,11 +137,11 @@ var getFromImage = function (dockerfile) { restartApp = function (app, callback) { if (app.docker && app.docker.Id) { try { - restartContainerSync(app.docker.Id); + Docker.restartContainerSync(app.docker.Id); } catch (e) { console.error(e); } - var containerData = getContainerDataSync(app.docker.Id); + var containerData = Docker.getContainerDataSync(app.docker.Id); Fiber(function () { Apps.update(app._id, {$set: { status: 'READY', @@ -209,7 +211,7 @@ var convertVolumeObjToArray = function (obj) { return result; }; -getImageData = function (imageId, callback) { +Docker.getImageData = function (imageId, callback) { var image = docker.getImage(imageId.toLowerCase()); image.inspect(function (err, data) { if (err) { @@ -224,11 +226,11 @@ getImageData = function (imageId, callback) { }); }; -getImageDataSync = function (imageId) { - return Meteor._wrapAsync(getImageData)(imageId); +Docker.getImageDataSync = function (imageId) { + return Meteor._wrapAsync(Docker.getImageData)(imageId); }; -removeImage = function (imageId, callback) { +Docker.removeImage = function (imageId, callback) { var image = docker.getImage(imageId.toLowerCase()); image.remove({force: true}, function (err) { if (err) { callback(err); return; } @@ -237,8 +239,8 @@ removeImage = function (imageId, callback) { }); }; -removeImageSync = function (imageId) { - return Meteor._wrapAsync(removeImage)(imageId); +Docker.removeImageSync = function (imageId) { + return Meteor._wrapAsync(Docker.removeImage)(imageId); }; deleteImage = function (image, callback) { @@ -247,7 +249,7 @@ deleteImage = function (image, callback) { return; } try { - removeImageSync(image.docker.Id); + Docker.removeImageSync(image.docker.Id); } catch (e) { console.error(e); } @@ -374,7 +376,7 @@ reloadDefaultContainers = function (callback) { async.until(function () { return ready; }, function (callback) { - docker.listContainers(function (err, containers) { + docker.listContainers(function (err) { if (!err) { ready = true; } @@ -505,7 +507,7 @@ pullImageFromDockerfile = function (dockerfile, imageId, callback) { console.log('From image: ' + fromImage); var installedImage = null; try { - installedImage = getImageDataSync(fromImage); + installedImage = Docker.getImageDataSync(fromImage); } catch (e) { console.error(e); } @@ -593,7 +595,7 @@ buildImage = function (image, callback) { Fiber(function () { var imageData = null; try { - imageData = getImageDataSync(image._id); + imageData = Docker.getImageDataSync(image._id); Images.update(image._id, { $set: { docker: imageData, @@ -614,7 +616,7 @@ buildImage = function (image, callback) { } if (oldImageId && imageData && oldImageId !== imageData.Id) { try { - removeImageSync(oldImageId); + Docker.removeImageSync(oldImageId); } catch (e) { console.error(e); } @@ -631,11 +633,11 @@ Meteor.methods({ this.unblock(); var image = Images.findOne({_id: app.imageId}); try { - removeContainerSync(app.name); + Docker.removeContainerSync(app.name); } catch (e) {} try { - var container = runContainerSync(app, image); - var containerData = getContainerDataSync(container.id); + var container = Docker.runContainerSync(app, image); + var containerData = Docker.getContainerDataSync(container.id); Meteor.setTimeout(function () { Apps.update(app._id, {$set: { docker: containerData, From e59c03d620be56233f6609bc6348586d64c2e185 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Sun, 31 Aug 2014 19:56:18 -0700 Subject: [PATCH 05/12] Moved kite functions to utilities. --- meteor/collections/apps.js | 11 +++++++ meteor/server/apps.js | 15 +++------ meteor/server/constants.js | 24 ++++++++++++++ meteor/server/docker.js | 7 ++++ meteor/server/images.js | 1 + meteor/server/kite.js | 59 ---------------------------------- meteor/server/lib/utilities.js | 35 ++++++++++++++++++++ 7 files changed, 82 insertions(+), 70 deletions(-) create mode 100644 meteor/server/constants.js delete mode 100755 meteor/server/kite.js diff --git a/meteor/collections/apps.js b/meteor/collections/apps.js index 3b0ff8b147..05006eb8e2 100755 --- a/meteor/collections/apps.js +++ b/meteor/collections/apps.js @@ -116,3 +116,14 @@ Apps.helpers({ }); Apps.attachSchema(schemaApps); + +Apps.after.remove(function (userId, app) { + deleteApp(app, function (err) { + if (err) { console.error(err); } + var appPath = path.join(KITE_PATH, app.name); + deleteFolder(appPath); + removeBindFolder(app.name, function () { + console.log('Deleted Kite ' + app.name + ' directory.'); + }); + }); +}); diff --git a/meteor/server/apps.js b/meteor/server/apps.js index af9383afa3..07a51cfa58 100755 --- a/meteor/server/apps.js +++ b/meteor/server/apps.js @@ -29,6 +29,7 @@ recoverApps = function (callback) { Meteor.methods({ recoverApps: function () { + this.unblock(); return Meteor._wrapAsync(recoverApps)(); }, configVar: function (appId, configVars) { @@ -48,19 +49,10 @@ Meteor.methods({ if (!app) { throw new Meteor.Error(403, 'No app found with this ID'); } - deleteApp(app, function (err) { - if (err) { console.error(err); } - var appPath = path.join(KITE_PATH, app.name); - deleteFolder(appPath); - removeBindFolder(app.name, function () { - console.log('Deleted Kite ' + app.name + ' directory.'); - Fiber(function () { - Apps.remove({_id: app._id}); - }).run(); - }); - }); + Apps.remove({_id: app._id}); }, createApp: function (formData) { + this.unblock(); var validationResult = formValidate(formData, FormSchema.formCreateApp); if (validationResult.errors) { throw new Meteor.Error(400, 'Validation Failed.', validationResult.errors); @@ -123,6 +115,7 @@ Meteor.methods({ } }, resolveWatchers: function () { + this.unblock(); return Meteor._wrapAsync(resolveWatchers)(); } }); diff --git a/meteor/server/constants.js b/meteor/server/constants.js new file mode 100644 index 0000000000..e3fd37c46e --- /dev/null +++ b/meteor/server/constants.js @@ -0,0 +1,24 @@ +KITE_PATH = path.join(getHomePath(), 'Kitematic'); +KITE_TAR_PATH = path.join(KITE_PATH, '.tar'); +KITE_IMAGES_PATH = path.join(KITE_PATH, '.images'); + +if (!fs.existsSync(KITE_PATH)) { + console.log('Created Kitematic directory.'); + fs.mkdirSync(KITE_PATH, function (err) { + if (err) { throw err; } + }); +} + +if (!fs.existsSync(KITE_TAR_PATH)) { + console.log('Created Kitematic .tar directory.'); + fs.mkdirSync(KITE_TAR_PATH, function (err) { + if (err) { throw err; } + }); +} + +if (!fs.existsSync(KITE_IMAGES_PATH)) { + console.log('Created Kitematic .images directory.'); + fs.mkdirSync(KITE_IMAGES_PATH, function (err) { + if (err) { throw err; } + }); +} diff --git a/meteor/server/docker.js b/meteor/server/docker.js index f5a3a022fe..c46ec6de30 100755 --- a/meteor/server/docker.js +++ b/meteor/server/docker.js @@ -632,12 +632,14 @@ Meteor.methods({ runApp: function (app) { this.unblock(); var image = Images.findOne({_id: app.imageId}); + // Delete old container if one already exists try { Docker.removeContainerSync(app.name); } catch (e) {} try { var container = Docker.runContainerSync(app, image); var containerData = Docker.getContainerDataSync(container.id); + // Set a delay for app to spin up Meteor.setTimeout(function () { Apps.update(app._id, {$set: { docker: containerData, @@ -652,18 +654,23 @@ Meteor.methods({ return DOCKER_HOST; }, reloadDefaultContainers: function () { + this.unblock(); return Meteor._wrapAsync(reloadDefaultContainers)(); }, checkDefaultImages: function () { + this.unblock(); return Meteor._wrapAsync(checkDefaultImages)(); }, resolveDefaultImages: function () { + this.unblock(); return Meteor._wrapAsync(resolveDefaultImages)(); }, checkDefaultContainers: function () { + this.unblock(); return Meteor._wrapAsync(checkDefaultContainers)(); }, resolveDefaultContainers: function () { + this.unblock(); return Meteor._wrapAsync(resolveDefaultContainers)(); } }); diff --git a/meteor/server/images.js b/meteor/server/images.js index 5429dd53b1..f83f21da7f 100755 --- a/meteor/server/images.js +++ b/meteor/server/images.js @@ -125,6 +125,7 @@ Meteor.methods({ }); }, validateDirectory: function (directory) { + this.unblock(); if (!hasDockerfile(directory)) { throw new Meteor.Error(400, "Only directories with Dockerfiles are supported now."); } diff --git a/meteor/server/kite.js b/meteor/server/kite.js deleted file mode 100755 index 712635616a..0000000000 --- a/meteor/server/kite.js +++ /dev/null @@ -1,59 +0,0 @@ -KITE_PATH = path.join(getHomePath(), 'Kitematic'); -KITE_TAR_PATH = path.join(KITE_PATH, '.tar'); -KITE_IMAGES_PATH = path.join(KITE_PATH, '.images'); - -if (!fs.existsSync(KITE_PATH)) { - console.log('Created Kitematic directory.'); - fs.mkdirSync(KITE_PATH, function (err) { - if (err) { throw err; } - }); -} - -if (!fs.existsSync(KITE_TAR_PATH)) { - console.log('Created Kitematic .tar directory.'); - fs.mkdirSync(KITE_TAR_PATH, function (err) { - if (err) { throw err; } - }); -} - -if (!fs.existsSync(KITE_IMAGES_PATH)) { - console.log('Created Kitematic .images directory.'); - fs.mkdirSync(KITE_IMAGES_PATH, function (err) { - if (err) { throw err; } - }); -} - -getImageJSON = function (directory) { - var KITE_JSON_PATH = path.join(directory, 'image.json'); - if (fs.existsSync(KITE_JSON_PATH)) { - var data = fs.readFileSync(KITE_JSON_PATH, 'utf8'); - return JSON.parse(data); - } else { - return null; - } -}; - -loadKiteVolumes = function (directory, appName) { - var KITE_VOLUMES_PATH = path.join(directory, 'volumes'); - if (fs.existsSync(KITE_VOLUMES_PATH)) { - var destinationPath = path.join(KITE_PATH, appName); - copyFolder(KITE_VOLUMES_PATH, destinationPath); - console.log('Copied volumes for: ' + appName); - } -}; - -saveImageFolder = function (directory, imageId, callback) { - var destinationPath = path.join(KITE_IMAGES_PATH, imageId); - if (!fs.existsSync(destinationPath)) { - fs.mkdirSync(destinationPath, function (err) { - if (err) { callback(err); return; } - }); - copyFolder(directory, destinationPath); - console.log('Copied image folder for: ' + imageId); - callback(null); - } -}; - -saveImageFolderSync = function (directory, imageId) { - return Meteor._wrapAsync(saveImageFolder)(directory, imageId); -}; diff --git a/meteor/server/lib/utilities.js b/meteor/server/lib/utilities.js index 6b4d68df1a..4be5a0edaa 100755 --- a/meteor/server/lib/utilities.js +++ b/meteor/server/lib/utilities.js @@ -51,3 +51,38 @@ copyFolder = function (src, dest) { } } }; + +getImageJSON = function (directory) { + var KITE_JSON_PATH = path.join(directory, 'image.json'); + if (fs.existsSync(KITE_JSON_PATH)) { + var data = fs.readFileSync(KITE_JSON_PATH, 'utf8'); + return JSON.parse(data); + } else { + return null; + } +}; + +loadKiteVolumes = function (directory, appName) { + var KITE_VOLUMES_PATH = path.join(directory, 'volumes'); + if (fs.existsSync(KITE_VOLUMES_PATH)) { + var destinationPath = path.join(KITE_PATH, appName); + copyFolder(KITE_VOLUMES_PATH, destinationPath); + console.log('Copied volumes for: ' + appName); + } +}; + +saveImageFolder = function (directory, imageId, callback) { + var destinationPath = path.join(KITE_IMAGES_PATH, imageId); + if (!fs.existsSync(destinationPath)) { + fs.mkdirSync(destinationPath, function (err) { + if (err) { callback(err); return; } + }); + copyFolder(directory, destinationPath); + console.log('Copied image folder for: ' + imageId); + callback(null); + } +}; + +saveImageFolderSync = function (directory, imageId) { + return Meteor._wrapAsync(saveImageFolder)(directory, imageId); +}; From eb46a9dee4a04b6accd7c2ad836ce6f3ca4b81fb Mon Sep 17 00:00:00 2001 From: Sean Li Date: Sun, 31 Aug 2014 20:27:49 -0700 Subject: [PATCH 06/12] Refactored app code into hooks. --- meteor/.jshintrc | 2 +- meteor/collections/apps.js | 23 ++++++++++++++++++++ meteor/server/apps.js | 39 ++++++++++------------------------ meteor/server/lib/utilities.js | 2 +- 4 files changed, 36 insertions(+), 30 deletions(-) diff --git a/meteor/.jshintrc b/meteor/.jshintrc index 2f77f05ffa..61e603f116 100755 --- a/meteor/.jshintrc +++ b/meteor/.jshintrc @@ -201,7 +201,7 @@ "restartApp": true, "deleteApp": true, "deleteFolder": true, - "loadKiteVolumes": true, + "copyVolumes": true, "getAppLogs": true, "hasDockerfile": true, "createTarFile": true, diff --git a/meteor/collections/apps.js b/meteor/collections/apps.js index 05006eb8e2..5bbc9ef2a9 100755 --- a/meteor/collections/apps.js +++ b/meteor/collections/apps.js @@ -117,6 +117,29 @@ Apps.helpers({ Apps.attachSchema(schemaApps); +Apps.after.insert(function (userId, app) { + // Give app an unique environment variable + var appId = this._id; + Apps.update(appId, { + $set: { + 'config.APP_ID': appId + } + }); + var image = Images.findOne(app.imageId); + copyVolumes(image.path, app.name); + app = Apps.findOne(appId); + removeBindFolder(app.name, function (err) { + if (err) { + console.error(err); + } + Fiber(function () { + Meteor.call('runApp', app, function (err) { + if (err) { throw err; } + }); + }).run(); + }); +}); + Apps.after.remove(function (userId, app) { deleteApp(app, function (err) { if (err) { console.error(err); } diff --git a/meteor/server/apps.js b/meteor/server/apps.js index 07a51cfa58..a52495810f 100755 --- a/meteor/server/apps.js +++ b/meteor/server/apps.js @@ -58,39 +58,22 @@ Meteor.methods({ throw new Meteor.Error(400, 'Validation Failed.', validationResult.errors); } else { var cleaned = validationResult.cleaned; - var appObj = { - name: cleaned.name, - imageId: cleaned.imageId, - status: 'STARTING', - config: {} - }; - var appId = Apps.insert(appObj); - var appPath = path.join(KITE_PATH, appObj.name); + var appName = cleaned.name; + var appPath = path.join(KITE_PATH, appName); if (!fs.existsSync(appPath)) { - console.log('Created Kite ' + appObj.name + ' directory.'); + console.log('Created Kite ' + appName + ' directory.'); fs.mkdirSync(appPath, function (err) { if (err) { throw err; } }); } - Apps.update(appId, { - $set: { - 'config.APP_ID': appId, - path: appPath - } - }); - var image = Images.findOne(appObj.imageId); - loadKiteVolumes(image.path, appObj.name); - var app = Apps.findOne(appId); - removeBindFolder(app.name, function (err) { - if (err) { - console.error(err); - } - Fiber(function () { - Meteor.call('runApp', app, function (err) { - if (err) { throw err; } - }); - }).run(); - }); + var appObj = { + name: appName, + imageId: cleaned.imageId, + status: 'STARTING', + config: {}, + path: appPath + }; + Apps.insert(appObj); } }, getAppLogs: function (appId) { diff --git a/meteor/server/lib/utilities.js b/meteor/server/lib/utilities.js index 4be5a0edaa..a0446ad702 100755 --- a/meteor/server/lib/utilities.js +++ b/meteor/server/lib/utilities.js @@ -62,7 +62,7 @@ getImageJSON = function (directory) { } }; -loadKiteVolumes = function (directory, appName) { +copyVolumes = function (directory, appName) { var KITE_VOLUMES_PATH = path.join(directory, 'volumes'); if (fs.existsSync(KITE_VOLUMES_PATH)) { var destinationPath = path.join(KITE_PATH, appName); From b3cc727dbbaa3906bf7d9b37d3f31ce759549b27 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Sun, 31 Aug 2014 21:07:22 -0700 Subject: [PATCH 07/12] Refactored utilities. --- meteor/.jshintrc | 6 +-- meteor/client/lib/boot2docker.js | 6 +-- meteor/client/lib/requires.js | 2 + meteor/client/lib/sync.js | 10 ++--- meteor/client/lib/utilities.js | 18 +------- meteor/client/lib/virtualbox.js | 7 ++- .../dashboard/apps/dashboard-single-app.js | 4 +- meteor/collections/apps.js | 4 +- meteor/{server => }/lib/utilities.js | 44 +++++-------------- meteor/server/apps.js | 2 +- meteor/server/constants.js | 2 +- meteor/server/docker.js | 4 +- meteor/server/images.js | 4 +- 13 files changed, 36 insertions(+), 77 deletions(-) create mode 100644 meteor/client/lib/requires.js rename meteor/{server => }/lib/utilities.js (54%) mode change 100755 => 100644 diff --git a/meteor/.jshintrc b/meteor/.jshintrc index 61e603f116..19c2e2f11c 100755 --- a/meteor/.jshintrc +++ b/meteor/.jshintrc @@ -163,8 +163,8 @@ // Server and Client "Docker": true, + "Util": true, "boot2dockerexec": true, - "getBinDir": true, "getBoot2DockerIp": true, "getBoot2DockerState": true, "getBoot2DockerDiskUsage": true, @@ -172,7 +172,6 @@ "getBoot2DockerInfo": true, "boot2DockerVMExists": true, "eraseBoot2DockerVMFiles": true, - "getHomePath": true, "initBoot2Docker": true, "isVirtualBoxInstalled": true, "upgradeBoot2Docker": true, @@ -200,8 +199,6 @@ "recoverApps": true, "restartApp": true, "deleteApp": true, - "deleteFolder": true, - "copyVolumes": true, "getAppLogs": true, "hasDockerfile": true, "createTarFile": true, @@ -224,7 +221,6 @@ "saveImageFolderSync": true, "rebuildImageSync": true, "saveImageFolder": true, - "copyFolder": true, // Forms "showFormErrors": true, diff --git a/meteor/client/lib/boot2docker.js b/meteor/client/lib/boot2docker.js index 8e939a2dc3..edeec4e5a8 100644 --- a/meteor/client/lib/boot2docker.js +++ b/meteor/client/lib/boot2docker.js @@ -2,7 +2,7 @@ var exec = require('exec'); var path = require('path'); boot2dockerexec = function (command, callback) { - exec(path.join(getBinDir(), 'boot2docker') + ' ' + command, function(err, stdout) { + exec(path.join(Util.getBinDir(), 'boot2docker') + ' ' + command, function(err, stdout) { callback(err, stdout); }); }; @@ -131,7 +131,7 @@ boot2DockerVMExists = function (callback) { }; eraseBoot2DockerVMFiles = function (callback) { - var VMFileLocation = path.join(getHomePath(), 'VirtualBox\\ VMs/boot2docker-vm'); + var VMFileLocation = path.join(Util.getHomePath(), 'VirtualBox\\ VMs/boot2docker-vm'); exec('rm -rf ' + VMFileLocation, function (err) { callback(err); }); @@ -174,7 +174,7 @@ upgradeBoot2Docker = function (callback) { }; installBoot2DockerAddons = function (callback) { - exec('/bin/cat ' + path.join(getBinDir(), 'kite-binaries.tar.gz') + ' | ' + path.join(getBinDir(), 'boot2docker') + ' ssh "tar zx -C /usr/local/bin"', function (err, stdout) { + exec('/bin/cat ' + path.join(Util.getBinDir(), 'kite-binaries.tar.gz') + ' | ' + path.join(Util.getBinDir(), 'boot2docker') + ' ssh "tar zx -C /usr/local/bin"', function (err, stdout) { console.log(stdout); callback(err); }); diff --git a/meteor/client/lib/requires.js b/meteor/client/lib/requires.js new file mode 100644 index 0000000000..2b261be406 --- /dev/null +++ b/meteor/client/lib/requires.js @@ -0,0 +1,2 @@ +path = require('path'); +fs = require('fs'); diff --git a/meteor/client/lib/sync.js b/meteor/client/lib/sync.js index 4dbbcace5d..9cf3fe0e4b 100644 --- a/meteor/client/lib/sync.js +++ b/meteor/client/lib/sync.js @@ -15,7 +15,7 @@ removeAppWatcher = function (id) { addAppWatcher = function (app) { removeAppWatcher(app._id); - var appPath = path.join(path.join(getHomePath(), 'Kitematic'), app.name); + var appPath = path.join(path.join(Util.getHomePath(), 'Kitematic'), app.name); var vmDir = path.join('/var/lib/docker/binds', app.name); var vmPath = 'ssh://docker@localhost:2022/' + vmDir; var watcher = chokidar.watch(appPath, {ignored: /.*\.DS_Store/}); @@ -30,7 +30,7 @@ addAppWatcher = function (app) { syncing = true; var errorPattern = /The\sfile\s(.*)\son\shost/g; var archiveErrorPattern = /Archive\s(.*)\son\shost\s.*\sshould\sbe\sDELETED/g; - var cmd = path.join(getBinDir(), 'unison'); + var cmd = path.join(Util.getBinDir(), 'unison'); var args = [ cmd, vmPath, @@ -46,7 +46,7 @@ addAppWatcher = function (app) { 'Name\ {*.tmp,*.unison,*.swp,*.pyc,.DS_Store}', '-auto', '-sshargs', - '-o\ UserKnownHostsFile=/dev/null\ -o\ StrictHostKeyChecking=no\ -o PreferredAuthentications=publickey\ -i\ ' + path.join(getHomePath(), '.ssh/id_boot2docker') + '-o\ UserKnownHostsFile=/dev/null\ -o\ StrictHostKeyChecking=no\ -o PreferredAuthentications=publickey\ -i\ ' + path.join(Util.getHomePath(), '.ssh/id_boot2docker') ]; if (!fs.existsSync(appPath)) { @@ -70,7 +70,7 @@ addAppWatcher = function (app) { if (err.indexOf('The archive file is missing on some hosts') !== -1) { var results = archiveErrorPattern.exec(err); var location = results[1].replace(' ', '\\ '); - var fullLocation = path.join(getHomePath(), 'Library/Application\\ Support/Unison', location); + var fullLocation = path.join(Util.getHomePath(), 'Library/Application\\ Support/Unison', location); var cmd = '/bin/rm -rf ' + fullLocation; exec(cmd, function () {}); } @@ -118,4 +118,4 @@ resolveWatchers = function (callback) { }); callback(); -}; \ No newline at end of file +}; diff --git a/meteor/client/lib/utilities.js b/meteor/client/lib/utilities.js index c3fe268798..3315ad4040 100755 --- a/meteor/client/lib/utilities.js +++ b/meteor/client/lib/utilities.js @@ -1,17 +1,3 @@ -var path = require('path'); - -getBinDir = function () { - if (process.env.NODE_ENV === 'development') { - return path.join(path.join(process.env.PWD, '..'), 'resources'); - } else { - return path.join(process.cwd(), 'resources'); - } -}; - -getHomePath = function () { - return process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME']; -}; - showFormErrors = function ($form, errors) { for (var name in errors) { if (errors.hasOwnProperty(name)) { @@ -31,7 +17,7 @@ clearFormErrors = function ($form) { $form.find('.form-group.has-error .help-block.error').remove(); $form.find('.form-group.has-error').removeClass('has-error'); }; - + resetForm = function ($form) { $form.find('input').val(''); }; @@ -41,4 +27,4 @@ trackLink = function (trackLabel) { console.log(trackLabel); ga('send', 'event', 'link', 'click', trackLabel); } -}; \ No newline at end of file +}; diff --git a/meteor/client/lib/virtualbox.js b/meteor/client/lib/virtualbox.js index 6d362492a9..9022d22430 100644 --- a/meteor/client/lib/virtualbox.js +++ b/meteor/client/lib/virtualbox.js @@ -25,8 +25,8 @@ isResolverSetup = function (callback) { }; setupResolver = function (callback) { - var installFile = path.join(getBinDir(), 'install'); - var cocoaSudo = path.join(getBinDir(), 'cocoasudo'); + var installFile = path.join(Util.getBinDir(), 'install'); + var cocoaSudo = path.join(Util.getBinDir(), 'cocoasudo'); var execCommand = cocoaSudo + ' --prompt="Kitematic Setup wants to make changes. Type your password to allow this." ' + installFile; child_process.exec(execCommand, function (error, stdout, stderr) { console.log(stdout); @@ -41,7 +41,7 @@ setupResolver = function (callback) { }; setupVirtualBox = function (callback) { - child_process.exec('open -W ' + path.join(getBinDir(), 'virtualbox-4.3.12.pkg'), function (error, stdout, stderr) { + child_process.exec('open -W ' + path.join(Util.getBinDir(), 'virtualbox-4.3.12.pkg'), function (error, stdout, stderr) { console.log(stdout); if (error) { console.log(error); @@ -52,4 +52,3 @@ setupVirtualBox = function (callback) { callback(); }); }; - diff --git a/meteor/client/views/dashboard/apps/dashboard-single-app.js b/meteor/client/views/dashboard/apps/dashboard-single-app.js index acbd198e79..5d32c4818f 100755 --- a/meteor/client/views/dashboard/apps/dashboard-single-app.js +++ b/meteor/client/views/dashboard/apps/dashboard-single-app.js @@ -21,8 +21,8 @@ Template.dashboard_single_app.events({ }, 'click .btn-terminal': function () { var app = this; - var cmd = path.join(getBinDir(), 'boot2docker') + ' ssh -t "sudo docker-enter ' + app.docker.Id + '"'; - var terminalCmd = path.join(getBinDir(), 'terminal') + ' ' + cmd; + var cmd = path.join(Util.getBinDir(), 'boot2docker') + ' ssh -t "sudo docker-enter ' + app.docker.Id + '"'; + var terminalCmd = path.join(Util.getBinDir(), 'terminal') + ' ' + cmd; var exec = require('child_process').exec; console.log(terminalCmd); exec(terminalCmd, function (err, stdout) { diff --git a/meteor/collections/apps.js b/meteor/collections/apps.js index 5bbc9ef2a9..1b7ee7ce97 100755 --- a/meteor/collections/apps.js +++ b/meteor/collections/apps.js @@ -126,7 +126,7 @@ Apps.after.insert(function (userId, app) { } }); var image = Images.findOne(app.imageId); - copyVolumes(image.path, app.name); + Util.copyVolumes(image.path, app.name); app = Apps.findOne(appId); removeBindFolder(app.name, function (err) { if (err) { @@ -144,7 +144,7 @@ Apps.after.remove(function (userId, app) { deleteApp(app, function (err) { if (err) { console.error(err); } var appPath = path.join(KITE_PATH, app.name); - deleteFolder(appPath); + Util.deleteFolder(appPath); removeBindFolder(app.name, function () { console.log('Deleted Kite ' + app.name + ' directory.'); }); diff --git a/meteor/server/lib/utilities.js b/meteor/lib/utilities.js old mode 100755 new mode 100644 similarity index 54% rename from meteor/server/lib/utilities.js rename to meteor/lib/utilities.js index a0446ad702..12c03f9298 --- a/meteor/server/lib/utilities.js +++ b/meteor/lib/utilities.js @@ -1,8 +1,10 @@ -getHomePath = function () { +Util = {}; + +Util.getHomePath = function () { return process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME']; }; -getBinDir = function () { +Util.getBinDir = function () { if (process.env.NODE_ENV === 'development') { return path.join(path.join(process.env.PWD, '..'), 'resources'); } else { @@ -10,13 +12,13 @@ getBinDir = function () { } }; -deleteFolder = function (directory) { +Util.deleteFolder = function (directory) { if (fs.existsSync(directory)) { fs.readdirSync(directory).forEach(function (file) { var curDirectory = directory + '/' + file; if (fs.lstatSync(curDirectory).isDirectory()) { // Recurse - deleteFolder(curDirectory); + Util.deleteFolder(curDirectory); } else { // Delete File try { @@ -30,7 +32,7 @@ deleteFolder = function (directory) { } }; -copyFolder = function (src, dest) { +Util.copyFolder = function (src, dest) { var exists = fs.existsSync(src); var stats = exists && fs.statSync(src); var isDirectory = exists && stats.isDirectory(); @@ -41,7 +43,7 @@ copyFolder = function (src, dest) { console.error(e); } fs.readdirSync(src).forEach(function (childItemName) { - copyFolder(path.join(src, childItemName), path.join(dest, childItemName)); + Util.copyFolder(path.join(src, childItemName), path.join(dest, childItemName)); }); } else { try { @@ -52,37 +54,11 @@ copyFolder = function (src, dest) { } }; -getImageJSON = function (directory) { - var KITE_JSON_PATH = path.join(directory, 'image.json'); - if (fs.existsSync(KITE_JSON_PATH)) { - var data = fs.readFileSync(KITE_JSON_PATH, 'utf8'); - return JSON.parse(data); - } else { - return null; - } -}; - -copyVolumes = function (directory, appName) { +Util.copyVolumes = function (directory, appName) { var KITE_VOLUMES_PATH = path.join(directory, 'volumes'); if (fs.existsSync(KITE_VOLUMES_PATH)) { var destinationPath = path.join(KITE_PATH, appName); - copyFolder(KITE_VOLUMES_PATH, destinationPath); + Util.copyFolder(KITE_VOLUMES_PATH, destinationPath); console.log('Copied volumes for: ' + appName); } }; - -saveImageFolder = function (directory, imageId, callback) { - var destinationPath = path.join(KITE_IMAGES_PATH, imageId); - if (!fs.existsSync(destinationPath)) { - fs.mkdirSync(destinationPath, function (err) { - if (err) { callback(err); return; } - }); - copyFolder(directory, destinationPath); - console.log('Copied image folder for: ' + imageId); - callback(null); - } -}; - -saveImageFolderSync = function (directory, imageId) { - return Meteor._wrapAsync(saveImageFolder)(directory, imageId); -}; diff --git a/meteor/server/apps.js b/meteor/server/apps.js index a52495810f..a96174beeb 100755 --- a/meteor/server/apps.js +++ b/meteor/server/apps.js @@ -1,5 +1,5 @@ removeBindFolder = function (name, callback) { - exec(path.join(getBinDir(), 'boot2docker') + ' ssh "sudo rm -rf /var/lib/docker/binds/' + name + '"', function(err, stdout) { + exec(path.join(Util.getBinDir(), 'boot2docker') + ' ssh "sudo rm -rf /var/lib/docker/binds/' + name + '"', function(err, stdout) { callback(err, stdout); }); }; diff --git a/meteor/server/constants.js b/meteor/server/constants.js index e3fd37c46e..cb35d90451 100644 --- a/meteor/server/constants.js +++ b/meteor/server/constants.js @@ -1,4 +1,4 @@ -KITE_PATH = path.join(getHomePath(), 'Kitematic'); +KITE_PATH = path.join(Util.getHomePath(), 'Kitematic'); KITE_TAR_PATH = path.join(KITE_PATH, '.tar'); KITE_IMAGES_PATH = path.join(KITE_PATH, '.images'); diff --git a/meteor/server/docker.js b/meteor/server/docker.js index c46ec6de30..0e22efb2ff 100755 --- a/meteor/server/docker.js +++ b/meteor/server/docker.js @@ -306,7 +306,7 @@ resolveDefaultImages = function () { image.inspect(function (err) { if (err) { if (err.reason === 'no such image') { - docker.loadImage(path.join(getBinDir(), 'base-images.tar.gz'), {}, function (err) { + docker.loadImage(path.join(Util.getBinDir(), 'base-images.tar.gz'), {}, function (err) { if (err) { innerCallback(err); return; @@ -393,7 +393,7 @@ reloadDefaultContainers = function (callback) { return; } console.log('Loading new Kitematic default images.'); - docker.loadImage(path.join(getBinDir(), 'base-images.tar.gz'), {}, function (err) { + docker.loadImage(path.join(Util.getBinDir(), 'base-images.tar.gz'), {}, function (err) { if (err) { callback(err); return; diff --git a/meteor/server/images.js b/meteor/server/images.js index f83f21da7f..8663f92cc4 100755 --- a/meteor/server/images.js +++ b/meteor/server/images.js @@ -13,7 +13,7 @@ getImageMetaData = function (directory) { }; rebuildImage = function (image, callback) { - deleteFolder(image.path); + Util.deleteFolder(image.path); var imageMetaData = getImageMetaData(image.originPath); if (imageMetaData.logo) { Images.update(image._id, { @@ -141,7 +141,7 @@ Meteor.methods({ console.log('here'); try { deleteImageSync(image); - deleteFolder(image.path); + Util.deleteFolder(image.path); } catch (e) { console.log(e); } finally { From aa6ac2a4d5cf7550e4eebc7f9c56537998e4bdf4 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Sun, 31 Aug 2014 21:08:21 -0700 Subject: [PATCH 08/12] Moved server utilities. --- meteor/server/images.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/meteor/server/images.js b/meteor/server/images.js index 8663f92cc4..d8985a8384 100755 --- a/meteor/server/images.js +++ b/meteor/server/images.js @@ -1,3 +1,29 @@ +getImageJSON = function (directory) { + var KITE_JSON_PATH = path.join(directory, 'image.json'); + if (fs.existsSync(KITE_JSON_PATH)) { + var data = fs.readFileSync(KITE_JSON_PATH, 'utf8'); + return JSON.parse(data); + } else { + return null; + } +}; + +saveImageFolder = function (directory, imageId, callback) { + var destinationPath = path.join(KITE_IMAGES_PATH, imageId); + if (!fs.existsSync(destinationPath)) { + fs.mkdirSync(destinationPath, function (err) { + if (err) { callback(err); return; } + }); + Util.copyFolder(directory, destinationPath); + console.log('Copied image folder for: ' + imageId); + callback(null); + } +}; + +saveImageFolderSync = function (directory, imageId) { + return Meteor._wrapAsync(saveImageFolder)(directory, imageId); +}; + getImageMetaData = function (directory) { var kiteJSON = getImageJSON(directory); if (kiteJSON) { From dc8cb18fa615b193523df2988818255b3394cf23 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Sun, 31 Aug 2014 22:10:32 -0700 Subject: [PATCH 09/12] Refactored code and fixed bin dir path issue. --- meteor/.jshintrc | 3 + meteor/client/lib/sync.js | 2 +- meteor/lib/utilities.js | 6 +- meteor/server/apps.js | 68 ++++++++++ meteor/server/docker.js | 225 ---------------------------------- meteor/server/images.js | 154 +++++++++++++++++++++++ meteor/server/lib/requires.js | 4 +- 7 files changed, 234 insertions(+), 228 deletions(-) diff --git a/meteor/.jshintrc b/meteor/.jshintrc index 19c2e2f11c..300055089f 100755 --- a/meteor/.jshintrc +++ b/meteor/.jshintrc @@ -143,6 +143,8 @@ "docker": true, "async": true, "child_process": true, + "convert": true, + "Convert": true, // Collections "SimpleSchema": false, @@ -221,6 +223,7 @@ "saveImageFolderSync": true, "rebuildImageSync": true, "saveImageFolder": true, + "getFromImage": true, // Forms "showFormErrors": true, diff --git a/meteor/client/lib/sync.js b/meteor/client/lib/sync.js index 9cf3fe0e4b..cd2468ef2d 100644 --- a/meteor/client/lib/sync.js +++ b/meteor/client/lib/sync.js @@ -75,7 +75,7 @@ addAppWatcher = function (app) { exec(cmd, function () {}); } } catch (e) { - // console.error(e); + //console.error(e); } syncing = false; if (willSyncAgain) { diff --git a/meteor/lib/utilities.js b/meteor/lib/utilities.js index 12c03f9298..73aea70f5f 100644 --- a/meteor/lib/utilities.js +++ b/meteor/lib/utilities.js @@ -8,7 +8,11 @@ Util.getBinDir = function () { if (process.env.NODE_ENV === 'development') { return path.join(path.join(process.env.PWD, '..'), 'resources'); } else { - return path.join(process.cwd(), '../../../resources'); + if (Meteor.isClient) { + return path.join(process.cwd(), 'resources'); + } else { + return path.join(process.cwd(), '../../../resources'); + } } }; diff --git a/meteor/server/apps.js b/meteor/server/apps.js index a96174beeb..6cc531bc13 100755 --- a/meteor/server/apps.js +++ b/meteor/server/apps.js @@ -1,3 +1,71 @@ +deleteApp = function (app, callback) { + if (!app.docker) { + callback(null); + return; + } + try { + Docker.removeContainerSync(app.docker.Id); + } catch (e) { + console.error(e); + } + callback(null); +}; + +deleteAppSync = function (app) { + return Meteor._wrapAsync(deleteApp)(app); +}; + +restartApp = function (app, callback) { + if (app.docker && app.docker.Id) { + try { + Docker.restartContainerSync(app.docker.Id); + } catch (e) { + console.error(e); + } + var containerData = Docker.getContainerDataSync(app.docker.Id); + Fiber(function () { + Apps.update(app._id, {$set: { + status: 'READY', + docker: containerData + }}); + }).run(); + callback(null); + // Use dig to refresh the DNS + exec('/usr/bin/dig dig ' + app.name + '.dev @172.17.42.1 ', function() {}); + } else { + callback(null); + } +}; + +getAppLogs = function (app) { + if (app.docker && app.docker.Id) { + var container = docker.getContainer(app.docker.Id); + container.logs({follow: false, stdout: true, stderr: true, timestamps: true, tail: 300}, function (err, response) { + if (err) { throw err; } + Fiber(function () { + Apps.update(app._id, { + $set: { + logs: [] + } + }); + }).run(); + var logs = []; + response.setEncoding('utf8'); + response.on('data', function (line) { + logs.push(convert.toHtml(line.slice(8))); + Fiber(function () { + Apps.update(app._id, { + $set: { + logs: logs + } + }); + }).run(); + }); + response.on('end', function () {}); + }); + } +}; + removeBindFolder = function (name, callback) { exec(path.join(Util.getBinDir(), 'boot2docker') + ' ssh "sudo rm -rf /var/lib/docker/binds/' + name + '"', function(err, stdout) { callback(err, stdout); diff --git a/meteor/server/docker.js b/meteor/server/docker.js index 0e22efb2ff..447359cf2d 100755 --- a/meteor/server/docker.js +++ b/meteor/server/docker.js @@ -1,8 +1,5 @@ Dockerode = Meteor.require('dockerode'); -var Convert = Meteor.require('ansi-to-html'); -var convert = new Convert(); - var DOCKER_HOST='192.168.59.103'; docker = new Dockerode({host: '192.168.59.103', port: '2375'}); @@ -28,23 +25,6 @@ Docker.removeContainerSync = function (containerId) { return Meteor._wrapAsync(Docker.removeContainer)(containerId); }; -deleteApp = function (app, callback) { - if (!app.docker) { - callback(null); - return; - } - try { - Docker.removeContainerSync(app.docker.Id); - } catch (e) { - console.error(e); - } - callback(null); -}; - -deleteAppSync = function (app) { - return Meteor._wrapAsync(deleteApp)(app); -}; - Docker.getContainerData = function (containerId, callback) { var container = docker.getContainer(containerId); container.inspect(function (err, data) { @@ -123,68 +103,6 @@ Docker.restartContainerSync = function (containerId) { return Meteor._wrapAsync(Docker.restartContainer)(containerId); }; -var getFromImage = function (dockerfile) { - var patternString = "(FROM)(.*)"; - var regex = new RegExp(patternString, "g"); - var fromInstruction = dockerfile.match(regex); - if (fromInstruction && fromInstruction.length > 0) { - return fromInstruction[0].replace('FROM', '').trim(); - } else { - return null; - } -}; - -restartApp = function (app, callback) { - if (app.docker && app.docker.Id) { - try { - Docker.restartContainerSync(app.docker.Id); - } catch (e) { - console.error(e); - } - var containerData = Docker.getContainerDataSync(app.docker.Id); - Fiber(function () { - Apps.update(app._id, {$set: { - status: 'READY', - docker: containerData - }}); - }).run(); - callback(null); - // Use dig to refresh the DNS - exec('/usr/bin/dig dig ' + app.name + '.dev @172.17.42.1 ', function() {}); - } else { - callback(null); - } -}; - -getAppLogs = function (app) { - if (app.docker && app.docker.Id) { - var container = docker.getContainer(app.docker.Id); - container.logs({follow: false, stdout: true, stderr: true, timestamps: true, tail: 300}, function (err, response) { - if (err) { throw err; } - Fiber(function () { - Apps.update(app._id, { - $set: { - logs: [] - } - }); - }).run(); - var logs = []; - response.setEncoding('utf8'); - response.on('data', function (line) { - logs.push(convert.toHtml(line.slice(8))); - Fiber(function () { - Apps.update(app._id, { - $set: { - logs: logs - } - }); - }).run(); - }); - response.on('end', function () {}); - }); - } -}; - createTarFile = function (image, callback) { var TAR_PATH = path.join(KITE_TAR_PATH, image._id + '.tar'); exec('tar czf ' + TAR_PATH + ' -C ' + image.path + ' .', function (err) { @@ -243,23 +161,6 @@ Docker.removeImageSync = function (imageId) { return Meteor._wrapAsync(Docker.removeImage)(imageId); }; -deleteImage = function (image, callback) { - if (!image.docker) { - callback(null, {}); - return; - } - try { - Docker.removeImageSync(image.docker.Id); - } catch (e) { - console.error(e); - } - callback(null); -}; - -deleteImageSync = function (image) { - return Meteor._wrapAsync(deleteImage)(image); -}; - var defaultContainerOptions = function () { return [ { @@ -502,132 +403,6 @@ killAndRemoveContainers = function (names, callback) { }); }; -pullImageFromDockerfile = function (dockerfile, imageId, callback) { - var fromImage = getFromImage(dockerfile); - console.log('From image: ' + fromImage); - var installedImage = null; - try { - installedImage = Docker.getImageDataSync(fromImage); - } catch (e) { - console.error(e); - } - if (fromImage && !installedImage) { - Fiber(function () { - Images.update(imageId, { - $set: { - buildLogs: [] - } - }); - }).run(); - var logs = []; - docker.pull(fromImage, function (err, response) { - if (err) { callback(err); return; } - response.setEncoding('utf8'); - response.on('data', function (data) { - try { - var logData = JSON.parse(data); - var logDisplay = ''; - if (logData.id) { - logDisplay += logData.id + ' | '; - } - logDisplay += logData.status; - if (logData.progressDetail && logData.progressDetail.current && logData.progressDetail.total) { - logDisplay += ' - ' + Math.round(logData.progressDetail.current / logData.progressDetail.total * 100) + '%'; - } - logs.push(logDisplay); - Fiber(function () { - Images.update(imageId, { - $set: { - buildLogs: logs - } - }); - }).run(); - } catch (e) { - console.error(e); - } - }); - response.on('end', function () { - console.log('Finished pulling image: ' + fromImage); - callback(null); - }); - }); - } else { - callback(null); - } -}; - -buildImage = function (image, callback) { - Fiber(function () { - var tarFilePath = createTarFileSync(image); - Images.update(image._id, { - $set: { - buildLogs: [] - } - }); - docker.buildImage(tarFilePath, {t: image._id.toLowerCase()}, function (err, response) { - if (err) { callback(err); } - console.log('Building Docker image...'); - var logs = []; - response.setEncoding('utf8'); - response.on('data', function (data) { - try { - var line = JSON.parse(data).stream; - logs.push(convert.toHtml(line)); - Fiber(function () { - Images.update(image._id, { - $set: { - buildLogs: logs - } - }); - }).run(); - } catch (e) { - console.error(e); - } - }); - response.on('end', function () { - console.log('Finished building Docker image.'); - try { - fs.unlinkSync(tarFilePath); - console.log('Cleaned up tar file.'); - } catch (e) { - console.error(e); - } - Fiber(function () { - var imageData = null; - try { - imageData = Docker.getImageDataSync(image._id); - Images.update(image._id, { - $set: { - docker: imageData, - status: 'READY' - } - }); - } catch (e) { - console.log(e); - Images.update(image._id, { - $set: { - status: 'ERROR' - } - }); - } - var oldImageId = null; - if (image.docker && image.docker.Id) { - oldImageId = image.docker.Id; - } - if (oldImageId && imageData && oldImageId !== imageData.Id) { - try { - Docker.removeImageSync(oldImageId); - } catch (e) { - console.error(e); - } - } - }).run(); - callback(null); - }); - }); - }).run(); -}; - Meteor.methods({ runApp: function (app) { this.unblock(); diff --git a/meteor/server/images.js b/meteor/server/images.js index d8985a8384..a2c91c538b 100755 --- a/meteor/server/images.js +++ b/meteor/server/images.js @@ -1,3 +1,14 @@ +getFromImage = function (dockerfile) { + var patternString = "(FROM)(.*)"; + var regex = new RegExp(patternString, "g"); + var fromInstruction = dockerfile.match(regex); + if (fromInstruction && fromInstruction.length > 0) { + return fromInstruction[0].replace('FROM', '').trim(); + } else { + return null; + } +}; + getImageJSON = function (directory) { var KITE_JSON_PATH = path.join(directory, 'image.json'); if (fs.existsSync(KITE_JSON_PATH)) { @@ -38,6 +49,23 @@ getImageMetaData = function (directory) { return kiteJSON; }; +deleteImage = function (image, callback) { + if (!image.docker) { + callback(null, {}); + return; + } + try { + Docker.removeImageSync(image.docker.Id); + } catch (e) { + console.error(e); + } + callback(null); +}; + +deleteImageSync = function (image) { + return Meteor._wrapAsync(deleteImage)(image); +}; + rebuildImage = function (image, callback) { Util.deleteFolder(image.path); var imageMetaData = getImageMetaData(image.originPath); @@ -75,6 +103,132 @@ rebuildImageSync = function (image) { return Meteor._wrapAsync(rebuildImage)(image); }; +pullImageFromDockerfile = function (dockerfile, imageId, callback) { + var fromImage = getFromImage(dockerfile); + console.log('From image: ' + fromImage); + var installedImage = null; + try { + installedImage = Docker.getImageDataSync(fromImage); + } catch (e) { + console.error(e); + } + if (fromImage && !installedImage) { + Fiber(function () { + Images.update(imageId, { + $set: { + buildLogs: [] + } + }); + }).run(); + var logs = []; + docker.pull(fromImage, function (err, response) { + if (err) { callback(err); return; } + response.setEncoding('utf8'); + response.on('data', function (data) { + try { + var logData = JSON.parse(data); + var logDisplay = ''; + if (logData.id) { + logDisplay += logData.id + ' | '; + } + logDisplay += logData.status; + if (logData.progressDetail && logData.progressDetail.current && logData.progressDetail.total) { + logDisplay += ' - ' + Math.round(logData.progressDetail.current / logData.progressDetail.total * 100) + '%'; + } + logs.push(logDisplay); + Fiber(function () { + Images.update(imageId, { + $set: { + buildLogs: logs + } + }); + }).run(); + } catch (e) { + console.error(e); + } + }); + response.on('end', function () { + console.log('Finished pulling image: ' + fromImage); + callback(null); + }); + }); + } else { + callback(null); + } +}; + +buildImage = function (image, callback) { + Fiber(function () { + var tarFilePath = createTarFileSync(image); + Images.update(image._id, { + $set: { + buildLogs: [] + } + }); + docker.buildImage(tarFilePath, {t: image._id.toLowerCase()}, function (err, response) { + if (err) { callback(err); } + console.log('Building Docker image...'); + var logs = []; + response.setEncoding('utf8'); + response.on('data', function (data) { + try { + var line = JSON.parse(data).stream; + logs.push(convert.toHtml(line)); + Fiber(function () { + Images.update(image._id, { + $set: { + buildLogs: logs + } + }); + }).run(); + } catch (e) { + console.error(e); + } + }); + response.on('end', function () { + console.log('Finished building Docker image.'); + try { + fs.unlinkSync(tarFilePath); + console.log('Cleaned up tar file.'); + } catch (e) { + console.error(e); + } + Fiber(function () { + var imageData = null; + try { + imageData = Docker.getImageDataSync(image._id); + Images.update(image._id, { + $set: { + docker: imageData, + status: 'READY' + } + }); + } catch (e) { + console.log(e); + Images.update(image._id, { + $set: { + status: 'ERROR' + } + }); + } + var oldImageId = null; + if (image.docker && image.docker.Id) { + oldImageId = image.docker.Id; + } + if (oldImageId && imageData && oldImageId !== imageData.Id) { + try { + Docker.removeImageSync(oldImageId); + } catch (e) { + console.error(e); + } + } + }).run(); + callback(null); + }); + }); + }).run(); +}; + Meteor.methods({ createImage: function (directory) { this.unblock(); diff --git a/meteor/server/lib/requires.js b/meteor/server/lib/requires.js index cac98d255a..6174cd0202 100755 --- a/meteor/server/lib/requires.js +++ b/meteor/server/lib/requires.js @@ -6,4 +6,6 @@ path = Meteor.require('path'); exec = Meteor.require('child_process').exec; async = Meteor.require('async'); Fiber = Meteor.require('fibers'); -child_process = Meteor.require('child_process'); \ No newline at end of file +child_process = Meteor.require('child_process'); +Convert = Meteor.require('ansi-to-html'); +convert = new Convert(); From 50d3629758654d4ed6895d22c78bbdeab57bdf9e Mon Sep 17 00:00:00 2001 From: Sean Li Date: Mon, 1 Sep 2014 00:59:32 -0700 Subject: [PATCH 10/12] Refactored app code. --- meteor/.jshintrc | 7 ------- meteor/client/main.js | 4 ++-- meteor/collections/apps.js | 20 ++++++++++++-------- meteor/lib/utilities.js | 4 ++++ meteor/server/apps.js | 37 +++++++------------------------------ meteor/server/docker.js | 23 ++++++----------------- meteor/server/images.js | 23 +++++++++++++++++++++-- 7 files changed, 52 insertions(+), 66 deletions(-) diff --git a/meteor/.jshintrc b/meteor/.jshintrc index 300055089f..139808b8bf 100755 --- a/meteor/.jshintrc +++ b/meteor/.jshintrc @@ -194,15 +194,9 @@ "fixInterval": true, "stopFixInterval": true, "runSetup": true, - "removeBindFolder": true, "removeAppWatcher": true, "addAppWatcher": true, "resolveWatchers": true, - "recoverApps": true, - "restartApp": true, - "deleteApp": true, - "getAppLogs": true, - "hasDockerfile": true, "createTarFile": true, "createTarFileSync": true, "deleteImage": true, @@ -232,7 +226,6 @@ "FormSchema": true, "showFormSuccess": true, "resetForm": true, - "deleteAppSync": true, // Testing "require": false, diff --git a/meteor/client/main.js b/meteor/client/main.js index 7abe7d59a1..4b47333ece 100755 --- a/meteor/client/main.js +++ b/meteor/client/main.js @@ -148,7 +148,7 @@ startFixInterval = function () { resolveWatchers(function () {}); fixBoot2DockerVM(function (err) { if (err) { console.log(err); return; } - // Meteor.call('recoverApps'); + Meteor.call('recoverApps'); fixDefaultImages(function (err) { if (err) { console.log(err); return; } fixDefaultContainers(function (err) { @@ -162,4 +162,4 @@ startFixInterval = function () { stopFixInterval = function () { Meteor.clearInterval(fixInterval); fixInterval = null; -}; \ No newline at end of file +}; diff --git a/meteor/collections/apps.js b/meteor/collections/apps.js index 1b7ee7ce97..ba40c9b2e9 100755 --- a/meteor/collections/apps.js +++ b/meteor/collections/apps.js @@ -128,7 +128,7 @@ Apps.after.insert(function (userId, app) { var image = Images.findOne(app.imageId); Util.copyVolumes(image.path, app.name); app = Apps.findOne(appId); - removeBindFolder(app.name, function (err) { + Docker.removeBindFolder(app.name, function (err) { if (err) { console.error(err); } @@ -141,12 +141,16 @@ Apps.after.insert(function (userId, app) { }); Apps.after.remove(function (userId, app) { - deleteApp(app, function (err) { - if (err) { console.error(err); } - var appPath = path.join(KITE_PATH, app.name); - Util.deleteFolder(appPath); - removeBindFolder(app.name, function () { - console.log('Deleted Kite ' + app.name + ' directory.'); - }); + if (app.docker) { + try { + Docker.removeContainerSync(app.docker.Id); + } catch (e) { + console.error(e); + } + } + var appPath = path.join(KITE_PATH, app.name); + Util.deleteFolder(appPath); + Docker.removeBindFolder(app.name, function () { + console.log('Deleted Kite ' + app.name + ' directory.'); }); }); diff --git a/meteor/lib/utilities.js b/meteor/lib/utilities.js index 73aea70f5f..2497df3b53 100644 --- a/meteor/lib/utilities.js +++ b/meteor/lib/utilities.js @@ -66,3 +66,7 @@ Util.copyVolumes = function (directory, appName) { console.log('Copied volumes for: ' + appName); } }; + +Util.hasDockerfile = function (directory) { + return fs.existsSync(path.join(directory, 'Dockerfile')); +}; diff --git a/meteor/server/apps.js b/meteor/server/apps.js index 6cc531bc13..a8e7c8dce7 100755 --- a/meteor/server/apps.js +++ b/meteor/server/apps.js @@ -1,21 +1,4 @@ -deleteApp = function (app, callback) { - if (!app.docker) { - callback(null); - return; - } - try { - Docker.removeContainerSync(app.docker.Id); - } catch (e) { - console.error(e); - } - callback(null); -}; - -deleteAppSync = function (app) { - return Meteor._wrapAsync(deleteApp)(app); -}; - -restartApp = function (app, callback) { +Apps.restart = function (app, callback) { if (app.docker && app.docker.Id) { try { Docker.restartContainerSync(app.docker.Id); @@ -37,7 +20,7 @@ restartApp = function (app, callback) { } }; -getAppLogs = function (app) { +Apps.logs = function (app) { if (app.docker && app.docker.Id) { var container = docker.getContainer(app.docker.Id); container.logs({follow: false, stdout: true, stderr: true, timestamps: true, tail: 300}, function (err, response) { @@ -66,13 +49,7 @@ getAppLogs = function (app) { } }; -removeBindFolder = function (name, callback) { - exec(path.join(Util.getBinDir(), 'boot2docker') + ' ssh "sudo rm -rf /var/lib/docker/binds/' + name + '"', function(err, stdout) { - callback(err, stdout); - }); -}; - -recoverApps = function (callback) { +Apps.recover = function (callback) { var apps = Apps.find({}).fetch(); _.each(apps, function (app) { // Update the app with the latest container info @@ -85,7 +62,7 @@ recoverApps = function (callback) { console.log('restarting: ' + app.name); console.log(app.docker.Id); Fiber(function () { - restartApp(app, function (err) { + Apps.restart(app, function (err) { if (err) { console.error(err); } }); }).run(); @@ -98,7 +75,7 @@ recoverApps = function (callback) { Meteor.methods({ recoverApps: function () { this.unblock(); - return Meteor._wrapAsync(recoverApps)(); + return Meteor._wrapAsync(Apps.recover)(); }, configVar: function (appId, configVars) { this.unblock(); @@ -148,7 +125,7 @@ Meteor.methods({ this.unblock(); var app = Apps.findOne(appId); if (app) { - getAppLogs(app, function (err) { + Apps.logs(app, function (err) { if (err) { throw err; } }); } @@ -160,7 +137,7 @@ Meteor.methods({ Apps.update(app._id, {$set: { status: 'STARTING' }}); - restartApp(app, function (err) { + Apps.restart(app, function (err) { if (err) { console.error(err); } }); } diff --git a/meteor/server/docker.js b/meteor/server/docker.js index 447359cf2d..ae1e759985 100755 --- a/meteor/server/docker.js +++ b/meteor/server/docker.js @@ -5,10 +5,6 @@ docker = new Dockerode({host: '192.168.59.103', port: '2375'}); Docker = {}; -hasDockerfile = function (directory) { - return fs.existsSync(path.join(directory, 'Dockerfile')); -}; - Docker.removeContainer = function (containerId, callback) { var container = docker.getContainer(containerId); container.kill(function (err) { @@ -103,19 +99,6 @@ Docker.restartContainerSync = function (containerId) { return Meteor._wrapAsync(Docker.restartContainer)(containerId); }; -createTarFile = function (image, callback) { - var TAR_PATH = path.join(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); - }); -}; - -createTarFileSync = function (image) { - return Meteor._wrapAsync(createTarFile)(image); -}; - var convertVolumeObjToArray = function (obj) { var result = []; if (obj !== null && typeof obj === 'object') { @@ -161,6 +144,12 @@ Docker.removeImageSync = function (imageId) { return Meteor._wrapAsync(Docker.removeImage)(imageId); }; +Docker.removeBindFolder = function (name, callback) { + exec(path.join(Util.getBinDir(), 'boot2docker') + ' ssh "sudo rm -rf /var/lib/docker/binds/' + name + '"', function (err, stdout) { + callback(err, stdout); + }); +}; + var defaultContainerOptions = function () { return [ { diff --git a/meteor/server/images.js b/meteor/server/images.js index a2c91c538b..3befdd5e2b 100755 --- a/meteor/server/images.js +++ b/meteor/server/images.js @@ -1,3 +1,16 @@ +createTarFile = function (image, callback) { + var TAR_PATH = path.join(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); + }); +}; + +createTarFileSync = function (image) { + return Meteor._wrapAsync(createTarFile)(image); +}; + getFromImage = function (dockerfile) { var patternString = "(FROM)(.*)"; var regex = new RegExp(patternString, "g"); @@ -272,7 +285,13 @@ Meteor.methods({ if (apps.length > 0) { _.each(apps, function (app) { console.log('Updating app: ' + app.name); - deleteAppSync(app); + if (app.docker) { + try { + Docker.removeContainerSync(app.docker.Id); + } catch (e) { + console.error(e); + } + } Apps.update(app._id, { $set: { 'docker.Id': null, @@ -306,7 +325,7 @@ Meteor.methods({ }, validateDirectory: function (directory) { this.unblock(); - if (!hasDockerfile(directory)) { + if (!Util.hasDockerfile(directory)) { throw new Meteor.Error(400, "Only directories with Dockerfiles are supported now."); } }, From 63148c2d9cc4246aea5e0e1f0dc2d19662db0a11 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Mon, 1 Sep 2014 02:15:00 -0700 Subject: [PATCH 11/12] Refactored image code. --- meteor/.jshintrc | 13 ----- meteor/collections/images.js | 40 ++++++++++++++ meteor/server/images.js | 103 ++++++++++------------------------- 3 files changed, 68 insertions(+), 88 deletions(-) diff --git a/meteor/.jshintrc b/meteor/.jshintrc index 139808b8bf..35c1c7df9b 100755 --- a/meteor/.jshintrc +++ b/meteor/.jshintrc @@ -197,27 +197,14 @@ "removeAppWatcher": true, "addAppWatcher": true, "resolveWatchers": true, - "createTarFile": true, - "createTarFileSync": true, - "deleteImage": true, "checkDefaultImages": true, "resolveDefaultImages": true, "checkDefaultContainers": true, "resolveDefaultContainers": true, "killAndRemoveContainers": true, - "deleteImageSync": true, "upContainers": true, "reloadDefaultContainers": true, "removeImages": true, - "pullImageFromDockerfile": true, - "buildImage": true, - "getImageMetaData": true, - "getImageJSON": true, - "rebuildImage": true, - "saveImageFolderSync": true, - "rebuildImageSync": true, - "saveImageFolder": true, - "getFromImage": true, // Forms "showFormErrors": true, diff --git a/meteor/collections/images.js b/meteor/collections/images.js index 15055ad021..5a4de5b4f8 100755 --- a/meteor/collections/images.js +++ b/meteor/collections/images.js @@ -91,3 +91,43 @@ Images.allow({ }); Images.attachSchema(schemaImages); + +Images.after.insert(function (userId, image) { + var imageId = this._id; + var imagePath = path.join(KITE_IMAGES_PATH, imageId); + Images.update(imageId, { + $set: { + path: imagePath + } + }); + if (image.meta.logo) { + Images.update(imageId, { + $set: { + logoPath: path.join(imagePath, image.meta.logo) + } + }); + } + image = Images.findOne(imageId); + Images.saveFolderSync(image.originPath, imageId); + Images.pull(fs.readFileSync(path.join(image.path, 'Dockerfile'), 'utf8'), imageId, function (err) { + if (err) { throw err; } + Images.build(image, function (err) { + if (err) { console.error(err); } + }); + }); +}); + +Images.after.remove(function (userId, image) { + if (image.docker) { + try { + Docker.removeImageSync(image.docker.Id); + } catch (e) { + console.error(e); + } + } + try { + Util.deleteFolder(image.path); + } catch (e) { + console.error(e); + } +}); diff --git a/meteor/server/images.js b/meteor/server/images.js index 3befdd5e2b..6ad43fe7d0 100755 --- a/meteor/server/images.js +++ b/meteor/server/images.js @@ -1,4 +1,4 @@ -createTarFile = function (image, callback) { +var createTarFile = function (image, callback) { var TAR_PATH = path.join(KITE_TAR_PATH, image._id + '.tar'); exec('tar czf ' + TAR_PATH + ' -C ' + image.path + ' .', function (err) { if (err) { callback(err, null); return; } @@ -7,11 +7,11 @@ createTarFile = function (image, callback) { }); }; -createTarFileSync = function (image) { +var createTarFileSync = function (image) { return Meteor._wrapAsync(createTarFile)(image); }; -getFromImage = function (dockerfile) { +var getFromImage = function (dockerfile) { var patternString = "(FROM)(.*)"; var regex = new RegExp(patternString, "g"); var fromInstruction = dockerfile.match(regex); @@ -22,7 +22,7 @@ getFromImage = function (dockerfile) { } }; -getImageJSON = function (directory) { +var getImageJSON = function (directory) { var KITE_JSON_PATH = path.join(directory, 'image.json'); if (fs.existsSync(KITE_JSON_PATH)) { var data = fs.readFileSync(KITE_JSON_PATH, 'utf8'); @@ -32,23 +32,7 @@ getImageJSON = function (directory) { } }; -saveImageFolder = function (directory, imageId, callback) { - var destinationPath = path.join(KITE_IMAGES_PATH, imageId); - if (!fs.existsSync(destinationPath)) { - fs.mkdirSync(destinationPath, function (err) { - if (err) { callback(err); return; } - }); - Util.copyFolder(directory, destinationPath); - console.log('Copied image folder for: ' + imageId); - callback(null); - } -}; - -saveImageFolderSync = function (directory, imageId) { - return Meteor._wrapAsync(saveImageFolder)(directory, imageId); -}; - -getImageMetaData = function (directory) { +var getImageMetaData = function (directory) { var kiteJSON = getImageJSON(directory); if (kiteJSON) { if (!kiteJSON.name) { @@ -62,24 +46,23 @@ getImageMetaData = function (directory) { return kiteJSON; }; -deleteImage = function (image, callback) { - if (!image.docker) { - callback(null, {}); - return; +Images.saveFolder = function (directory, imageId, callback) { + var destinationPath = path.join(KITE_IMAGES_PATH, imageId); + if (!fs.existsSync(destinationPath)) { + fs.mkdirSync(destinationPath, function (err) { + if (err) { callback(err); return; } + }); + Util.copyFolder(directory, destinationPath); + console.log('Copied image folder for: ' + imageId); + callback(null); } - try { - Docker.removeImageSync(image.docker.Id); - } catch (e) { - console.error(e); - } - callback(null); }; -deleteImageSync = function (image) { - return Meteor._wrapAsync(deleteImage)(image); +Images.saveFolderSync = function (directory, imageId) { + return Meteor._wrapAsync(Images.saveFolder)(directory, imageId); }; -rebuildImage = function (image, callback) { +Images.rebuild = function (image, callback) { Util.deleteFolder(image.path); var imageMetaData = getImageMetaData(image.originPath); if (imageMetaData.logo) { @@ -102,21 +85,21 @@ rebuildImage = function (image, callback) { } }); image = Images.findOne(image._id); - saveImageFolderSync(image.originPath, image._id); - pullImageFromDockerfile(fs.readFileSync(path.join(image.path, 'Dockerfile'), 'utf8'), image._id, function (err) { + Images.saveFolderSync(image.originPath, image._id); + Images.pull(fs.readFileSync(path.join(image.path, 'Dockerfile'), 'utf8'), image._id, function (err) { if (err) { callback(err, null); return; } - buildImage(image, function (err) { + Images.build(image, function (err) { if (err) { console.error(err); } callback(null, null); }); }); }; -rebuildImageSync = function (image) { - return Meteor._wrapAsync(rebuildImage)(image); +Images.rebuildSync = function (image) { + return Meteor._wrapAsync(Images.rebuild)(image); }; -pullImageFromDockerfile = function (dockerfile, imageId, callback) { +Images.pull = function (dockerfile, imageId, callback) { var fromImage = getFromImage(dockerfile); console.log('From image: ' + fromImage); var installedImage = null; @@ -170,7 +153,7 @@ pullImageFromDockerfile = function (dockerfile, imageId, callback) { } }; -buildImage = function (image, callback) { +Images.build = function (image, callback) { Fiber(function () { var tarFilePath = createTarFileSync(image); Images.update(image._id, { @@ -251,29 +234,7 @@ Meteor.methods({ }; var imageMetaData = getImageMetaData(directory); imageObj.meta = imageMetaData; - var imageId = Images.insert(imageObj); - var imagePath = path.join(KITE_IMAGES_PATH, imageId); - Images.update(imageId, { - $set: { - path: imagePath - } - }); - if (imageObj.meta.logo) { - Images.update(imageId, { - $set: { - logoPath: path.join(imagePath, imageObj.meta.logo) - } - }); - } - var image = Images.findOne(imageId); - saveImageFolderSync(directory, imageId); - console.log('Saved folder sync'); - pullImageFromDockerfile(fs.readFileSync(path.join(image.path, 'Dockerfile'), 'utf8'), imageId, function (err) { - if (err) { throw err; } - buildImage(image, function (err) { - if (err) { console.error(err); } - }); - }); + Images.insert(imageObj); }, rebuildImage: function (imageId) { this.unblock(); @@ -300,7 +261,7 @@ Meteor.methods({ } }); }); - rebuildImageSync(image); + Images.rebuildSync(image); _.each(apps, function (app) { app = Apps.findOne(app._id); Meteor.call('runApp', app, function (err) { @@ -308,7 +269,7 @@ Meteor.methods({ }); }); } else { - rebuildImageSync(image); + Images.rebuildSync(image); } }, changeDirectory: function (imageId, directory) { @@ -337,15 +298,7 @@ Meteor.methods({ } var app = Apps.findOne({imageId: imageId}); if (!app) { - console.log('here'); - try { - deleteImageSync(image); - Util.deleteFolder(image.path); - } catch (e) { - console.log(e); - } finally { - Images.remove({_id: image._id}); - } + Images.remove({_id: image._id}); } else { throw new Meteor.Error(400, 'This image is currently being used by ' + app.name + "."); } From c00fe7b6306e52df06ffaf4c44bbd26c1e94a43b Mon Sep 17 00:00:00 2001 From: Sean Li Date: Mon, 1 Sep 2014 02:23:18 -0700 Subject: [PATCH 12/12] JSHint. --- meteor/client/views/dashboard/setup/setup-install.js | 5 ++--- meteor/server/publications.js | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/meteor/client/views/dashboard/setup/setup-install.js b/meteor/client/views/dashboard/setup/setup-install.js index 004ac755cf..dfb9ec9fd8 100644 --- a/meteor/client/views/dashboard/setup/setup-install.js +++ b/meteor/client/views/dashboard/setup/setup-install.js @@ -12,7 +12,6 @@ var steps = [ { install: function (callback) { isVirtualBoxInstalled(function (err, virtualBoxInstalled) { - var installedYet = false; if (!virtualBoxInstalled) { setupVirtualBox(function (err) { callback(err); @@ -77,7 +76,7 @@ var steps = [ pastMessage: 'Started the Kitematic VM', message: 'Starting the Kitematic VM', subMessage: '(This may take a few minutes)', - futureMessage: 'Start the Kitematic VM', + futureMessage: 'Start the Kitematic VM' }, // Set up the default Kitematic images @@ -90,7 +89,7 @@ var steps = [ pastMessage: 'Started the Kitematic VM', message: 'Setting up the default Kitematic images...', subMessage: '(This may take a few minutes)', - futureMessage: 'Set up the default Kitematic images', + futureMessage: 'Set up the default Kitematic images' } ]; diff --git a/meteor/server/publications.js b/meteor/server/publications.js index fe75a8a9ba..6e3540fc61 100755 --- a/meteor/server/publications.js +++ b/meteor/server/publications.js @@ -7,5 +7,5 @@ Meteor.publish('images', function () { }); Meteor.publish('installs', function () { - return Installs.find({}, {sort: {createdAt: -1}}); + return Installs.find({}); });