deploy.sh 1.0.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintignore +1 -0
- package/.eslintrc +4 -15
- package/.github/workflows/ci.yml +48 -0
- package/.husky/pre-commit +5 -0
- package/{test/fixtures/static/out.gifcd → .prettierrc} +0 -0
- package/.release-it.json +5 -0
- package/README.md +3 -4
- package/{test → __tests__}/fixtures/unknown/.gitkeep +0 -0
- package/__tests__/lib/classifier.test.js +49 -0
- package/__tests__/lib/helpers/util.test.js +57 -0
- package/bin/deploy-delete.js +5 -2
- package/bin/deploy-deploy.js +16 -11
- package/bin/deploy-list.js +17 -9
- package/bin/deploy-login.js +25 -21
- package/bin/deploy-logout.js +8 -4
- package/bin/deploy-logs.js +19 -12
- package/bin/deploy-open.js +13 -6
- package/bin/deploy-register.js +25 -20
- package/bin/deploy-server.js +9 -3
- package/bin/deploy-whoami.js +8 -6
- package/bin/deploy.js +97 -71
- package/{test/fixtures → examples}/docker/Dockerfile +0 -0
- package/examples/docker/index.js +12 -0
- package/examples/node/index.js +8 -0
- package/{test/fixtures → examples}/node/package.json +0 -0
- package/examples/static/index.html +22 -0
- package/{test/fixtures → examples}/static/main.css +4 -2
- package/examples/static/out.gifcd +0 -0
- package/generate-docs.js +55 -0
- package/index.js +37 -23
- package/lib/classifier.js +18 -16
- package/lib/deploy.js +30 -22
- package/lib/helpers/cli.js +66 -59
- package/lib/helpers/util.js +36 -30
- package/lib/models/deployment.js +157 -138
- package/lib/models/request.js +29 -26
- package/lib/models/user.js +41 -32
- package/lib/server.js +177 -131
- package/lib/static/static-server.js +52 -51
- package/package.json +43 -33
- package/website/README.md +41 -0
- package/website/babel.config.js +3 -0
- package/website/docs/api/_category_.yml +1 -0
- package/website/docs/api/lib/classifier.js.md +11 -0
- package/website/docs/api/lib/deploy.js.md +13 -0
- package/website/docs/api/lib/helpers/cli.js.md +193 -0
- package/website/docs/api/lib/helpers/util.js.md +65 -0
- package/website/docs/api/lib/models/deployment.js.md +171 -0
- package/website/docs/api/lib/models/request.js.md +67 -0
- package/website/docs/api/lib/models/user.js.md +92 -0
- package/website/docs/api/lib/server.js.md +0 -0
- package/website/docs/api/lib/static/static-server.js.md +0 -0
- package/website/docs/intro.md +57 -0
- package/website/docusaurus.config.js +82 -0
- package/website/package-lock.json +25218 -0
- package/website/package.json +39 -0
- package/website/sidebars.js +31 -0
- package/website/src/components/HomepageFeatures/index.js +79 -0
- package/website/src/components/HomepageFeatures/styles.module.css +11 -0
- package/website/src/css/custom.css +39 -0
- package/website/src/pages/index.js +57 -0
- package/website/src/pages/index.module.css +23 -0
- package/website/static/.nojekyll +0 -0
- package/{docs → website/static}/example.gif +0 -0
- package/{docs → website/static}/example.mov +0 -0
- package/website/static/img/favicon.ico +0 -0
- package/website/static/img/intro/deploy.png +0 -0
- package/website/static/img/intro/logs.png +0 -0
- package/{docs → website/static/img}/logo.png +0 -0
- package/{docs → website/static/img}/logo.pxm +0 -0
- package/{docs → website/static/img}/logo@2x.png +0 -0
- package/.travis.yml +0 -9
- package/.tryitout +0 -48
- package/docs/code/CLI.html +0 -2901
- package/docs/code/Deployment.html +0 -2469
- package/docs/code/Request.html +0 -906
- package/docs/code/User.html +0 -1219
- package/docs/code/classifier.js.html +0 -121
- package/docs/code/deploy.js.html +0 -122
- package/docs/code/fonts/OpenSans-Bold-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-Bold-webfont.svg +0 -1830
- package/docs/code/fonts/OpenSans-Bold-webfont.woff +0 -0
- package/docs/code/fonts/OpenSans-BoldItalic-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-BoldItalic-webfont.svg +0 -1830
- package/docs/code/fonts/OpenSans-BoldItalic-webfont.woff +0 -0
- package/docs/code/fonts/OpenSans-Italic-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-Italic-webfont.svg +0 -1830
- package/docs/code/fonts/OpenSans-Italic-webfont.woff +0 -0
- package/docs/code/fonts/OpenSans-Light-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-Light-webfont.svg +0 -1831
- package/docs/code/fonts/OpenSans-Light-webfont.woff +0 -0
- package/docs/code/fonts/OpenSans-LightItalic-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-LightItalic-webfont.svg +0 -1835
- package/docs/code/fonts/OpenSans-LightItalic-webfont.woff +0 -0
- package/docs/code/fonts/OpenSans-Regular-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-Regular-webfont.svg +0 -1831
- package/docs/code/fonts/OpenSans-Regular-webfont.woff +0 -0
- package/docs/code/fonts/OpenSans-Semibold-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-Semibold-webfont.svg +0 -1830
- package/docs/code/fonts/OpenSans-Semibold-webfont.ttf +0 -0
- package/docs/code/fonts/OpenSans-Semibold-webfont.woff +0 -0
- package/docs/code/fonts/OpenSans-SemiboldItalic-webfont.eot +0 -0
- package/docs/code/fonts/OpenSans-SemiboldItalic-webfont.svg +0 -1830
- package/docs/code/fonts/OpenSans-SemiboldItalic-webfont.ttf +0 -0
- package/docs/code/fonts/OpenSans-SemiboldItalic-webfont.woff +0 -0
- package/docs/code/helpers_cli.js.html +0 -315
- package/docs/code/helpers_util.js.html +0 -194
- package/docs/code/index.html +0 -66
- package/docs/code/models_deployment.js.html +0 -515
- package/docs/code/models_request.js.html +0 -158
- package/docs/code/models_user.js.html +0 -198
- package/docs/code/module-lib_classifier.html +0 -246
- package/docs/code/module-lib_deploy.html +0 -350
- package/docs/code/module-lib_helpers_util.html +0 -707
- package/docs/code/scripts/linenumber.js +0 -25
- package/docs/code/scripts/prettify/Apache-License-2.0.txt +0 -202
- package/docs/code/scripts/prettify/lang-css.js +0 -2
- package/docs/code/scripts/prettify/prettify.js +0 -28
- package/docs/code/styles/jsdoc-default.css +0 -692
- package/docs/code/styles/prettify-jsdoc.css +0 -111
- package/docs/code/styles/prettify-tomorrow.css +0 -132
- package/docs/index.html +0 -4463
- package/docs/main.css +0 -162
- package/docs/main.js +0 -53
- package/test/fixtures/docker/index.js +0 -12
- package/test/fixtures/node/index.js +0 -8
- package/test/fixtures/static/index.html +0 -14
- package/test/lib/classifier.js +0 -51
- package/test/lib/helpers/util.js +0 -47
|
@@ -1,515 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="utf-8">
|
|
5
|
-
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
6
|
-
<title>models/deployment.js - Documentation</title>
|
|
7
|
-
|
|
8
|
-
<script src="scripts/prettify/prettify.js"></script>
|
|
9
|
-
<script src="scripts/prettify/lang-css.js"></script>
|
|
10
|
-
<!--[if lt IE 9]>
|
|
11
|
-
<script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
|
|
12
|
-
<![endif]-->
|
|
13
|
-
<link type="text/css" rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
|
|
14
|
-
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
|
|
15
|
-
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
|
|
16
|
-
</head>
|
|
17
|
-
<body>
|
|
18
|
-
|
|
19
|
-
<input type="checkbox" id="nav-trigger" class="nav-trigger" />
|
|
20
|
-
<label for="nav-trigger" class="navicon-button x">
|
|
21
|
-
<div class="navicon"></div>
|
|
22
|
-
</label>
|
|
23
|
-
|
|
24
|
-
<label for="nav-trigger" class="overlay"></label>
|
|
25
|
-
|
|
26
|
-
<nav>
|
|
27
|
-
<li class="nav-link nav-home-link"><a href="index.html">Home</a></li><li class="nav-heading">Classes</li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="CLI.html">CLI</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="CLI.html#.cacheCredentials">cacheCredentials</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="CLI.html#.createBundle">createBundle</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="CLI.html#.deleteDeployment">deleteDeployment</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="CLI.html#.getCredentials">getCredentials</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="CLI.html#.getDeployments">getDeployments</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="CLI.html#.getLogs">getLogs</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="CLI.html#.getUserDetails">getUserDetails</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="CLI.html#.login">login</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="CLI.html#.logout">logout</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="CLI.html#.register">register</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="CLI.html#.removeBundle">removeBundle</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="CLI.html#.uploadBundle">uploadBundle</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Deployment.html">Deployment</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Deployment.html#.decorate">decorate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Deployment.html#.del">del</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Deployment.html#.get">get</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Deployment.html#.getAll">getAll</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Deployment.html#.logs">logs</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Deployment.html#.proxy">proxy</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Deployment.html#.remove">remove</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Deployment.html#.start">start</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Deployment.html#.stop">stop</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Deployment.html#.update">update</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="Request.html">Request</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Request.html#.count">count</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Request.html#.del">del</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="Request.html#.log">log</a></span></li><li class="nav-heading"><span class="nav-item-type type-class">C</span><span class="nav-item-name"><a href="User.html">User</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="User.html#.authenticate">authenticate</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="User.html#.authenticateMiddleware">authenticateMiddleware</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="User.html#.login">login</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="User.html#.logout">logout</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="User.html#.register">register</a></span></li><li class="nav-heading">Modules</li><li class="nav-heading"><span class="nav-item-type type-module">M</span><span class="nav-item-name"><a href="module-lib_classifier.html">lib/classifier</a></span></li><li class="nav-heading"><span class="nav-item-type type-module">M</span><span class="nav-item-name"><a href="module-lib_deploy.html">lib/deploy</a></span></li><li class="nav-heading"><span class="nav-item-type type-module">M</span><span class="nav-item-name"><a href="module-lib_helpers_util.html">lib/helpers/util</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="module-lib_helpers_util.html#.mk">mk</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="module-lib_helpers_util.html#~contains">contains</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="module-lib_helpers_util.html#~getPort">getPort</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="module-lib_helpers_util.html#~hash">hash</a></span></li>
|
|
28
|
-
</nav>
|
|
29
|
-
|
|
30
|
-
<div id="main">
|
|
31
|
-
|
|
32
|
-
<h1 class="page-title">models/deployment.js</h1>
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
<section>
|
|
41
|
-
<article>
|
|
42
|
-
<pre class="prettyprint source linenums"><code>const mongoose = require('mongoose');
|
|
43
|
-
const http = require('http');
|
|
44
|
-
const fs = require('fs');
|
|
45
|
-
const path = require('path');
|
|
46
|
-
const Docker = require('dockerode');
|
|
47
|
-
const docker = new Docker({
|
|
48
|
-
socketPath: '/var/run/docker.sock'
|
|
49
|
-
});
|
|
50
|
-
const stream = require('stream');
|
|
51
|
-
|
|
52
|
-
const Schema = mongoose.Schema;
|
|
53
|
-
|
|
54
|
-
const { authenticate } = require('./user');
|
|
55
|
-
const { hash, rm } = require('../helpers/util');
|
|
56
|
-
const { count } = require('./request');
|
|
57
|
-
const deleteRequests = require('./request').del;
|
|
58
|
-
|
|
59
|
-
const DeploymentSchema = new Schema({
|
|
60
|
-
id: String,
|
|
61
|
-
name: String,
|
|
62
|
-
port: Number,
|
|
63
|
-
subdomain: String,
|
|
64
|
-
directory: String,
|
|
65
|
-
username: String
|
|
66
|
-
}, {
|
|
67
|
-
minimize: false,
|
|
68
|
-
timestamps: {
|
|
69
|
-
createdAt: 'created_at',
|
|
70
|
-
updatedAt: 'updated_at'
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
const DeploymentModel = mongoose.model('Deployment', DeploymentSchema);
|
|
75
|
-
|
|
76
|
-
/**
|
|
77
|
-
* Deployment definition
|
|
78
|
-
* @class Deployment
|
|
79
|
-
* @property {String} id - the container id
|
|
80
|
-
* @property {String} name - the name of the deployment
|
|
81
|
-
* @property {Number} port - the port that the container has exposed
|
|
82
|
-
* @property {String} subdomain - the subdomain of the application
|
|
83
|
-
* @property {String} directory - the directory of tared application
|
|
84
|
-
* @property {String} username - the username who owns the deployment
|
|
85
|
-
*/
|
|
86
|
-
class Deployment {
|
|
87
|
-
/**
|
|
88
|
-
* updates a deployment
|
|
89
|
-
* @method update
|
|
90
|
-
* @memberof Deployment
|
|
91
|
-
* @param {Object} options
|
|
92
|
-
* @param {String} options.name - the name of the deployment
|
|
93
|
-
* @param {String} options.username - the username associated with this deployment
|
|
94
|
-
* @return {Promise}
|
|
95
|
-
*/
|
|
96
|
-
static async update({ name, token, username, deployment }) {
|
|
97
|
-
let user = await authenticate(username, token);
|
|
98
|
-
|
|
99
|
-
let found = await DeploymentModel.findOne({
|
|
100
|
-
username: user.username,
|
|
101
|
-
name
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
if(found) {
|
|
105
|
-
|
|
106
|
-
found.id = deployment.id || found.id;
|
|
107
|
-
found.name = deployment.name || found.name;
|
|
108
|
-
found.port = deployment.port || found.port;
|
|
109
|
-
found.subdomain = deployment.subdomain || found.subdomain;
|
|
110
|
-
found.directory = deployment.directory || found.directory;
|
|
111
|
-
found.username = user.username;
|
|
112
|
-
|
|
113
|
-
await found.save();
|
|
114
|
-
|
|
115
|
-
return found;
|
|
116
|
-
} else {
|
|
117
|
-
const deployment = {
|
|
118
|
-
name,
|
|
119
|
-
subdomain: `${name}-${hash(6)}`,
|
|
120
|
-
username: user.username
|
|
121
|
-
};
|
|
122
|
-
return await DeploymentModel.create(deployment);
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
/**
|
|
126
|
-
* deletes the specified deployment from the user
|
|
127
|
-
* @method del
|
|
128
|
-
* @memberof Deployment
|
|
129
|
-
* @param {String} name - the name of the deployment
|
|
130
|
-
* @param {String} options.token - the token for the user who owns the deployment
|
|
131
|
-
* @param {String} options.username - the username associated with this deployment
|
|
132
|
-
* @return {Promise}
|
|
133
|
-
*/
|
|
134
|
-
static async del({ name, username, token }) {
|
|
135
|
-
const user = await authenticate(username, token);
|
|
136
|
-
|
|
137
|
-
const deployment = await DeploymentModel.findOne({
|
|
138
|
-
username: user.username,
|
|
139
|
-
name
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
await rm(deployment.directory);
|
|
143
|
-
|
|
144
|
-
await Deployment.remove({
|
|
145
|
-
subdomain: deployment.subdomain,
|
|
146
|
-
token,
|
|
147
|
-
username: user.username
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
await deployment.remove();
|
|
151
|
-
|
|
152
|
-
await deleteRequests({
|
|
153
|
-
subdomain: deployment.subdomain
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
/**
|
|
157
|
-
* express middleware to proxy to correct container
|
|
158
|
-
* @method proxy
|
|
159
|
-
* @memberof Deployment
|
|
160
|
-
* @param {String} subdomain - the subdomain for the application being requested
|
|
161
|
-
* @return {Promise}
|
|
162
|
-
*/
|
|
163
|
-
static async proxy(req, res) {
|
|
164
|
-
const { url, method, headers } = req;
|
|
165
|
-
const { host } = headers;
|
|
166
|
-
|
|
167
|
-
// If this is not an upload request, it is a proxy request
|
|
168
|
-
const subdomain = host.split('.')[0];
|
|
169
|
-
|
|
170
|
-
let deployment = await DeploymentModel.findOne({
|
|
171
|
-
"subdomain":{
|
|
172
|
-
"$eq": subdomain
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
if(!deployment) {
|
|
177
|
-
return res.status(404).sendFile(path.resolve(__dirname, '../static/not-found.html'));
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
const { port } = deployment;
|
|
181
|
-
const proxy = http.request({
|
|
182
|
-
method,
|
|
183
|
-
path: url,
|
|
184
|
-
headers,
|
|
185
|
-
port,
|
|
186
|
-
host: 'localhost'
|
|
187
|
-
});
|
|
188
|
-
proxy.addListener('response', function (proxy_response) {
|
|
189
|
-
proxy_response.addListener('data', (chunk) => res.write(chunk, 'binary'));
|
|
190
|
-
proxy_response.addListener('end', () => res.end());
|
|
191
|
-
res.writeHead(proxy_response.statusCode, proxy_response.headers);
|
|
192
|
-
});
|
|
193
|
-
proxy.on('error', () => {
|
|
194
|
-
res.status(502).sendFile(path.resolve(__dirname, '../static/page-could-not-load.html'));
|
|
195
|
-
});
|
|
196
|
-
req.addListener('data', (chunk) => proxy.write(chunk, 'binary'));
|
|
197
|
-
req.addListener('end', () => proxy.end());
|
|
198
|
-
}
|
|
199
|
-
/**
|
|
200
|
-
* decorates a deployment with the correct data on get
|
|
201
|
-
* @method decorate
|
|
202
|
-
* @memberof Deployment
|
|
203
|
-
* @param {Deployment} deployment - a deployment instance
|
|
204
|
-
* @return {Promise}
|
|
205
|
-
*/
|
|
206
|
-
static async decorate(deployment) {
|
|
207
|
-
let requests = await count({ subdomain: deployment.subdomain });
|
|
208
|
-
|
|
209
|
-
deployment.requests = requests || 0;
|
|
210
|
-
|
|
211
|
-
const container = docker.getContainer(deployment.id);
|
|
212
|
-
|
|
213
|
-
try {
|
|
214
|
-
let info = await container.inspect();
|
|
215
|
-
|
|
216
|
-
deployment.status = info.State.Status;
|
|
217
|
-
} catch(ex) {
|
|
218
|
-
deployment.status = 'error';
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
return deployment;
|
|
222
|
-
}
|
|
223
|
-
/**
|
|
224
|
-
* gets a specific deployment for the specified user
|
|
225
|
-
* @method get
|
|
226
|
-
* @memberof Deployment
|
|
227
|
-
* @param {Object} options
|
|
228
|
-
* @param {String} options.name - the name of the deployment
|
|
229
|
-
* @param {String} options.token - the token for the user who owns the deployment
|
|
230
|
-
* @param {String} options.username - the username associated with this deployment
|
|
231
|
-
* @param {Boolean} option.create - create a deployment if not found
|
|
232
|
-
* @return {Promise}
|
|
233
|
-
*/
|
|
234
|
-
static async get({ name, token, username, create }) {
|
|
235
|
-
let user = await authenticate(username, token);
|
|
236
|
-
|
|
237
|
-
let deployment = await DeploymentModel.findOne({
|
|
238
|
-
username: user.username,
|
|
239
|
-
name
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
if(deployment) {
|
|
243
|
-
return await Deployment.decorate(deployment._doc);
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
if(create) {
|
|
247
|
-
// add a new deployment name
|
|
248
|
-
// TODO: figure out how to avoid collisions
|
|
249
|
-
return await DeploymentModel.create({
|
|
250
|
-
name,
|
|
251
|
-
subdomain: `${name}-${hash(6)}`,
|
|
252
|
-
username: user.username,
|
|
253
|
-
});
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
/**
|
|
257
|
-
* gets all deployments for the specified user
|
|
258
|
-
* @method getAll
|
|
259
|
-
* @memberof Deployment
|
|
260
|
-
* @param {String} options.token - the token for the user who owns the deployment
|
|
261
|
-
* @param {String} options.username - the username associated with this deployment
|
|
262
|
-
* @return {Promise}
|
|
263
|
-
*/
|
|
264
|
-
static async getAll({ token, username }) {
|
|
265
|
-
let user = await authenticate(username, token);
|
|
266
|
-
|
|
267
|
-
let deployments = await DeploymentModel.find({
|
|
268
|
-
username: user.username
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
for(var i = 0; i < deployments.length; i++) {
|
|
272
|
-
deployments[i] = await Deployment.decorate(deployments[i]._doc);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
return deployments;
|
|
276
|
-
}
|
|
277
|
-
static build({ name, subdomain, username, token, port, directory }) {
|
|
278
|
-
function recurse(directory) {
|
|
279
|
-
let files = [];
|
|
280
|
-
fs.readdirSync(directory).map((f) => {
|
|
281
|
-
let stat = fs.statSync(`${directory}/${f}`);
|
|
282
|
-
if(stat.isDirectory()) {
|
|
283
|
-
files = files.concat(recurse(`${directory}/${f}`));
|
|
284
|
-
} else {
|
|
285
|
-
files.push(`${directory}/${f}`);
|
|
286
|
-
}
|
|
287
|
-
});
|
|
288
|
-
return files;
|
|
289
|
-
}
|
|
290
|
-
// we are working off the the relative paths and we need to make the absolute paths relative to context
|
|
291
|
-
let src = recurse(directory).map((f) => f.replace(directory, ''));
|
|
292
|
-
|
|
293
|
-
return new Promise(function(resolve, reject) {
|
|
294
|
-
docker.buildImage({
|
|
295
|
-
context: directory,
|
|
296
|
-
src
|
|
297
|
-
}, {
|
|
298
|
-
t: subdomain
|
|
299
|
-
}, (err, stream) => {
|
|
300
|
-
if(err) return reject(err);
|
|
301
|
-
docker.modem.followProgress(stream, onFinished, onProgress);
|
|
302
|
-
|
|
303
|
-
function onFinished(err) {
|
|
304
|
-
if(err) return reject(err);
|
|
305
|
-
docker.createContainer({
|
|
306
|
-
Image: subdomain,
|
|
307
|
-
name: subdomain,
|
|
308
|
-
env: [
|
|
309
|
-
'PORT=3000'
|
|
310
|
-
],
|
|
311
|
-
ExposedPorts: {
|
|
312
|
-
'3000/tcp': {}
|
|
313
|
-
},
|
|
314
|
-
PortBindings: {
|
|
315
|
-
'3000/tcp': [{
|
|
316
|
-
'HostPort': `${port}`
|
|
317
|
-
}]
|
|
318
|
-
},
|
|
319
|
-
Privileged: true
|
|
320
|
-
}, (err, container) => {
|
|
321
|
-
if (err) return reject(err);
|
|
322
|
-
container.start((err) => {
|
|
323
|
-
if (err) return reject(err);
|
|
324
|
-
const id = container.id;
|
|
325
|
-
|
|
326
|
-
Deployment.update({
|
|
327
|
-
name,
|
|
328
|
-
username,
|
|
329
|
-
token,
|
|
330
|
-
deployment: {
|
|
331
|
-
id,
|
|
332
|
-
port,
|
|
333
|
-
directory
|
|
334
|
-
}
|
|
335
|
-
})
|
|
336
|
-
.then((deployment) => resolve(deployment))
|
|
337
|
-
.catch((ex) => reject(ex));
|
|
338
|
-
});
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
// TODO: be able to stream the output of this to a socket to give real time updates
|
|
342
|
-
function onProgress() {
|
|
343
|
-
// console.log(ev);
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
});
|
|
347
|
-
}
|
|
348
|
-
/**
|
|
349
|
-
* starts a container or all containers
|
|
350
|
-
* @method start
|
|
351
|
-
* @memberof Deployment
|
|
352
|
-
* @param {String=} name - to start a specific container a name property is needed
|
|
353
|
-
* @param {String} options.token - the token for the user who owns the deployment
|
|
354
|
-
* @param {String} options.username - the username associated with this deployment
|
|
355
|
-
* @return {Promise}
|
|
356
|
-
*/
|
|
357
|
-
static async start({ name, username, token }) {
|
|
358
|
-
let opts = {};
|
|
359
|
-
// TODO: check username and token to make sure the request is authenticated
|
|
360
|
-
if(username && token) {
|
|
361
|
-
opts.username = username;
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
const deployments = await DeploymentModel.find(opts);
|
|
365
|
-
|
|
366
|
-
if(deployments.length === 0) return;
|
|
367
|
-
|
|
368
|
-
for(var i = 0; i < deployments.length; i++) {
|
|
369
|
-
const deployment = deployments[i];
|
|
370
|
-
|
|
371
|
-
if(name && deployment.name == name) {
|
|
372
|
-
await docker.getContainer(deployment.id).start();
|
|
373
|
-
}
|
|
374
|
-
if(!name) {
|
|
375
|
-
await docker.getContainer(deployment.id).start();
|
|
376
|
-
}
|
|
377
|
-
}
|
|
378
|
-
return deployments;
|
|
379
|
-
}
|
|
380
|
-
/**
|
|
381
|
-
* stops a container or all containers
|
|
382
|
-
* @method stop
|
|
383
|
-
* @memberof Deployment
|
|
384
|
-
* @param {String=} name - to stop a specific container a name property is needed
|
|
385
|
-
* @param {String=} options.token - the token for the user who owns the deployment
|
|
386
|
-
* @param {String=} options.username - the username associated with this deployment
|
|
387
|
-
* @return {Promise}
|
|
388
|
-
*/
|
|
389
|
-
static async stop({ name, token, username }) {
|
|
390
|
-
let opts = {};
|
|
391
|
-
// TODO: check username and token to make sure the request is authenticated
|
|
392
|
-
if(username && token) {
|
|
393
|
-
opts.username = username;
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
const deployments = await DeploymentModel.find(opts);
|
|
397
|
-
|
|
398
|
-
if(deployments.length === 0) return;
|
|
399
|
-
|
|
400
|
-
for(var i = 0; i < deployments.length; i++) {
|
|
401
|
-
const deployment = deployments[i];
|
|
402
|
-
|
|
403
|
-
if(name && deployment.name == name) {
|
|
404
|
-
await docker.getContainer(deployment.id).kill({ force: true });
|
|
405
|
-
}
|
|
406
|
-
if(!name) {
|
|
407
|
-
await docker.getContainer(deployment.id).kill({ force: true });
|
|
408
|
-
}
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
return deployments;
|
|
412
|
-
}
|
|
413
|
-
/**
|
|
414
|
-
* retrieves from a given instance
|
|
415
|
-
* @method logs
|
|
416
|
-
* @memberof Deployment
|
|
417
|
-
* @param {String} name - instance name
|
|
418
|
-
* @param {String} token - the token for the user who owns the deployment
|
|
419
|
-
* @param {String} username - the username associated with this deployment
|
|
420
|
-
* @return {Promise}
|
|
421
|
-
*/
|
|
422
|
-
static logs({ name, token, username }) {
|
|
423
|
-
return new Promise(async (resolve, reject) => {
|
|
424
|
-
try {
|
|
425
|
-
const user = await authenticate(username, token);
|
|
426
|
-
|
|
427
|
-
const deployment = await DeploymentModel.findOne({
|
|
428
|
-
name,
|
|
429
|
-
username: user.username
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
const logs = [];
|
|
433
|
-
const container = docker.getContainer(deployment.id);
|
|
434
|
-
|
|
435
|
-
const logStream = new stream.PassThrough();
|
|
436
|
-
|
|
437
|
-
logStream.on('data', (chunk) => { logs.push(chunk.toString('utf8')); });
|
|
438
|
-
|
|
439
|
-
const cStream = await container.logs({
|
|
440
|
-
follow: true,
|
|
441
|
-
stdout: true,
|
|
442
|
-
stderr: true
|
|
443
|
-
});
|
|
444
|
-
|
|
445
|
-
container.modem.demuxStream(cStream, logStream, logStream);
|
|
446
|
-
cStream.on('end', function(){
|
|
447
|
-
return resolve(logs);
|
|
448
|
-
});
|
|
449
|
-
|
|
450
|
-
setTimeout(function() {
|
|
451
|
-
cStream.destroy();
|
|
452
|
-
}, 2000);
|
|
453
|
-
} catch(ex) {
|
|
454
|
-
return reject(ex);
|
|
455
|
-
}
|
|
456
|
-
});
|
|
457
|
-
}
|
|
458
|
-
/**
|
|
459
|
-
* removes a specific container, will stop and cleanup all necessary files
|
|
460
|
-
* @method remove
|
|
461
|
-
* @memberof Deployment
|
|
462
|
-
* @param {String} name - the name of the container
|
|
463
|
-
* @param {String} options.token - the token for the user who owns the deployment
|
|
464
|
-
* @param {String} options.username - the username associated with this deployment
|
|
465
|
-
* @return {Promise}
|
|
466
|
-
*/
|
|
467
|
-
static async remove({ subdomain, token, username }) {
|
|
468
|
-
let user = await authenticate(username, token);
|
|
469
|
-
|
|
470
|
-
let deployment = await DeploymentModel.findOne({
|
|
471
|
-
subdomain: subdomain,
|
|
472
|
-
username: user.username
|
|
473
|
-
});
|
|
474
|
-
|
|
475
|
-
try {
|
|
476
|
-
const container = docker.getContainer(deployment.id);
|
|
477
|
-
|
|
478
|
-
await container.kill();
|
|
479
|
-
|
|
480
|
-
let info = await container.inspect();
|
|
481
|
-
|
|
482
|
-
await docker.getImage(info.Image).remove({
|
|
483
|
-
force: true
|
|
484
|
-
});
|
|
485
|
-
await container.remove();
|
|
486
|
-
} catch(ex) {
|
|
487
|
-
if(ex.reason !== 'no such container') {
|
|
488
|
-
throw new Error(ex);
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
|
|
492
|
-
return deployment;
|
|
493
|
-
}
|
|
494
|
-
}
|
|
495
|
-
|
|
496
|
-
module.exports = Deployment;
|
|
497
|
-
</code></pre>
|
|
498
|
-
</article>
|
|
499
|
-
</section>
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
</div>
|
|
505
|
-
|
|
506
|
-
<br class="clear">
|
|
507
|
-
|
|
508
|
-
<footer>
|
|
509
|
-
Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 3.5.5</a> using the Minami theme.
|
|
510
|
-
</footer>
|
|
511
|
-
|
|
512
|
-
<script>prettyPrint();</script>
|
|
513
|
-
<script src="scripts/linenumber.js"></script>
|
|
514
|
-
</body>
|
|
515
|
-
</html>
|