@zappinginc/zm2 6.0.14

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.
Files changed (133) hide show
  1. package/.claude/settings.local.json +8 -0
  2. package/.gitattributes +4 -0
  3. package/.mocharc.js +14 -0
  4. package/CHANGELOG.md +2416 -0
  5. package/CLAUDE.md +84 -0
  6. package/CONTRIBUTING.md +124 -0
  7. package/GNU-AGPL-3.0.txt +665 -0
  8. package/LICENSE +1 -0
  9. package/README.md +248 -0
  10. package/bin/zm2 +3 -0
  11. package/bin/zm2-dev +3 -0
  12. package/bin/zm2-docker +3 -0
  13. package/bin/zm2-runtime +3 -0
  14. package/bin/zm2-windows +3 -0
  15. package/bin/zm2.ps1 +3 -0
  16. package/bun.lock +421 -0
  17. package/constants.js +114 -0
  18. package/index.js +13 -0
  19. package/lib/API/Configuration.js +212 -0
  20. package/lib/API/Containerizer.js +335 -0
  21. package/lib/API/Dashboard.js +459 -0
  22. package/lib/API/Deploy.js +117 -0
  23. package/lib/API/Extra.js +775 -0
  24. package/lib/API/ExtraMgmt/Docker.js +30 -0
  25. package/lib/API/Log.js +315 -0
  26. package/lib/API/LogManagement.js +371 -0
  27. package/lib/API/Modules/LOCAL.js +122 -0
  28. package/lib/API/Modules/Modularizer.js +148 -0
  29. package/lib/API/Modules/NPM.js +445 -0
  30. package/lib/API/Modules/TAR.js +362 -0
  31. package/lib/API/Modules/flagExt.js +46 -0
  32. package/lib/API/Modules/index.js +120 -0
  33. package/lib/API/Monit.js +247 -0
  34. package/lib/API/Serve.js +343 -0
  35. package/lib/API/Startup.js +629 -0
  36. package/lib/API/UX/helpers.js +213 -0
  37. package/lib/API/UX/index.js +9 -0
  38. package/lib/API/UX/pm2-describe.js +193 -0
  39. package/lib/API/UX/pm2-ls-minimal.js +31 -0
  40. package/lib/API/UX/pm2-ls.js +483 -0
  41. package/lib/API/Version.js +382 -0
  42. package/lib/API/interpreter.json +12 -0
  43. package/lib/API/pm2-plus/PM2IO.js +372 -0
  44. package/lib/API/pm2-plus/auth-strategies/CliAuth.js +288 -0
  45. package/lib/API/pm2-plus/auth-strategies/WebAuth.js +187 -0
  46. package/lib/API/pm2-plus/helpers.js +97 -0
  47. package/lib/API/pm2-plus/link.js +126 -0
  48. package/lib/API/pm2-plus/pres/motd +16 -0
  49. package/lib/API/pm2-plus/pres/motd.update +26 -0
  50. package/lib/API/pm2-plus/pres/welcome +28 -0
  51. package/lib/API/pm2-plus/process-selector.js +52 -0
  52. package/lib/API/schema.json +379 -0
  53. package/lib/API.js +1931 -0
  54. package/lib/Client.js +776 -0
  55. package/lib/Common.js +911 -0
  56. package/lib/Configuration.js +304 -0
  57. package/lib/Daemon.js +456 -0
  58. package/lib/Event.js +37 -0
  59. package/lib/God/ActionMethods.js +909 -0
  60. package/lib/God/ClusterMode.js +97 -0
  61. package/lib/God/ForkMode.js +297 -0
  62. package/lib/God/Methods.js +265 -0
  63. package/lib/God/Reload.js +240 -0
  64. package/lib/God.js +632 -0
  65. package/lib/HttpInterface.js +76 -0
  66. package/lib/ProcessContainer.js +305 -0
  67. package/lib/ProcessContainerBun.js +360 -0
  68. package/lib/ProcessContainerFork.js +42 -0
  69. package/lib/ProcessContainerForkBun.js +33 -0
  70. package/lib/ProcessUtils.js +55 -0
  71. package/lib/TreeKill.js +118 -0
  72. package/lib/Utility.js +430 -0
  73. package/lib/VersionCheck.js +46 -0
  74. package/lib/Watcher.js +117 -0
  75. package/lib/Worker.js +169 -0
  76. package/lib/binaries/CLI.js +1041 -0
  77. package/lib/binaries/DevCLI.js +183 -0
  78. package/lib/binaries/Runtime.js +101 -0
  79. package/lib/binaries/Runtime4Docker.js +192 -0
  80. package/lib/completion.js +229 -0
  81. package/lib/completion.sh +40 -0
  82. package/lib/motd +36 -0
  83. package/lib/templates/Dockerfiles/Dockerfile-java.tpl +7 -0
  84. package/lib/templates/Dockerfiles/Dockerfile-nodejs.tpl +8 -0
  85. package/lib/templates/Dockerfiles/Dockerfile-ruby.tpl +7 -0
  86. package/lib/templates/ecosystem-es.tpl +24 -0
  87. package/lib/templates/ecosystem-simple-es.tpl +8 -0
  88. package/lib/templates/ecosystem-simple.tpl +6 -0
  89. package/lib/templates/ecosystem.tpl +22 -0
  90. package/lib/templates/init-scripts/launchd.tpl +35 -0
  91. package/lib/templates/init-scripts/openrc.tpl +52 -0
  92. package/lib/templates/init-scripts/pm2-init-amazon.sh +86 -0
  93. package/lib/templates/init-scripts/rcd-openbsd.tpl +41 -0
  94. package/lib/templates/init-scripts/rcd.tpl +44 -0
  95. package/lib/templates/init-scripts/smf.tpl +43 -0
  96. package/lib/templates/init-scripts/systemd-online.tpl +22 -0
  97. package/lib/templates/init-scripts/systemd.tpl +22 -0
  98. package/lib/templates/init-scripts/upstart.tpl +103 -0
  99. package/lib/templates/logrotate.d/pm2 +10 -0
  100. package/lib/templates/sample-apps/http-server/README.md +14 -0
  101. package/lib/templates/sample-apps/http-server/api.js +9 -0
  102. package/lib/templates/sample-apps/http-server/ecosystem.config.js +14 -0
  103. package/lib/templates/sample-apps/http-server/package.json +11 -0
  104. package/lib/templates/sample-apps/pm2-plus-metrics-actions/README.md +45 -0
  105. package/lib/templates/sample-apps/pm2-plus-metrics-actions/custom-metrics.js +66 -0
  106. package/lib/templates/sample-apps/pm2-plus-metrics-actions/ecosystem.config.js +12 -0
  107. package/lib/templates/sample-apps/pm2-plus-metrics-actions/package.json +11 -0
  108. package/lib/templates/sample-apps/python-app/README.md +4 -0
  109. package/lib/templates/sample-apps/python-app/echo.py +7 -0
  110. package/lib/templates/sample-apps/python-app/ecosystem.config.js +12 -0
  111. package/lib/templates/sample-apps/python-app/package.json +11 -0
  112. package/lib/tools/Config.js +248 -0
  113. package/lib/tools/IsAbsolute.js +20 -0
  114. package/lib/tools/copydirSync.js +101 -0
  115. package/lib/tools/deleteFolderRecursive.js +19 -0
  116. package/lib/tools/find-package-json.js +74 -0
  117. package/lib/tools/fmt.js +72 -0
  118. package/lib/tools/isbinaryfile.js +94 -0
  119. package/lib/tools/json5.js +752 -0
  120. package/lib/tools/open.js +63 -0
  121. package/lib/tools/passwd.js +58 -0
  122. package/lib/tools/promise.min.js +1 -0
  123. package/lib/tools/sexec.js +55 -0
  124. package/lib/tools/treeify.js +113 -0
  125. package/lib/tools/which.js +120 -0
  126. package/lib/tools/xdg-open +861 -0
  127. package/package.json +219 -0
  128. package/paths.js +93 -0
  129. package/pm2 +11 -0
  130. package/preinstall.js +24 -0
  131. package/run.sh +9 -0
  132. package/types/index.d.ts +722 -0
  133. package/types/tsconfig.json +14 -0
