diff --git a/app/Container.react.js b/app/Container.react.js
new file mode 100644
index 0000000000..f69ca483b3
--- /dev/null
+++ b/app/Container.react.js
@@ -0,0 +1,15 @@
+var React = require('react');
+var Router = require('react-router');
+var Route = Router.Route;
+var NotFoundRoute = Router.NotFoundRoute;
+var DefaultRoute = Router.DefaultRoute;
+var Link = Router.Link;
+var RouteHandler = Router.RouteHandler;
+
+var Container = React.createClass({
+ render: function () {
+ return
Hello
;
+ }
+});
+
+module.exports = Container;
diff --git a/app/Containers.react.js b/app/Containers.react.js
new file mode 100644
index 0000000000..4cd6f02d8f
--- /dev/null
+++ b/app/Containers.react.js
@@ -0,0 +1,69 @@
+var React = require('react');
+var Router = require('react-router');
+var Route = Router.Route;
+var NotFoundRoute = Router.NotFoundRoute;
+var DefaultRoute = Router.DefaultRoute;
+var Link = Router.Link;
+var RouteHandler = Router.RouteHandler;
+var Navigation= Router.Navigation;
+
+var async = require('async');
+var docker = require('./docker.js');
+
+var ContainerList = React.createClass({
+ render: function () {
+ var containers = this.props.containers.map(function (container) {
+ return {container.Name.replace('/', '')}
+ });
+ return (
+
+ );
+ }
+});
+
+var Containers = React.createClass({
+ mixins: [Navigation],
+ getInitialState: function() {
+ return {containers: []};
+ },
+ update: function () {
+ var self = this;
+ docker.client().listContainers({all: true}, function (err, containers) {
+ async.map(containers, function(container, callback) {
+ docker.client().getContainer(container.Id).inspect(function (err, data) {
+ callback(null, data);
+ });
+ }, function (err, results) {
+ if (results.length > 0) {
+ self.transitionTo('container', {Id: results[0].Id})
+ }
+ self.setState({containers: results});
+ });
+ });
+ },
+ componentDidMount: function () {
+ this.update();
+ var self = this;
+ docker.client().getEvents(function (err, stream) {
+ if (err) {
+ throw err;
+ }
+ stream.setEncoding('utf8');
+ stream.on('data', function (data) {
+ self.update();
+ });
+ });
+ },
+ render: function () {
+ return (
+
+
+
+
+ );
+ }
+});
+
+module.exports = Containers;
diff --git a/app/Radial.react.js b/app/Radial.react.js
new file mode 100644
index 0000000000..c91c898445
--- /dev/null
+++ b/app/Radial.react.js
@@ -0,0 +1,37 @@
+var React = require('react/addons');
+
+var Radial = React.createClass({
+ render: function () {
+ var percentage;
+ if (this.props.progress && !this.props.spin) {
+ percentage = (
+
+ );
+ } else {
+ percentage = ;
+ }
+ var classes = React.addons.classSet({
+ 'radial-progress': true,
+ 'radial-spinner': this.props.spin
+ });
+ return (
+
+ );
+ }
+});
+
+module.exports = Radial;
diff --git a/app/Setup.react.js b/app/Setup.react.js
new file mode 100644
index 0000000000..934b86e948
--- /dev/null
+++ b/app/Setup.react.js
@@ -0,0 +1,195 @@
+var React = require('react');
+var Router = require('react-router');
+var Radial = require('./Radial.react.js');
+var async = require('async');
+var assign = require('object-assign');
+var fs = require('fs');
+var path = require('path');
+var boot2docker = require('./boot2docker.js');
+var virtualbox = require('./virtualbox.js');
+var util = require('./util.js');
+var docker = require('./docker.js');
+
+var setupSteps = [
+ {
+ run: function (callback, progressCallback) {
+ var installed = virtualbox.installed();
+ if (!installed) {
+ util.download('https://s3.amazonaws.com/kite-installer/' + virtualbox.INSTALLER_FILENAME, path.join(process.cwd(), 'resources', virtualbox.INSTALLER_FILENAME), virtualbox.INSTALLER_CHECKSUM, function (err) {
+ if (err) {callback(err); return;}
+ virtualbox.install(function (err) {
+ if (!virtualbox.installed()) {
+ callback('VirtualBox could not be installed. The installation either failed or was cancelled. Please try closing all VirtualBox instances and try again.');
+ } else {
+ callback(err);
+ }
+ });
+ }, function (progress) {
+ progressCallback(progress);
+ });
+ } else {
+ virtualbox.version(function (err, installedVersion) {
+ if (err) {callback(err); return;}
+ if (util.compareVersions(installedVersion, virtualbox.REQUIRED_VERSION) < 0) {
+ // Download a newer version of Virtualbox
+ util.downloadFile(Setup.BASE_URL + virtualbox.INSTALLER_FILENAME, path.join(util.getResourceDir(), virtualbox.INSTALLER_FILENAME), virtualbox.INSTALLER_CHECKSUM, function (err) {
+ if (err) {callback(err); return;}
+ virtualbox.kill(function (err) {
+ if (err) {callback(err); return;}
+ virtualbox.install(function (err) {
+ if (err) {callback(err); return;}
+ virtualbox.version(function (err, installedVersion) {
+ if (err) {callback(err); return;}
+ if (util.compareVersions(installedVersion, virtualbox.REQUIRED_VERSION) < 0) {
+ callback('VirtualBox could not be installed. The installation either failed or was cancelled. Please try closing all VirtualBox instances and try again.');
+ } else {
+ callback(err);
+ }
+ });
+ });
+ });
+ }, function (progress) {
+ progressCallback(progress);
+ });
+ } else {
+ callback();
+ }
+ });
+ }
+ },
+ message: 'Downloading VirtualBox...'
+ },
+ {
+ run: function (callback) {
+ virtualbox.deleteVM('kitematic-vm', function (err, removed) {
+ if (err) {
+ console.log(err);
+ }
+ callback();
+ });
+ },
+ message: 'Cleaning up existing Docker VM...'
+ },
+
+ // Initialize Boot2Docker if necessary.
+ {
+ run: function (callback) {
+ boot2docker.exists(function (err, exists) {
+ if (err) { callback(err); return; }
+ if (!exists) {
+ boot2docker.init(function (err) {
+ callback(err);
+ });
+ } else {
+ if (!boot2docker.sshKeyExists()) {
+ callback('Boot2Docker SSH key doesn\'t exist. Fix by removing the existing Boot2Docker VM and re-run the installer. This usually occurs because an old version of Boot2Docker is installed.');
+ } else {
+ boot2docker.isoVersion(function (err, version) {
+ if (err || util.compareVersions(version, boot2docker.version()) < 0) {
+ boot2docker.stop(function(err) {
+ boot2docker.upgrade(function (err) {
+ callback(err);
+ });
+ });
+ } else {
+ callback();
+ }
+ });
+ }
+ }
+ });
+ },
+ message: 'Setting up the Docker VM...'
+ },
+ {
+ run: function (callback) {
+ boot2docker.waitWhileStatus('saving', function (err) {
+ boot2docker.status(function (err, status) {
+ if (err) {callback(err); return;}
+ if (status !== 'running') {
+ boot2docker.start(function (err) {
+ callback(err);
+ });
+ } else {
+ callback();
+ }
+ });
+ });
+ },
+ message: 'Starting the Docker VM...'
+ },
+ {
+ run: function (callback) {
+ boot2docker.ip(function (err, ip) {
+ if (err) {callback(err); return;}
+ console.log('Setting host IP to: ' + ip);
+ // Docker.setHost(ip);
+ callback(err);
+ });
+ },
+ message: 'Detecting Docker VM...'
+ }
+];
+
+var Setup = React.createClass({
+ mixins: [ Router.Navigation ],
+ render: function () {
+ var radial;
+ if (this.state.progress) {
+ radial = ;
+ } else {
+ radial = ;
+ }
+ return (
+
+ {radial}
+
{this.state.message}
+
+ );
+ },
+ componentWillMount: function () {
+ this.setState({});
+ },
+ componentDidMount: function () {
+ var self = this;
+ this.setup(function (err) {
+ boot2docker.ip(function (err, ip) {
+ docker.setHost(ip);
+ self.transitionTo('containers');
+ });
+ });
+ },
+ setup: function (callback) {
+ var self = this;
+ var currentStep = 0;
+ async.eachSeries(setupSteps, function (step, callback) {
+ console.log('Performing step ' + currentStep);
+ self.setState({progress: 0});
+ self.setState({message: step.message});
+ step.run(function (err) {
+ if (err) {
+ callback(err);
+ } else {
+ currentStep += 1;
+ callback();
+ }
+ }, function (progress) {
+ self.setState({progress: progress});
+ });
+ }, function (err) {
+ if (err) {
+ // if any of the steps fail
+ console.log('Kitematic setup failed at step ' + currentStep);
+ console.log(err);
+ self.setState({error: err});
+ callback(err);
+ } else {
+ // Setup Finished
+ console.log('Setup finished.');
+ callback();
+ }
+ });
+ }
+});
+
+module.exports = Setup;
diff --git a/app/Store.js b/app/Store.js
deleted file mode 100644
index 7a7c0dbc62..0000000000
--- a/app/Store.js
+++ /dev/null
@@ -1,18 +0,0 @@
-var flux = require('flux-react');
-var actions = require('./actions.js');
-
-module.exports = flux.createStore({
- messages: [],
- actions: [
- actions.addMessage
- ],
- addMessage: function (message) {
- this.messages.push(message);
- this.emitChange();
- },
- exports: {
- getMessages: function () {
- return this.messages;
- }
- }
-});
\ No newline at end of file
diff --git a/app/actions.js b/app/actions.js
deleted file mode 100644
index 1b984841b3..0000000000
--- a/app/actions.js
+++ /dev/null
@@ -1,5 +0,0 @@
-var flux = require('flux-react');
-
-module.exports = flux.createActions([
- 'addMessage'
-]);
\ No newline at end of file
diff --git a/app/boot2docker.js b/app/boot2docker.js
index fba5d2e902..23c6feecb3 100644
--- a/app/boot2docker.js
+++ b/app/boot2docker.js
@@ -6,7 +6,6 @@ var async = require('async');
var cmdExec = function (cmd, callback) {
exec(cmd, function (stderr, stdout, code) {
- console.log(stderr, stdout, code);
if (code) {
callback('Exit code ' + code + ': ' + stderr);
} else {
@@ -21,12 +20,10 @@ var homeDir = function () {
var Boot2Docker = {
version: function () {
- var packagejson = JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf8'));
- return packagejson['boot2docker-version'];
+ return JSON.parse(fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf8'))['boot2docker-version'];
},
cliVersion: function (callback) {
cmdExec([Boot2Docker.command(), 'version'], function (err, out) {
- console.log(err, out);
if (err) {
callback(err);
return;
@@ -61,7 +58,6 @@ var Boot2Docker = {
},
status: function (callback) {
cmdExec([Boot2Docker.command(), 'status'], function (err, out) {
- console.log(err, out);
if (err) {
callback(err);
return;
@@ -192,26 +188,26 @@ var Boot2Docker = {
},
sshKeyExists: function () {
return fs.existsSync(path.join(homeDir(), '.ssh', 'id_boot2docker'));
+ },
+
+ // Todo: move me to setup
+ waitWhileStatus: function (status, callback) {
+ var current = status;
+ async.whilst(function () {
+ return current === status;
+ }, function (callback) {
+ Boot2Docker.status(function (err, vmStatus) {
+ if (err) {
+ callback(err);
+ } else {
+ current = vmStatus.trim();
+ callback();
+ }
+ });
+ }, function (err) {
+ callback(err);
+ });
}
};
module.exports = Boot2Docker;
-
-//TODO: move me to setup
-Boot2Docker.waitWhileStatus = function (status, callback) {
- var current = status;
- async.whilst(function () {
- return current === status;
- }, function (callback) {
- Boot2Docker.status(function (err, vmStatus) {
- if (err) {
- callback(err);
- } else {
- current = vmStatus.trim();
- callback();
- }
- });
- }, function (err) {
- callback(err);
- });
-};
diff --git a/app/docker.js b/app/docker.js
new file mode 100644
index 0000000000..fc96e8e6bc
--- /dev/null
+++ b/app/docker.js
@@ -0,0 +1,26 @@
+var fs = require('fs');
+var path = require('path');
+var dockerode = require('dockerode');
+
+var Docker = {
+ host: null,
+ setHost: function(host) {
+ this.host = host;
+ },
+ client: function () {
+ var certDir = path.join(process.env[(process.platform === 'win32') ? 'USERPROFILE' : 'HOME'], '.boot2docker/certs/boot2docker-vm');
+ if (!fs.existsSync(certDir)) {
+ return null;
+ }
+ return new dockerode({
+ protocol: 'https',
+ host: this.host,
+ port: 2376,
+ ca: fs.readFileSync(path.join(certDir, 'ca.pem')),
+ cert: fs.readFileSync(path.join(certDir, 'cert.pem')),
+ key: fs.readFileSync(path.join(certDir, 'key.pem'))
+ });
+ }
+};
+
+module.exports = Docker;
diff --git a/app/index.html b/app/index.html
index a4343e491c..701d067f25 100644
--- a/app/index.html
+++ b/app/index.html
@@ -4,14 +4,8 @@
-
+
-