-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
257 lines (223 loc) · 10.6 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
'use strict';
var _ = require('lodash');
var fs = require('fs');
var exec = require('child-process-promise').exec;
var Promise = require("bluebird");
var chalk = require('chalk');
module.exports = (function DockerServiceRunnerClassWrapper(_) {
function DockerServiceRunner() {
}
var _dockerContainers = [];
var _dockerRepositoriesRootFolder = '/usr/local/docker';
DockerServiceRunner.prototype.run = function run(optionsPlural) {
var _this = this, i = 0, promises;
return new Promise(function runPromise(resolve, reject) {
promises = _.map(optionsPlural, function (opt) {
return _this.runSingle(opt)
});
Promise.all(promises).then(function killAllContainersThen() {
resolve();
}).catch(function killAllContainersCatcher(e) {
reject({
message: 'Could not run all images error attached',
err: e
});
});
});
};
DockerServiceRunner.prototype.runSingle = function runSingle(options) {
var _this = this;
return new Promise(function runMainPromise(resolve, reject) {
if (_this.validateOptions(options)) {
// Basic validations for what we need in order to run
DockerServiceRunner.validateDockerRootFolderExists()
.then(function validateDockerRootFolderExistsThen() {
console.log('validating terminal..');
return DockerServiceRunner.validateRunningInDockerTerminal();
})
.then(function validateRunningInDockerTerminalThen() {
console.log('validating git is installed..');
return DockerServiceRunner.validateGitInstalled();
})
.then(function validateGitInstalledThen() {
console.log('resolving repository..');
return _this.resolveGitRepository(options);
})
.then(function resolveGitRepositoryThen() {
console.log('build image..');
return _this.dockerBuild(options);
})
.then(function dockerBuildThen() {
console.log('running container..');
return _this.dockerRunContainer(options);
})
.then(function dockerRunMainThen() {
var message = 'Service started as a docker container listening on port: ' + options.port;
console.log(message);
resolve({message: message});
})
.catch(function catchResolver(e) {
console.log(e.message);
reject({message: e.message, err: e});
});
}
});
};
DockerServiceRunner.prototype.stop = function stop() {
var _this = this, i = 0, promises = [];
return new Promise(function stopPromise(resolve, reject) {
for (i = 0; i < _dockerContainers.length; i++) {
promises.push(_this.stopSingleContainer(i));
}
Promise.all(promises).then(function killAllContainersThen() {
resolve();
}).catch(function killAllContainersCatcher(e) {
reject({
message: 'Could not kill all running containers, please kill manually using docker ps',
err: e
});
});
});
};
DockerServiceRunner.prototype.stopSingleContainer = function stopSingleContainer(index) {
return new Promise(function stopSingleContainerPromise(resolve, reject) {
if (index in _dockerContainers) {
console.log('Stopping container of service ' + _dockerContainers[index].name + '..');
exec('docker kill ' + _dockerContainers[index].ref).then(function dockerKillContainerThen() {
console.log('Container of service ' + _dockerContainers[index].name + ' stopped successfully!');
resolve();
}).catch(function dockerKillContainerCatcher(e) {
reject(e);
});
}
});
};
DockerServiceRunner.prototype.dockerRunContainer = function dockerRunContainer(options) {
var _this = this, port = options.port;
return new Promise(function dockerRunContainerPromise(resolve, reject) {
exec('docker run -d -p ' + port + ':' + port + ' -e "port=' + port + '" ' + options.name)
.then(function dockerRunContainerThen(result) {
console.log('docker run output to stdout:');
console.log(result.stdout);
if (result.stdout.length > 0) {
_dockerContainers.push({
port: options.port,
ref: _.trim(result.stdout),
name: options.name
});
_this.dockerRunPollNodeProcessUp(options).then(function () {
resolve();
});
}
}).catch(function dockerRunContainerCatch(e) {
var message = 'Cannot start container of service ' + options.name + ' on port ' + options.port + ' error attached';
console.log(message);
if (e.stderr.indexOf('port is already allocated') !== -1) {
console.warn(chalk.yellow('NOTICE: port ' + options.port + ' already taken! Docker container won\'t run'));
resolve();
} else {
console.log(e);
reject({message: message, err: e});
}
});
});
};
DockerServiceRunner.prototype.dockerRunPollNodeProcessUp = function dockerRunPollNodeProcessUp(options, timeout) {
timeout = timeout || 5000;
var _this = this;
return new Promise(function dockerRunPollNodeProcessUpPromise(resolve, reject) {
exec('curl docker-host:' + options.port + '/status').then(function dockerImagesGrepThen(result) {
console.log('resolved');
console.log(result.stdout);
resolve();
}).catch(function (e) {
if (timeout >= 0) {
setTimeout(function () {
_this.dockerRunPollNodeProcessUp(options, timeout - 200).then(function () {
resolve();
});
}, 200);
} else {
reject('Timeout server not loading');
}
});
})
};
DockerServiceRunner.prototype.validateOptions = function validateOptions(options) {
if ('name' in options) {
if (options.name.toLowerCase() != options.name) {
console.log('options.name with ' + options.name + ' is not a valid name for this service , please use all lowercase characters! (example: ' + options.name.toLowerCase() + ')');
return false;
}
}
return true;
};
DockerServiceRunner.prototype.dockerBuild = function dockerBuild(options) {
var _this = this, targetDir = _this.getRepositoryPath(options);
// This method requires polling since the promise returned is fulfilled a lot before the image is actually
// ready for usage.
return exec('cd ' + targetDir + ' && docker build -t ' + options.name + ' .')
.catch(function dockerBuildCatcher(e) {
throw({
message: 'Cannot generate Docker image for service ' + options.name + '\n' + 'attached is the error in full:' + '\n',
err: e
});
});
};
DockerServiceRunner.prototype.getRepositoryPath = function getRepositoryPath(options) {
return _dockerRepositoriesRootFolder + '/' + _.trim(options.name, '/');
};
DockerServiceRunner.prototype.resolveGitRepository = function resolveGitRepository(options) {
var _this = this, targetDir = _this.getRepositoryPath(options);
// If git repository directory exists, only pull otherwise clone.
return (DockerServiceRunner.directoryExists(targetDir)) ? exec('cd ' + targetDir + ' && git reset --hard && git pull') : _this.cloneGitRepository(options);
};
DockerServiceRunner.prototype.cloneGitRepository = function cloneGitRepository(options) {
var _this = this, targetDir = _this.getRepositoryPath(options);
console.log('cloning repository..');
return exec('git clone ' + options.git + ' ' + targetDir);
};
DockerServiceRunner.directoryExists = function directoryExists(dirPath) {
try {
// Query the entry
var stats = fs.lstatSync(dirPath);
// Is it a directory?
if (stats.isDirectory()) {
// Yes it is, nothing more to do here , we finished our validation
return true;
}
} catch (e) {
// Directory doesn't exist
}
return false;
};
DockerServiceRunner.validateGitInstalled = function validateGitInstalled() {
exec('git').then(function gitThen(result) {
return Promise.resolve({message: 'All good! carry on!', stdout: result.stdout});
}).catch((err) => {
return Promise.reject({
message: 'You don\'t have git installed! please run (Linux: apt-get install git / Mac: brew install git)',
error: err
});
});
};
DockerServiceRunner.validateRunningInDockerTerminal = function validateRunningInDockerTerminal() {
return new Promise(function (resolve, reject) {
exec('docker ps').then(function dockerProcessesThen() {
resolve();
}).catch(function dockerTerminalCatch(e) {
reject({message: 'You are not running in a Docker terminal!', err: e});
});
});
};
DockerServiceRunner.validateDockerRootFolderExists = function validateDockerRootFolderExists() {
console.log('validating root docker directory exists');
var existFlag = DockerServiceRunner.directoryExists(_dockerRepositoriesRootFolder);
if (!existFlag) {
// Create the root directory
return exec('mkdir -p ' + _dockerRepositoriesRootFolder);
}
return Promise.resolve({message: 'Directory already exists, were all good!'});
};
return DockerServiceRunner;
})(_);