@@ -0,0 +1,212 @@
1
+
2
+ var Common = require('../Common.js');
3
+ var cst = require('../../constants.js');
4
+ var UX = require('./UX');
5
+ var chalk = require('ansis');
6
+ var Configuration = require('../Configuration.js');
7
+
8
+ module.exports = function(CLI) {
9
+
10
+ CLI.prototype.get = function(key, cb) {
11
+ var that = this;
12
+
13
+ if (!key || key == 'all') {
14
+ displayConf(function(err, data) {
15
+ if (err)
16
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
17
+ return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
18
+ });
19
+ return false;
20
+ }
21
+ Configuration.get(key, function(err, data) {
22
+ if (err) {
23
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
24
+ }
25
+ // pm2 conf module-name
26
+ if (key.indexOf(':') === -1 && key.indexOf('.') === -1) {
27
+ displayConf(key, function() {
28
+ console.log('Modules configuration. Copy/Paste line to edit values.')
29
+ return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT)
30
+ });
31
+ return false;
32
+ }
33
+ // pm2 conf module-name:key
34
+ var module_name, key_name;
35
+
36
+ if (key.indexOf(':') > -1) {
37
+ module_name = key.split(':')[0];
38
+ key_name = key.split(':')[1];
39
+ } else if (key.indexOf('.') > -1) {
40
+ module_name = key.split('.')[0];
41
+ key_name = key.split('.')[1];
42
+ }
43
+
44
+ Common.printOut('Value for module ' + chalk.blue(module_name), 'key ' + chalk.blue(key_name) + ': ' + chalk.bold.green(data));
45
+
46
+
47
+ return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
48
+ });
49
+ };
50
+
51
+ CLI.prototype.set = function(key, value, cb) {
52
+ var that = this;
53
+
54
+ if (!key) {
55
+ interactiveConfigEdit(function(err) {
56
+ if (err)
57
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
58
+ return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
59
+ });
60
+ return false;
61
+ }
62
+
63
+ /**
64
+ * Set value
65
+ */
66
+ Configuration.set(key, value, function(err) {
67
+ if (err)
68
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
69
+
70
+ var values = [];
71
+
72
+ if (key.indexOf('.') > -1)
73
+ values = key.split('.');
74
+
75
+ if (key.indexOf(':') > -1)
76
+ values = key.split(':');
77
+
78
+ if (values && values.length > 1) {
79
+ // The first element is the app name (module_conf.json)
80
+ var app_name = values[0];
81
+
82
+ process.env.PM2_PROGRAMMATIC = 'true';
83
+ that.restart(app_name, {
84
+ updateEnv : true
85
+ }, function(err, data) {
86
+ process.env.PM2_PROGRAMMATIC = 'false';
87
+ if (!err)
88
+ Common.printOut(cst.PREFIX_MSG + 'Module %s restarted', app_name);
89
+ Common.log('Setting changed')
90
+ displayConf(app_name, function() {
91
+ return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
92
+ });
93
+ });
94
+ return false;
95
+ }
96
+ displayConf(null, function() {
97
+ return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
98
+ });
99
+ });
100
+ };
101
+
102
+ CLI.prototype.multiset = function(serial, cb) {
103
+ var that = this;
104
+
105
+ Configuration.multiset(serial, function(err, data) {
106
+ if (err)
107
+ return cb ? cb({success:false, err:err}) : that.exitCli(cst.ERROR_EXIT);
108
+
109
+ var values = [];
110
+ var key = serial.match(/(?:[^ "]+|"[^"]*")+/g)[0];
111
+
112
+ if (key.indexOf('.') > -1)
113
+ values = key.split('.');
114
+
115
+ if (key.indexOf(':') > -1)
116
+ values = key.split(':');
117
+
118
+ if (values && values.length > 1) {
119
+ // The first element is the app name (module_conf.json)
120
+ var app_name = values[0];
121
+
122
+ process.env.PM2_PROGRAMMATIC = 'true';
123
+ that.restart(app_name, {
124
+ updateEnv : true
125
+ }, function(err, data) {
126
+ process.env.PM2_PROGRAMMATIC = 'false';
127
+ if (!err)
128
+ Common.printOut(cst.PREFIX_MSG + 'Module %s restarted', app_name);
129
+ displayConf(app_name, function() {
130
+ return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT)
131
+ });
132
+ });
133
+ return false;
134
+ }
135
+ displayConf(app_name, function() {
136
+ return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT)
137
+ });
138
+ });
139
+ };
140
+
141
+ CLI.prototype.unset = function(key, cb) {
142
+ var that = this;
143
+
144
+ Configuration.unset(key, function(err) {
145
+ if (err) {
146
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
147
+ }
148
+
149
+ displayConf(function() { cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT) });
150
+ });
151
+ };
152
+
153
+ CLI.prototype.conf = function(key, value, cb) {
154
+ var that = this;
155
+
156
+ if (typeof(value) === 'function') {
157
+ cb = value;
158
+ value = null;
159
+ }
160
+
161
+ // If key + value = set
162
+ if (key && value) {
163
+ that.set(key, value, function(err) {
164
+ if (err)
165
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
166
+ return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
167
+ });
168
+ }
169
+ // If only key = get
170
+ else if (key) {
171
+ that.get(key, function(err, data) {
172
+ if (err)
173
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
174
+ return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
175
+ });
176
+ }
177
+ else {
178
+ interactiveConfigEdit(function(err) {
179
+ if (err)
180
+ return cb ? cb(Common.retErr(err)) : that.exitCli(cst.ERROR_EXIT);
181
+ return cb ? cb(null, {success:true}) : that.exitCli(cst.SUCCESS_EXIT);
182
+ });
183
+ }
184
+ };
185
+
186
+ };
187
+
188
+ function interactiveConfigEdit(cb) {
189
+ UX.helpers.openEditor(cst.PM2_MODULE_CONF_FILE, function(err, data) {
190
+ Common.printOut(chalk.bold('Module configuration (%s) edited.'), cst.PM2_MODULE_CONF_FILE);
191
+ Common.printOut(chalk.bold('To take changes into account, please restart module related.'), cst.PM2_MODULE_CONF_FILE);
192
+ if (err)
193
+ return cb(Common.retErr(err));
194
+ return cb(null, {success:true});
195
+ });
196
+
197
+ }
198
+
199
+ /**
200
+ * Configuration
201
+ */
202
+ function displayConf(target_app, cb) {
203
+ if (typeof(target_app) == 'function') {
204
+ cb = target_app;
205
+ target_app = null;
206
+ }
207
+
208
+ Configuration.getAll(function(err, data) {
209
+ UX.helpers.dispKeys(data, target_app);
210
+ return cb();
211
+ });
212
+ }
@@ -0,0 +1,335 @@
1
+
2
+ var spawn = require('child_process').spawn;
3
+ var exec = require('child_process').exec;
4
+ var chalk = require('ansis');
5
+ var util = require('util');
6
+ var fmt = require('../tools/fmt.js');
7
+ var fs = require('fs');
8
+ var path = require('path');
9
+ var cst = require('../../constants.js');
10
+ var Promise = require('../tools/promise.min.js');
11
+
12
+ function pspawn(cmd) {
13
+ return new Promise(function(resolve, reject) {
14
+ var p_cmd = cmd.split(' ');
15
+
16
+ var install_instance = spawn(p_cmd[0], p_cmd.splice(1, cmd.length), {
17
+ stdio : 'inherit',
18
+ env : process.env,
19
+ shell : true
20
+ });
21
+
22
+ install_instance.on('close', function(code) {
23
+ if (code != 0) {
24
+ console.log(chalk.bold.red('Command failed'));
25
+ return reject(new Error('Bad cmd return'));
26
+ }
27
+ return resolve();
28
+ });
29
+
30
+ install_instance.on('error', function (err) {
31
+ return reject(err);
32
+ });
33
+ });
34
+ }
35
+
36
+ function checkDockerSetup() {
37
+ return new Promise(function(resolve, reject) {
38
+ exec("docker version -f '{{.Client.Version}}'", function(err, stdout, stderr) {
39
+ if (err) {
40
+ console.error(chalk.red.bold('[Docker access] Error while trying to use docker command'));
41
+ if (err.message && err.message.indexOf('Cannot connect to the Docker') > -1) {
42
+ console.log();
43
+ console.log(chalk.blue.bold('[Solution] Setup Docker to be able to be used without sudo rights:'));
44
+ console.log(chalk.bold('$ sudo groupadd docker'));
45
+ console.log(chalk.bold('$ sudo usermod -aG docker $USER'));
46
+ console.log(chalk.bold('Then LOGOUT and LOGIN your Linux session'));
47
+ console.log('Read more: http://bit.ly/29JGdCE');
48
+ }
49
+ return reject(err);
50
+ }
51
+ return resolve();
52
+ });
53
+ });
54
+ }
55
+
56
+ /**
57
+ * Switch Dockerfile mode
58
+ * check test/programmatic/containerizer.mocha.js
59
+ */
60
+ function parseAndSwitch(file_content, main_file, opts) {
61
+ var lines = file_content.split('\n');
62
+ var mode = opts.mode;
63
+
64
+ lines[0] = 'FROM keymetrics/pm2:' + opts.node_version;
65
+
66
+ for (var i = 0; i < lines.length; i++) {
67
+ var line = lines[i];
68
+
69
+ if (['## DISTRIBUTION MODE', '## DEVELOPMENT MODE'].indexOf(line) > -1 ||
70
+ i == lines.length - 1) {
71
+ lines.splice(i, lines.length);
72
+ lines[i] = '## ' + mode.toUpperCase() + ' MODE';
73
+ lines[i + 1] = 'ENV NODE_ENV=' + (mode == 'distribution' ? 'production' : mode);
74
+
75
+ if (mode == 'distribution') {
76
+ lines[i + 2] = 'COPY . /var/app';
77
+ lines[i + 3] = 'CMD ["pm2-docker", "' + main_file + '", "--env", "production"]';
78
+ }
79
+ if (mode == 'development') {
80
+ lines[i + 2] = 'CMD ["pm2-dev", "' + main_file + '", "--env", "development"]';
81
+ }
82
+ break;
83
+ }
84
+ };
85
+ lines = lines.join('\n');
86
+ return lines;
87
+ };
88
+
89
+ /**
90
+ * Replace ENV, COPY and CMD depending on the mode
91
+ * @param {String} docker_filepath Dockerfile absolute path
92
+ * @param {String} main_file Main file to start in container
93
+ * @param {String} mode Mode to switch the Dockerfile
94
+ */
95
+ function switchDockerFile(docker_filepath, main_file, opts) {
96
+ return new Promise(function(resolve, reject) {
97
+ var data = fs.readFileSync(docker_filepath, 'utf8').toString();
98
+
99
+ if (['distribution', 'development'].indexOf(opts.mode) == -1)
100
+ return reject(new Error('Unknown mode'));
101
+
102
+ var lines = parseAndSwitch(data, main_file, opts)
103
+ fs.writeFile(docker_filepath, lines, function(err) {
104
+ if (err) return reject(err);
105
+ resolve({
106
+ Dockerfile_path : docker_filepath,
107
+ Dockerfile : lines,
108
+ CMD : ''
109
+ });
110
+ })
111
+ });
112
+ }
113
+
114
+ /**
115
+ * Generate sample Dockerfile (lib/templates/Dockerfiles)
116
+ * @param {String} docker_filepath Dockerfile absolute path
117
+ * @param {String} main_file Main file to start in container
118
+ * @param {String} mode Mode to switch the Dockerfile
119
+ */
120
+ function generateDockerfile(docker_filepath, main_file, opts) {
121
+ return new Promise(function(resolve, reject) {
122
+ var tpl_file = path.join(cst.TEMPLATE_FOLDER, cst.DOCKERFILE_NODEJS);
123
+ var template = fs.readFileSync(tpl_file, {encoding: 'utf8'});
124
+ var CMD;
125
+
126
+ template = parseAndSwitch(template, main_file, opts);
127
+
128
+ fs.writeFile(docker_filepath, template, function(err) {
129
+ if (err) return reject(err);
130
+ resolve({
131
+ Dockerfile_path : docker_filepath,
132
+ Dockerfile : template,
133
+ CMD : CMD
134
+ });
135
+ });
136
+ });
137
+ }
138
+
139
+ function handleExit(CLI, opts, mode) {
140
+ process.on('SIGINT', function() {
141
+ CLI.disconnect();
142
+
143
+ if (mode != 'distribution')
144
+ return false;
145
+
146
+ exec('docker ps -lq', function(err, stdout, stderr) {
147
+ if (err) {
148
+ console.error(err);
149
+ }
150
+ require('vizion').analyze({folder : process.cwd()}, function recur_path(err, meta){
151
+ if (!err && meta.revision) {
152
+ var commit_id = util.format('#%s(%s) %s',
153
+ meta.branch,
154
+ meta.revision.slice(0, 5),
155
+ meta.comment);
156
+
157
+ console.log(chalk.bold.magenta('$ docker commit -m "%s" %s %s'),
158
+ commit_id,
159
+ stdout.replace('\n', ''),
160
+ opts.imageName);
161
+ }
162
+ else
163
+ console.log(chalk.bold.magenta('$ docker commit %s %s'), stdout.replace('\n', ''), opts.imageName);
164
+
165
+ console.log(chalk.bold.magenta('$ docker push %s'), opts.imageName);
166
+ });
167
+ });
168
+ });
169
+ }
170
+
171
+ module.exports = function(CLI) {
172
+ CLI.prototype.generateDockerfile = function(script, opts) {
173
+ var docker_filepath = path.join(process.cwd(), 'Dockerfile');
174
+ var that = this;
175
+
176
+ fs.stat(docker_filepath, function(err, stat) {
177
+ if (err || opts.force == true) {
178
+ generateDockerfile(docker_filepath, script, {
179
+ mode : 'development'
180
+ })
181
+ .then(function() {
182
+ console.log(chalk.bold('New Dockerfile generated in current folder'));
183
+ console.log(chalk.bold('You can now run\n$ pm2 docker:dev <file|config>'));
184
+ return that.exitCli(cst.SUCCESS_EXIT);
185
+ });
186
+ return false;
187
+ }
188
+ console.log(chalk.red.bold('Dockerfile already exists in this folder, use --force if you want to replace it'));
189
+ that.exitCli(cst.ERROR_EXIT);
190
+ });
191
+ };
192
+
193
+ CLI.prototype.dockerMode = function(script, opts, mode) {
194
+ var promptly = require('promptly');
195
+ var self = this;
196
+ handleExit(self, opts, mode);
197
+
198
+ if (mode == 'distribution' && !opts.imageName) {
199
+ console.error(chalk.bold.red('--image-name [name] option is missing'));
200
+ return self.exitCli(cst.ERROR_EXIT);
201
+ }
202
+
203
+ var template;
204
+ var app_path, main_script;
205
+ var image_name;
206
+ var node_version = opts.nodeVersion ? opts.nodeVersion.split('.')[0] : 'latest';
207
+
208
+ image_name = opts.imageName || require('crypto').randomBytes(6).toString('hex');
209
+
210
+ if (script.indexOf('/') > -1) {
211
+ app_path = path.join(process.cwd(), path.dirname(script));
212
+ main_script = path.basename(script);
213
+ }
214
+ else {
215
+ app_path = process.cwd();
216
+ main_script = script;
217
+ }
218
+
219
+ checkDockerSetup()
220
+ .then(function() {
221
+ /////////////////////////
222
+ // Generate Dockerfile //
223
+ /////////////////////////
224
+ return new Promise(function(resolve, reject) {
225
+ var docker_filepath = path.join(process.cwd(), 'Dockerfile');
226
+
227
+ fs.stat(docker_filepath, function(err, stat) {
228
+ if (err) {
229
+ // Dockerfile does not exist, generate one
230
+ // console.log(chalk.blue.bold('Generating new Dockerfile'));
231
+ if (opts.force == true) {
232
+ return resolve(generateDockerfile(docker_filepath, main_script, {
233
+ node_version : node_version,
234
+ mode : mode
235
+ }));
236
+ }
237
+ if (opts.dockerdaemon)
238
+ return resolve(generateDockerfile(docker_filepath, main_script, {
239
+ node_version : node_version,
240
+ mode : mode
241
+ }));
242
+ promptly.prompt('No Dockerfile in current directory, ok to generate a new one? (y/n)', function(err, value) {
243
+ if (value == 'y')
244
+ return resolve(generateDockerfile(docker_filepath, main_script, {
245
+ node_version : node_version,
246
+ mode : mode
247
+ }));
248
+ else
249
+ return self.exitCli(cst.SUCCESS_EXIT);
250
+ });
251
+ return false;
252
+ }
253
+ return resolve(switchDockerFile(docker_filepath, main_script, {
254
+ node_version : node_version,
255
+ mode : mode
256
+ }));
257
+ });
258
+ });
259
+ })
260
+ .then(function(_template) {
261
+ template = _template;
262
+ return Promise.resolve();
263
+ })
264
+ .then(function() {
265
+ //////////////////
266
+ // Docker build //
267
+ //////////////////
268
+
269
+ var docker_build = util.format('docker build -t %s -f %s',
270
+ image_name,
271
+ template.Dockerfile_path);
272
+
273
+ if (opts.fresh == true)
274
+ docker_build += ' --no-cache';
275
+ docker_build += ' .';
276
+
277
+ console.log();
278
+ fmt.sep();
279
+ fmt.title('Building Boot System');
280
+ fmt.field('Type', chalk.cyan.bold('Docker'));
281
+ fmt.field('Mode', mode);
282
+ fmt.field('Image name', image_name);
283
+ fmt.field('Docker build command', docker_build);
284
+ fmt.field('Dockerfile path', template.Dockerfile_path);
285
+ fmt.sep();
286
+
287
+ return pspawn(docker_build);
288
+ })
289
+ .then(function() {
290
+ ////////////////
291
+ // Docker run //
292
+ ////////////////
293
+
294
+ var docker_run = 'docker run --net host';
295
+
296
+ if (opts.dockerdaemon == true)
297
+ docker_run += ' -d';
298
+ if (mode != 'distribution')
299
+ docker_run += util.format(' -v %s:/var/app -v /var/app/node_modules', app_path);
300
+ docker_run += ' ' + image_name;
301
+ var dockerfile_parsed = template.Dockerfile.split('\n');
302
+ var base_image = dockerfile_parsed[0];
303
+ var run_cmd = dockerfile_parsed[dockerfile_parsed.length - 1];
304
+
305
+ console.log();
306
+ fmt.sep();
307
+ fmt.title('Booting');
308
+ fmt.field('Type', chalk.cyan.bold('Docker'));
309
+ fmt.field('Mode', mode);
310
+ fmt.field('Base Image', base_image);
311
+ fmt.field('Image Name', image_name);
312
+ fmt.field('Docker Command', docker_run);
313
+ fmt.field('RUN Command', run_cmd);
314
+ fmt.field('CWD', app_path);
315
+ fmt.sep();
316
+ return pspawn(docker_run);
317
+ })
318
+ .then(function() {
319
+ console.log(chalk.blue.bold('>>> Leaving Docker instance uuid=%s'), image_name);
320
+ self.disconnect();
321
+ return Promise.resolve();
322
+ })
323
+ .catch(function(err) {
324
+ console.log();
325
+ console.log(chalk.gray('Raw error=', err.message));
326
+ self.disconnect();
327
+ });
328
+
329
+ };
330
+
331
+ };
332
+
333
+ module.exports.generateDockerfile = generateDockerfile;
334
+ module.exports.parseAndSwitch = parseAndSwitch;
335
+ module.exports.switchDockerFile = switchDockerFile;