mirror of https://github.com/docker/docs.git
Merge branch 'master' into windows
Signed-off-by: Jeffrey Morgan <jmorganca@gmail.com>
This commit is contained in:
commit
ea1dc80240
|
@ -1,6 +1,4 @@
|
|||
language: node_js
|
||||
node_js:
|
||||
- "0.10"
|
||||
|
||||
sudo: false
|
||||
|
||||
|
|
|
@ -6,29 +6,54 @@ Before you fil an issue or a pull request, quickly read of the following tips on
|
|||
|
||||
## Table of Contents
|
||||
|
||||
- [Development](#development)
|
||||
- [Getting Started](#getting-started)
|
||||
- [Architecture](#architecture)
|
||||
- [GitHub Issues](#github-issues)
|
||||
- [Pull Requests](#pull-requests)
|
||||
- [Code Guidelines](#code-guidelines)
|
||||
- [Testing](#testing)
|
||||
- [License](#license)
|
||||
|
||||
### Development
|
||||
|
||||
- `npm install`
|
||||
|
||||
To run the app in development:
|
||||
|
||||
- `npm start`
|
||||
|
||||
### Building & Release
|
||||
|
||||
- `npm run release`
|
||||
|
||||
### Unit Tests
|
||||
|
||||
- `npm test`
|
||||
|
||||
### Getting Started
|
||||
|
||||
- `npm install`
|
||||
|
||||
To run the app in development:
|
||||
|
||||
- `npm start`
|
||||
|
||||
### Building & Release
|
||||
|
||||
- `npm run release`
|
||||
|
||||
### Unit Tests
|
||||
|
||||
- `npm test`
|
||||
|
||||
## Architecture
|
||||
|
||||
### Overview
|
||||
|
||||
**Note: This architecture is work in progress and doesn't reflect the current state of the app, yet!**
|
||||
|
||||
Kitematic is an application built using [atom-shell](https://github.com/atom/atom-shell) and is powered by the [Docker Engine](https://github.com/docker/docker). While it's work in progress, the goal is to make Kitematic a high-performance, portable Javascript ES6 application built with React and Reflux. It adopts a single data flow pattern:
|
||||
|
||||
```
|
||||
╔═════════╗ ╔════════╗ ╔═════════════════╗
|
||||
║ Actions ║──────>║ Stores ║──────>║ View Components ║
|
||||
╚═════════╝ ╚════════╝ ╚═════════════════╝
|
||||
^ │
|
||||
└──────────────────────────────────────┘
|
||||
```
|
||||
|
||||
As explained in the [Reflux docs](https://github.com/spoike/refluxjs), there are three primary types of objects:
|
||||
- **Actions**: The main logic workhorses of the application. These objects interact with the Docker API and other endpoints to fetch new data and flowing it into the stores, which in turn create events that cause views to update.
|
||||
- **Views**: Views make up the UI, and trigger available actions.
|
||||
- **Stores**: Stores store the state of the application.
|
||||
|
||||
### Guidelines
|
||||
|
||||
- Avoid asynchronous code in Stores or Views. Instead, put code involving callbacks, promises or generators in actions.
|
||||
|
||||
## GitHub Issues
|
||||
|
||||
|
@ -54,9 +79,15 @@ We're thrilled to receive pull requests of any kind. Anything from bug fix, test
|
|||
That said, please let us know what you're planning to do! For large changes always create a proposal. Maintainers will love to give you advice on building it and it keeps the app's design coherent.
|
||||
|
||||
### Pull Request Requirements:
|
||||
- Tests
|
||||
- Includes tests
|
||||
- [Signed Off](https://github.com/docker/docker/blob/master/CONTRIBUTING.md#sign-your-work)
|
||||
|
||||
## Testing
|
||||
|
||||
Please try to test any new code.
|
||||
- Tests can be run using `npm test`
|
||||
- Kitematic uses the [Jest framework](https://facebook.github.io/jest/) by Facebook. To keep tests fast, please mock as much as possible.
|
||||
|
||||
## Code Guidelines
|
||||
|
||||
### Javascript
|
||||
|
@ -70,17 +101,7 @@ Kitematic is es6 ready. Please use es6 constructs where possible, they are power
|
|||
|
||||
Run `npm run lint` before committing to ensure your javascript is up to standard. Feel free to suggest changes to the lint spec in `.jshint`.
|
||||
|
||||
### React
|
||||
|
||||
- Use tags and elements appropriate for React / an HTML5 doctype (e.g., self-closing tags)
|
||||
- Try to avoid using JQuery or manually changing the DOM. Use React instead.
|
||||
- Try to build self-contained components that listen and emit events. This is definitely nowhere near perfect yet for the existing codebase.
|
||||
|
||||
## Testing
|
||||
|
||||
While the project is early, please try to test any new code.
|
||||
- Tests can be run using `npm test`
|
||||
- Kitematic uses the [Jest framework](https://facebook.github.io/jest/) by Facebook. To keep tests fast, please mock as much as possible.
|
||||
We designed Kitematic to be easy to build, extend and distribute for developers.
|
||||
|
||||
## License
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
[](https://travis-ci.org/kitematic/kitematic)
|
||||
[](https://coveralls.io/r/kitematic/kitematic?branch=master)
|
||||
[](http://app.bithound.io/kitematic/kitematic)
|
||||
[](https://gitter.im/kitematic/kitematic?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
[](https://www.bithound.io/github/kitematic/kitematic)
|
||||
|
||||
|
||||

|
||||
|
||||
|
@ -27,9 +27,9 @@ Please read through our [Contributing Guidelines](https://github.com/kitematic/k
|
|||
|
||||
## Community
|
||||
|
||||
- For questions on how to use Kitematic, see our [user forum](https://forums.docker.com/c/kitematic).
|
||||
- [](https://gitter.im/kitematic/kitematic?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||
- Ask questions on our [user forum](https://forums.docker.com/c/kitematic).
|
||||
- **#kitematic** on IRC. [Join the channel](http://webchat.freenode.net/?channels=%23kitematic&uio=d4).
|
||||
- Join the Kitematic [Gitter Channel](https://gitter.im/kitematic/kitematic)
|
||||
- Follow [@kitematic on Twitter](https://twitter.com/kitematic).
|
||||
- Read and subscribe to [the Kitematic Blog](http://blog.kitematic.com).
|
||||
|
||||
|
|
10
circle.yml
10
circle.yml
|
@ -1,10 +0,0 @@
|
|||
machine:
|
||||
node:
|
||||
version: 0.10.36
|
||||
dependencies:
|
||||
cache_directories:
|
||||
- "resources"
|
||||
- "node_modules"
|
||||
notify:
|
||||
webhooks:
|
||||
- url: https://coveralls.io/webhook
|
14
gulpfile.js
14
gulpfile.js
|
@ -18,7 +18,7 @@ var shell = require('gulp-shell');
|
|||
var sourcemaps = require('gulp-sourcemaps');
|
||||
|
||||
var dependencies = Object.keys(packagejson.dependencies);
|
||||
var isBeta = process.argv.indexOf('--beta') !== -1;
|
||||
var argv = require('minimist')(process.argv.slice(2));
|
||||
|
||||
var settings;
|
||||
try {
|
||||
|
@ -26,15 +26,15 @@ try {
|
|||
} catch (err) {
|
||||
settings = {};
|
||||
}
|
||||
settings.beta = isBeta;
|
||||
settings.beta = argv.beta;
|
||||
|
||||
var options = {
|
||||
dev: process.argv.indexOf('release') === -1,
|
||||
beta: isBeta,
|
||||
appFilename: isBeta ? 'Kitematic (Beta).app' : 'Kitematic.app',
|
||||
appName: isBeta ? 'Kitematic (Beta)' : 'Kitematic',
|
||||
beta: argv.beta,
|
||||
appFilename: argv.beta ? 'Kitematic (Beta).app' : 'Kitematic.app',
|
||||
appName: argv.beta ? 'Kitematic (Beta)' : 'Kitematic',
|
||||
name: 'Kitematic',
|
||||
icon: isBeta ? './util/kitematic-beta.icns' : './util/kitematic.icns',
|
||||
icon: argv.beta ? './util/kitematic-beta.icns' : './util/kitematic.icns',
|
||||
bundle: 'com.kitematic.kitematic'
|
||||
};
|
||||
|
||||
|
@ -64,7 +64,6 @@ gulp.task('styles', function () {
|
|||
return gulp.src('styles/main.less')
|
||||
.pipe(plumber(function(error) {
|
||||
gutil.log(gutil.colors.red('Error (' + error.plugin + '): ' + error.message));
|
||||
// emit the end event, to properly end the task
|
||||
this.emit('end');
|
||||
}))
|
||||
.pipe(gulpif(options.dev, changed('./build')))
|
||||
|
@ -107,6 +106,7 @@ gulp.task('dist', function () {
|
|||
'mkdir -p dist/osx/<%= filename %>/Contents/Resources/app/resources',
|
||||
'cp -v resources/* dist/osx/<%= filename %>/Contents/Resources/app/resources/ || :',
|
||||
'cp <%= icon %> dist/osx/<%= filename %>/Contents/Resources/atom.icns',
|
||||
'cp ./util/Info.plist dist/osx/<%= filename %>/Contents/Info.plist',
|
||||
'/usr/libexec/PlistBuddy -c "Set :CFBundleVersion <%= version %>" dist/osx/<%= filename %>/Contents/Info.plist',
|
||||
'/usr/libexec/PlistBuddy -c "Set :CFBundleDisplayName <%= name %>" dist/osx/<%= filename %>/Contents/Info.plist',
|
||||
'/usr/libexec/PlistBuddy -c "Set :CFBundleName <%= name %>" dist/osx/<%= filename %>/Contents/Info.plist',
|
||||
|
|
53
package.json
53
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "Kitematic",
|
||||
"version": "0.5.13",
|
||||
"version": "0.5.15",
|
||||
"author": "Kitematic",
|
||||
"description": "Simple Docker Container management for Mac OS X.",
|
||||
"homepage": "https://kitematic.com/",
|
||||
|
@ -12,7 +12,7 @@
|
|||
"bugs": "https://github.com/kitematic/kitematic/issues",
|
||||
"scripts": {
|
||||
"start": "gulp",
|
||||
"test": "jest --coverage",
|
||||
"test": "jest",
|
||||
"release": "gulp release",
|
||||
"release:beta": "gulp release --beta",
|
||||
"lint": "jsxhint src && jsxhint browser",
|
||||
|
@ -44,9 +44,9 @@
|
|||
"<rootDir>/node_modules/bluebird"
|
||||
]
|
||||
},
|
||||
"docker-version": "1.5.0",
|
||||
"docker-machine-version": "0.1.0-kitematic-0.5.10",
|
||||
"atom-shell-version": "0.21.3",
|
||||
"docker-version": "1.6.0",
|
||||
"docker-machine-version": "0.2.0",
|
||||
"atom-shell-version": "0.23.0",
|
||||
"virtualbox-version": "4.3.26",
|
||||
"virtualbox-filename": "VirtualBox-4.3.26.pkg",
|
||||
"virtualbox-filename-win": "VirtualBox-4.3.26.exe",
|
||||
|
@ -56,7 +56,7 @@
|
|||
"ansi-to-html": "0.3.0",
|
||||
"any-promise": "^0.1.0",
|
||||
"async": "^0.9.0",
|
||||
"bluebird": "^2.9.12",
|
||||
"bluebird": "^2.9.24",
|
||||
"bugsnag-js": "^2.4.7",
|
||||
"coveralls": "^2.11.2",
|
||||
"dockerode": "^2.1.1",
|
||||
|
@ -64,41 +64,40 @@
|
|||
"fs-extra": "^0.17.0",
|
||||
"fs-promise": "^0.3.1",
|
||||
"jquery": "^2.1.3",
|
||||
"minimist": "^1.1.0",
|
||||
"mixpanel": "0.0.20",
|
||||
"node-uuid": "^1.4.2",
|
||||
"mixpanel": "0.2.0",
|
||||
"node-uuid": "^1.4.3",
|
||||
"object-assign": "^2.0.0",
|
||||
"open": "0.0.5",
|
||||
"react": "^0.12.2",
|
||||
"react-bootstrap": "^0.15.1",
|
||||
"react": "^0.13.1",
|
||||
"react-bootstrap": "^0.20.3",
|
||||
"react-retina-image": "^1.1.2",
|
||||
"react-router": "^0.12.4",
|
||||
"request": "^2.53.0",
|
||||
"react-router": "^0.13.2",
|
||||
"request": "^2.55.0",
|
||||
"request-progress": "^0.3.1",
|
||||
"rimraf": "^2.2.8",
|
||||
"underscore": "^1.8.2"
|
||||
"rimraf": "^2.3.2",
|
||||
"underscore": "^1.8.3"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel": "^4.5.5",
|
||||
"babel": "^5.1.10",
|
||||
"gulp": "^3.8.11",
|
||||
"gulp-babel": "^4.0.0",
|
||||
"gulp-changed": "^1.1.1",
|
||||
"gulp-babel": "^5.1.0",
|
||||
"gulp-changed": "^1.2.1",
|
||||
"gulp-concat": "^2.5.2",
|
||||
"gulp-cssmin": "^0.1.6",
|
||||
"gulp-download-atom-shell": "0.0.4",
|
||||
"gulp-if": "^1.2.5",
|
||||
"gulp-insert": "^0.4.0",
|
||||
"gulp-less": "^3.0.1",
|
||||
"gulp-less": "^3.0.2",
|
||||
"gulp-livereload": "^3.8.0",
|
||||
"gulp-plumber": "^0.6.6",
|
||||
"gulp-react": "^2.0.0",
|
||||
"gulp-rename": "^1.2.0",
|
||||
"gulp-shell": "^0.3.0",
|
||||
"gulp-sourcemaps": "^1.5.0",
|
||||
"gulp-plumber": "^1.0.0",
|
||||
"gulp-react": "^3.0.1",
|
||||
"gulp-shell": "^0.4.1",
|
||||
"gulp-sourcemaps": "^1.5.2",
|
||||
"gulp-util": "^3.0.4",
|
||||
"gulp": "^3.8.11",
|
||||
"jest-cli": "kitematic/jest",
|
||||
"jsxhint": "^0.12.1",
|
||||
"react-tools": "^0.12.2",
|
||||
"jsxhint": "^0.14.0",
|
||||
"minimist": "^1.1.1",
|
||||
"react-tools": "^0.13.1",
|
||||
"run-sequence": "^1.0.2"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -112,7 +112,7 @@ var ContainerHome = React.createClass({
|
|||
<ContainerHomePreview />
|
||||
</div>
|
||||
<div className="right">
|
||||
<ContainerHomeLogs/>
|
||||
<ContainerHomeLogs container={this.props.container}/>
|
||||
<ContainerHomeFolders container={this.props.container} />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -138,7 +138,7 @@ var ContainerHome = React.createClass({
|
|||
<div className="details-panel home">
|
||||
<div className="content">
|
||||
<div className="left">
|
||||
<ContainerHomeLogs/>
|
||||
<ContainerHomeLogs container={this.props.container}/>
|
||||
</div>
|
||||
{right}
|
||||
</div>
|
||||
|
|
|
@ -6,51 +6,54 @@ var metrics = require('./Metrics');
|
|||
|
||||
var _prevBottom = 0;
|
||||
|
||||
var ContainerHomeLogs = React.createClass({
|
||||
mixins: [Router.State, Router.Navigation],
|
||||
module.exports = React.createClass({
|
||||
mixins: [Router.Navigation],
|
||||
getInitialState: function () {
|
||||
return {
|
||||
logs: []
|
||||
};
|
||||
},
|
||||
componentWillReceiveProps: function () {
|
||||
this.init();
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.init();
|
||||
LogStore.on(LogStore.SERVER_LOGS_EVENT, this.updateLogs);
|
||||
if (!this.props.container) {
|
||||
return;
|
||||
}
|
||||
this.update();
|
||||
this.scrollToBottom();
|
||||
LogStore.on(LogStore.SERVER_LOGS_EVENT, this.update);
|
||||
LogStore.fetch(this.props.container.Name);
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
LogStore.removeListener(LogStore.SERVER_LOGS_EVENT, this.updateLogs);
|
||||
if (!this.props.container) {
|
||||
return;
|
||||
}
|
||||
|
||||
LogStore.detach(this.props.container.Name);
|
||||
LogStore.removeListener(LogStore.SERVER_LOGS_EVENT, this.update);
|
||||
},
|
||||
componentDidUpdate: function () {
|
||||
// Scroll logs to bottom
|
||||
this.scrollToBottom();
|
||||
},
|
||||
scrollToBottom: function () {
|
||||
var parent = $('.logs');
|
||||
if (parent.scrollTop() >= _prevBottom - 50) {
|
||||
parent.scrollTop(parent[0].scrollHeight - parent.height());
|
||||
}
|
||||
_prevBottom = parent[0].scrollHeight - parent.height();
|
||||
},
|
||||
init: function () {
|
||||
this.updateLogs();
|
||||
},
|
||||
updateLogs: function (name) {
|
||||
if (name && name !== this.getParams().name) {
|
||||
return;
|
||||
}
|
||||
this.setState({
|
||||
logs: LogStore.logs(this.getParams().name)
|
||||
});
|
||||
},
|
||||
handleClickLogs: function () {
|
||||
metrics.track('Viewed Logs', {
|
||||
from: 'preview'
|
||||
});
|
||||
this.transitionTo('containerLogs', {name: this.getParams().name});
|
||||
this.transitionTo('containerLogs', {name: this.props.container.Name});
|
||||
},
|
||||
update: function () {
|
||||
this.setState({
|
||||
logs: LogStore.logs(this.props.container.Name)
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
var logs = this.state.logs.map(function (l, i) {
|
||||
return <p key={i} dangerouslySetInnerHTML={{__html: l}}></p>;
|
||||
return <span key={i} dangerouslySetInnerHTML={{__html: l}}></span>;
|
||||
});
|
||||
if (logs.length === 0) {
|
||||
logs = "No logs for this container.";
|
||||
|
@ -62,11 +65,8 @@ var ContainerHomeLogs = React.createClass({
|
|||
<div className="logs">
|
||||
{logs}
|
||||
</div>
|
||||
<div className="mini-logs-overlay" onClick={this.handleClickLogs}><span className="icon icon-scale-spread-1"></span><div className="text">View Logs</div></div>
|
||||
</div>
|
||||
<div className="mini-logs-overlay" onClick={this.handleClickLogs}><span className="icon icon-scale-spread-1"></span><div className="text">View Logs</div></div> </div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ContainerHomeLogs;
|
||||
|
|
|
@ -1,49 +1,46 @@
|
|||
var $ = require('jquery');
|
||||
var React = require('react/addons');
|
||||
var LogStore = require('./LogStore');
|
||||
var Router = require('react-router');
|
||||
|
||||
var _prevBottom = 0;
|
||||
|
||||
var ContainerLogs = React.createClass({
|
||||
mixins: [Router.State],
|
||||
module.exports = React.createClass({
|
||||
getInitialState: function () {
|
||||
return {
|
||||
logs: []
|
||||
};
|
||||
},
|
||||
componentWillReceiveProps: function () {
|
||||
this.init();
|
||||
},
|
||||
componentDidMount: function() {
|
||||
this.init();
|
||||
LogStore.on(LogStore.SERVER_LOGS_EVENT, this.updateLogs);
|
||||
if (!this.props.container) {
|
||||
return;
|
||||
}
|
||||
this.update();
|
||||
this.scrollToBottom();
|
||||
LogStore.on(LogStore.SERVER_LOGS_EVENT, this.update);
|
||||
LogStore.fetch(this.props.container.Name);
|
||||
},
|
||||
componentWillUnmount: function() {
|
||||
LogStore.removeListener(LogStore.SERVER_LOGS_EVENT, this.updateLogs);
|
||||
LogStore.detach(this.props.container.Name);
|
||||
LogStore.removeListener(LogStore.SERVER_LOGS_EVENT, this.update);
|
||||
},
|
||||
componentDidUpdate: function () {
|
||||
// Scroll logs to bottom
|
||||
this.scrollToBottom();
|
||||
},
|
||||
scrollToBottom: function () {
|
||||
var parent = $('.details-logs');
|
||||
if (parent.scrollTop() >= _prevBottom - 50) {
|
||||
parent.scrollTop(parent[0].scrollHeight - parent.height());
|
||||
}
|
||||
_prevBottom = parent[0].scrollHeight - parent.height();
|
||||
},
|
||||
init: function () {
|
||||
this.updateLogs();
|
||||
},
|
||||
updateLogs: function (name) {
|
||||
if (name && name !== this.getParams().name) {
|
||||
return;
|
||||
}
|
||||
update: function () {
|
||||
this.setState({
|
||||
logs: LogStore.logs(this.getParams().name)
|
||||
logs: LogStore.logs(this.props.container.Name)
|
||||
});
|
||||
},
|
||||
render: function () {
|
||||
var logs = this.state.logs.map(function (l, i) {
|
||||
return <p key={i} dangerouslySetInnerHTML={{__html: l}}></p>;
|
||||
return <span key={i} dangerouslySetInnerHTML={{__html: l}}></span>;
|
||||
});
|
||||
if (logs.length === 0) {
|
||||
logs = "No logs for this container.";
|
||||
|
@ -55,5 +52,3 @@ var ContainerLogs = React.createClass({
|
|||
);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = ContainerLogs;
|
||||
|
|
|
@ -2,59 +2,79 @@ var EventEmitter = require('events').EventEmitter;
|
|||
var assign = require('object-assign');
|
||||
var Convert = require('ansi-to-html');
|
||||
var docker = require('./Docker');
|
||||
var stream = require('stream');
|
||||
|
||||
var _convert = new Convert();
|
||||
var _logs = {};
|
||||
var _streams = {};
|
||||
|
||||
var LogStore = assign(Object.create(EventEmitter.prototype), {
|
||||
var MAX_LOG_SIZE = 3000;
|
||||
|
||||
module.exports = assign(Object.create(EventEmitter.prototype), {
|
||||
SERVER_LOGS_EVENT: 'server_logs_event',
|
||||
_escapeHTML: function (html) {
|
||||
_escape: function (html) {
|
||||
var text = document.createTextNode(html);
|
||||
var div = document.createElement('div');
|
||||
div.appendChild(text);
|
||||
return div.innerHTML;
|
||||
},
|
||||
fetchLogs: function (name) {
|
||||
fetch: function (name) {
|
||||
if (!name || !docker.client()) {
|
||||
return;
|
||||
}
|
||||
var index = 0;
|
||||
var self = this;
|
||||
docker.client().getContainer(name).logs({
|
||||
follow: true,
|
||||
stdout: true,
|
||||
stderr: true,
|
||||
timestamps: true
|
||||
}, function (err, stream) {
|
||||
if (_streams[name]) {
|
||||
return;
|
||||
}
|
||||
_streams[name] = stream;
|
||||
timestamps: false,
|
||||
tail: MAX_LOG_SIZE,
|
||||
follow: false
|
||||
}, (err, logStream) => {
|
||||
if (err) {
|
||||
return;
|
||||
throw err;
|
||||
}
|
||||
_logs[name] = [];
|
||||
stream.setEncoding('utf8');
|
||||
stream.on('data', function (buf) {
|
||||
// Every other message is a header
|
||||
if (index % 2 === 1) {
|
||||
//var time = buf.substr(0,buf.indexOf(' '));
|
||||
var msg = buf.substr(buf.indexOf(' ')+1);
|
||||
_logs[name].push(_convert.toHtml(self._escapeHTML(msg)));
|
||||
self.emit(self.SERVER_LOGS_EVENT);
|
||||
}
|
||||
index += 1;
|
||||
var logs = [];
|
||||
var outstream = new stream.PassThrough();
|
||||
docker.client().modem.demuxStream(logStream, outstream, outstream);
|
||||
outstream.on('data', (chunk) => {
|
||||
logs.push(_convert.toHtml(this._escape(chunk)));
|
||||
});
|
||||
stream.on('end', function () {
|
||||
delete _streams[name];
|
||||
logStream.on('end', () => {
|
||||
_logs[name] = logs;
|
||||
this.emit(this.SERVER_LOGS_EVENT);
|
||||
this.attach(name);
|
||||
});
|
||||
});
|
||||
},
|
||||
logs: function (name) {
|
||||
if (!_streams[name]) {
|
||||
this.fetchLogs(name);
|
||||
attach: function (name) {
|
||||
if (!name || !docker.client() || _streams[name]) {
|
||||
return;
|
||||
}
|
||||
docker.client().getContainer(name).attach({
|
||||
stdout: true,
|
||||
stderr: true,
|
||||
logs: false,
|
||||
stream: true
|
||||
}, (err, logStream) => {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
var outstream = new stream.PassThrough();
|
||||
docker.client().modem.demuxStream(logStream, outstream, outstream);
|
||||
outstream.on('data', (chunk) => {
|
||||
_logs[name].push(_convert.toHtml(this._escape(chunk)));
|
||||
if (_logs[name].length > MAX_LOG_SIZE) {
|
||||
_logs[name] = _logs[name].slice(_logs[name].length - MAX_LOG_SIZE, MAX_LOG_SIZE);
|
||||
}
|
||||
this.emit(this.SERVER_LOGS_EVENT);
|
||||
});
|
||||
});
|
||||
},
|
||||
detach: function (name) {
|
||||
if (_streams[name]) {
|
||||
_streams[name].destroy();
|
||||
}
|
||||
},
|
||||
logs: function (name) {
|
||||
return _logs[name] || [];
|
||||
},
|
||||
rename: function (name, newName) {
|
||||
|
@ -63,5 +83,3 @@ var LogStore = assign(Object.create(EventEmitter.prototype), {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = LogStore;
|
||||
|
|
|
@ -81,19 +81,14 @@ describe('SetupStore', function () {
|
|||
machine.isoversion.mockReturnValue('1.0');
|
||||
machine.stop.mockReturnValue(Promise.resolve());
|
||||
machine.start.mockReturnValue(Promise.resolve());
|
||||
machine.regenerateCerts.mockReturnValue(Promise.resolve());
|
||||
machine.upgrade.mockReturnValue(Promise.resolve());
|
||||
setupUtil.compareVersions.mockReturnValue(-1);
|
||||
machine.create.mockClear();
|
||||
machine.upgrade.mockClear();
|
||||
machine.stop.mockClear();
|
||||
machine.start.mockClear();
|
||||
machine.regenerateCerts.mockClear();
|
||||
return setupStore.steps().init.run(() => {}).then(() => {
|
||||
expect(machine.create).not.toBeCalled();
|
||||
expect(machine.stop).toBeCalled();
|
||||
expect(machine.upgrade).toBeCalled();
|
||||
expect(machine.regenerateCerts).toBeCalled();
|
||||
expect(machine.start).toBeCalled();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -99,19 +99,14 @@ var _steps = [{
|
|||
return;
|
||||
}
|
||||
|
||||
if ((yield machine.state()) === 'Saved') {
|
||||
yield virtualBox.wake(machine.name());
|
||||
}
|
||||
|
||||
var isoversion = machine.isoversion();
|
||||
var packagejson = util.packagejson();
|
||||
if (!isoversion || setupUtil.compareVersions(isoversion, packagejson['docker-version']) < 0) {
|
||||
yield machine.stop();
|
||||
yield machine.start();
|
||||
yield machine.upgrade();
|
||||
}
|
||||
if ((yield machine.state()) !== 'Running') {
|
||||
yield machine.start();
|
||||
yield machine.regenerateCerts();
|
||||
}
|
||||
})
|
||||
}];
|
||||
|
|
|
@ -21,9 +21,7 @@ fi
|
|||
if [ ! -f $DOCKER_MACHINE_CLI_FILE ]; then
|
||||
echo "-----> Downloading Docker Machine CLI..."
|
||||
rm -rf docker-machine*
|
||||
# Use temporary, new version of docker-machine that has some important fixes
|
||||
# curl -L -o $DOCKER_MACHINE_CLI_FILE https://github.com/docker/machine/releases/download/v$DOCKER_MACHINE_CLI_VERSION/docker-machine_darwin-amd64
|
||||
curl -L -o $DOCKER_MACHINE_CLI_FILE https://github.com/kitematic/kitematic/releases/download/v0.5.10/docker-machine_darwin-amd64
|
||||
curl -L -o $DOCKER_MACHINE_CLI_FILE https://github.com/docker/machine/releases/download/v$DOCKER_MACHINE_CLI_VERSION/docker-machine_darwin-amd64
|
||||
chmod +x $DOCKER_MACHINE_CLI_FILE
|
||||
fi
|
||||
|
||||
|
|
Loading…
Reference in New Issue