UNPKG

13.6 kBJavaScriptView Raw
1
2var cst = require('../../constants.js');
3var Common = require('../Common.js');
4var fs = require('fs');
5var eachSeries = require('async/eachSeries');
6var child = require('child_process');
7
8var printError = Common.printError;
9var printOut = Common.printOut;
10
11module.exports = function(CLI) {
12
13 var EXEC_TIMEOUT = 60000; // Default: 1 min
14
15 CLI.prototype._pull = function(opts, cb) {
16 var that = this;
17
18 var process_name = opts.process_name;
19 var reload_type = opts.action;
20
21 printOut(cst.PREFIX_MSG + 'Updating repository for process name %s', process_name);
22
23 that.Client.getProcessByNameOrId(process_name, function (err, processes) {
24
25 if (err || processes.length === 0) {
26 printError('No processes with this name or id : %s', process_name);
27 return cb ? cb({msg: 'Process not found: ' + process_name}) : that.exitCli(cst.ERROR_EXIT);
28 }
29
30 var proc = processes[0];
31 if (!proc.pm2_env.versioning) {
32 printOut(cst.PREFIX_MSG + 'No versioning system found for process %s', process_name);
33 return cb ? cb({success:false, msg: 'No versioning system found for process'}) : that.exitCli(cst.SUCCESS_EXIT);
34 }
35 require('vizion').update({
36 folder: proc.pm2_env.versioning.repo_path
37 }, function(err, meta) {
38 if (err !== null) {
39 return cb ? cb({msg:err}) : that.exitCli(cst.ERROR_EXIT);
40 }
41
42 if (meta.success === true) {
43 getPostUpdateCmds(proc.pm2_env.versioning.repo_path, process_name, function (command_list) {
44 execCommands(proc.pm2_env.versioning.repo_path, command_list, function(err, res) {
45 if (err !== null) {
46 printError(err);
47 return cb ? cb({msg: meta.output + err}) : that.exitCli(cst.ERROR_EXIT);
48 }
49 else {
50 printOut(cst.PREFIX_MSG + 'Process successfully updated %s', process_name);
51 printOut(cst.PREFIX_MSG + 'Current commit %s', meta.current_revision);
52 return that[reload_type](process_name, function(err, procs) {
53 if (err && cb) return cb(err);
54 if (err) console.error(err);
55 return cb ? cb(null, meta.output + res) : that.exitCli(cst.SUCCESS_EXIT);
56 });
57 }
58 });
59 });
60 }
61 else {
62 printOut(cst.PREFIX_MSG + 'Already up-to-date or an error occured for app: %s', process_name);
63 return cb ? cb({success:false, msg : 'Already up to date'}) : that.exitCli(cst.SUCCESS_EXIT);
64 }
65 return false;
66 });
67 return false;
68 });
69 };
70
71 /**
72 * CLI method for updating a repository to a specific commit id
73 * @method pullCommitId
74 * @param {string} process_name
75 * @param {string} commit_id
76 * @return
77 */
78 CLI.prototype.pullCommitId = function(process_name, commit_id, cb) {
79 var reload_type = 'reload';
80 var that = this;
81
82 printOut(cst.PREFIX_MSG + 'Updating repository for process name %s', process_name);
83
84 that.Client.getProcessByNameOrId(process_name, function (err, processes) {
85
86 if (err || processes.length === 0) {
87 printError('No processes with this name or id : %s', process_name);
88 return cb ? cb({msg: 'Process not found: ' + process_name}) : that.exitCli(cst.ERROR_EXIT);
89 }
90
91 var proc = processes[0];
92 if (proc.pm2_env.versioning) {
93 require('vizion').isUpToDate({folder: proc.pm2_env.versioning.repo_path}, function(err, meta) {
94 if (err !== null)
95 return cb ? cb({msg:err}) : that.exitCli(cst.ERROR_EXIT);
96 require('vizion').revertTo(
97 {revision: commit_id,
98 folder: proc.pm2_env.versioning.repo_path},
99 function(err2, meta2) {
100 if (!err2 && meta2.success) {
101 getPostUpdateCmds(proc.pm2_env.versioning.repo_path, process_name, function (command_list) {
102 execCommands(proc.pm2_env.versioning.repo_path, command_list, function(err, res) {
103 if (err !== null)
104 {
105 printError(err);
106 return cb ? cb({msg:err}) : that.exitCli(cst.ERROR_EXIT);
107 }
108 else {
109 printOut(cst.PREFIX_MSG + 'Process successfully updated %s', process_name);
110 printOut(cst.PREFIX_MSG + 'Current commit %s', commit_id);
111 return that[reload_type](process_name, cb);
112 }
113 });
114 });
115 }
116 else {
117 printOut(cst.PREFIX_MSG + 'Already up-to-date or an error occured: %s', process_name);
118 return cb ? cb(null, {success:meta.success}) : that.exitCli(cst.SUCCESS_EXIT);
119 }
120 });
121 });
122 }
123 else {
124 printOut(cst.PREFIX_MSG + 'No versioning system found for process %s', process_name);
125 return cb ? cb(null, {success:false}) : that.exitCli(cst.SUCCESS_EXIT);
126 }
127 });
128 };
129
130 /**
131 * CLI method for downgrading a repository to the previous commit (older)
132 * @method backward
133 * @param {string} process_name
134 * @return
135 */
136 CLI.prototype.backward = function(process_name, cb) {
137 var that = this;
138 printOut(cst.PREFIX_MSG + 'Downgrading to previous commit repository for process name %s', process_name);
139
140 that.Client.getProcessByNameOrId(process_name, function (err, processes) {
141
142 if (err || processes.length === 0) {
143 printError('No processes with this name or id : %s', process_name);
144 return cb ? cb({msg: 'Process not found: ' + process_name}) : that.exitCli(cst.ERROR_EXIT);
145 }
146
147 var proc = processes[0];
148 // in case user searched by id/pid
149 process_name = proc.name;
150
151 if (proc.pm2_env.versioning === undefined ||
152 proc.pm2_env.versioning === null)
153 return cb({msg : 'Versioning unknown'});
154
155 require('vizion').prev({
156 folder: proc.pm2_env.versioning.repo_path
157 }, function(err, meta) {
158 if (err)
159 return cb ? cb({msg:err, data : meta}) : that.exitCli(cst.ERROR_EXIT);
160
161 if (meta.success !== true) {
162 printOut(cst.PREFIX_MSG + 'No versioning system found for process %s', process_name);
163 return cb ? cb({msg:err, data : meta}) : that.exitCli(cst.ERROR_EXIT);
164 }
165
166 getPostUpdateCmds(proc.pm2_env.versioning.repo_path, process_name, function (command_list) {
167 execCommands(proc.pm2_env.versioning.repo_path, command_list, function(err, res) {
168 if (err !== null) {
169 require('vizion').next({folder: proc.pm2_env.versioning.repo_path}, function(err2, meta2) {
170 printError(err);
171 return cb ? cb({msg: meta.output + err}) : that.exitCli(cst.ERROR_EXIT);
172 });
173 return false;
174 }
175
176 printOut(cst.PREFIX_MSG + 'Process successfully updated %s', process_name);
177 printOut(cst.PREFIX_MSG + 'Current commit %s', meta.current_revision);
178 that.reload(process_name, function(err, procs) {
179 if (err) return cb(err);
180 return cb ? cb(null, meta.output + res) : that.exitCli(cst.SUCCESS_EXIT);
181 });
182 });
183 });
184 });
185 });
186 };
187
188 /**
189 * CLI method for updating a repository to the next commit (more recent)
190 * @method forward
191 * @param {string} process_name
192 * @return
193 */
194 CLI.prototype.forward = function(process_name, cb) {
195 var that = this;
196 printOut(cst.PREFIX_MSG + 'Updating to next commit repository for process name %s', process_name);
197
198 that.Client.getProcessByNameOrId(process_name, function (err, processes) {
199
200 if (err || processes.length === 0) {
201 printError('No processes with this name or id: %s', process_name);
202 return cb ? cb({msg: 'Process not found: ' + process_name}) : that.exitCli(cst.ERROR_EXIT);
203 }
204
205 var proc = processes[0];
206 // in case user searched by id/pid
207 process_name = proc.name;
208 if (proc.pm2_env.versioning) {
209 require('vizion').next({folder: proc.pm2_env.versioning.repo_path}, function(err, meta) {
210 if (err !== null)
211 return cb ? cb({msg:err}) : that.exitCli(cst.ERROR_EXIT);
212 if (meta.success === true) {
213 getPostUpdateCmds(proc.pm2_env.versioning.repo_path, process_name, function (command_list) {
214 execCommands(proc.pm2_env.versioning.repo_path, command_list, function(err, res) {
215 if (err !== null)
216 {
217 require('vizion').prev({folder: proc.pm2_env.versioning.repo_path}, function(err2, meta2) {
218 printError(err);
219 return cb ? cb({msg:meta.output + err}) : that.exitCli(cst.ERROR_EXIT);
220 });
221 }
222 else {
223 printOut(cst.PREFIX_MSG + 'Process successfully updated %s', process_name);
224 printOut(cst.PREFIX_MSG + 'Current commit %s', meta.current_revision);
225 that.reload(process_name, function(err, procs) {
226 if (err) return cb(err);
227 return cb ? cb(null, meta.output + res) : that.exitCli(cst.SUCCESS_EXIT);
228 });
229 }
230 });
231 });
232 }
233 else {
234 printOut(cst.PREFIX_MSG + 'Already up-to-date or an error occured: %s', process_name);
235 return cb ? cb(null, {success:meta.success}) : that.exitCli(cst.SUCCESS_EXIT);
236 }
237 });
238 }
239 else {
240 printOut(cst.PREFIX_MSG + 'No versioning system found for process %s', process_name);
241 return cb ? cb({success:false, msg: 'No versioning system found'}) : that.exitCli(cst.SUCCESS_EXIT);
242 }
243 });
244 };
245
246 var exec = function (cmd, callback) {
247 var output = '';
248
249 var c = child.exec(cmd, {
250 env: process.env,
251 maxBuffer: 3*1024*1024,
252 timeout: EXEC_TIMEOUT
253 }, function(err) {
254 if (callback)
255 callback(err ? err.code : 0, output);
256 });
257
258 c.stdout.on('data', function(data) {
259 output += data;
260 });
261
262 c.stderr.on('data', function(data) {
263 output += data;
264 });
265 };
266
267 /**
268 *
269 * @method execCommands
270 * @param {string} repo_path
271 * @param {object} command_list
272 * @return
273 */
274 var execCommands = function(repo_path, command_list, cb) {
275 var stdout = '';
276
277 eachSeries(command_list, function(command, callback) {
278 stdout += '\n' + command;
279 exec('cd '+repo_path+';'+command,
280 function(code, output) {
281 stdout += '\n' + output;
282 if (code === 0)
283 callback();
284 else
285 callback('`'+command+'` failed');
286 });
287 }, function(err) {
288 if (err)
289 return cb(stdout + '\n' + err);
290 return cb(null, stdout);
291 });
292 }
293
294 /**
295 * Description Search process.json for post-update commands
296 * @method getPostUpdateCmds
297 * @param {string} repo_path
298 * @param {string} proc_name
299 * @return
300 */
301 var getPostUpdateCmds = function(repo_path, proc_name, cb) {
302 if (typeof repo_path !== 'string')
303 return cb([]);
304 if (repo_path[repo_path.length - 1] !== '/')
305 repo_path += '/';
306
307 var searchForCommands = function(file, callback) {
308 fs.exists(repo_path+file, function(exists) {
309 if (exists) {
310 try {
311 var conf_string = fs.readFileSync(repo_path + file);
312 var data = Common.parseConfig(conf_string, repo_path + file);
313 } catch (e) {
314 console.error(e.message || e);
315 }
316
317 if (data && data.apps) {
318 eachSeries(data.apps, function(item, callb) {
319 if (item.name && item.name === proc_name) {
320 if (item.post_update && typeof(item.post_update) === 'object') {
321 if (item.exec_timeout)
322 EXEC_TIMEOUT = parseInt(item.exec_timeout);
323 return callb(item.post_update);
324 }
325 else {
326 return callb();
327 }
328 }
329 else
330 return callb();
331 }, function(final) {
332 return callback(final);
333 });
334 }
335 else {
336 return callback();
337 }
338 }
339 else {
340 return callback();
341 }
342 });
343 };
344
345 eachSeries(['ecosystem.json', 'process.json', 'package.json'], searchForCommands,
346 function(final) {
347 return cb(final ? final : []);
348 });
349 };
350
351
352 /**
353 * CLI method for updating a repository
354 * @method pullAndRestart
355 * @param {string} process_name name of processes to pull
356 * @return
357 */
358 CLI.prototype.pullAndRestart = function (process_name, cb) {
359 this._pull({process_name: process_name, action: 'reload'}, cb);
360 };
361
362 /**
363 * CLI method for updating a repository
364 * @method pullAndReload
365 * @param {string} process_name name of processes to pull
366 * @return
367 */
368 CLI.prototype.pullAndReload = function (process_name, cb) {
369 this._pull({process_name: process_name, action: 'reload'}, cb);
370 };
371
372 /**
373 * CLI method for updating a repository to a specific commit id
374 * @method pullCommitId
375 * @param {object} opts
376 * @return
377 */
378 CLI.prototype._pullCommitId = function (opts, cb) {
379 this.pullCommitId(opts.pm2_name, opts.commit_id, cb);
380 };
381
382}