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 | var fs = require('fs-extra');
|
34 | var path = require('path');
|
35 | var os = require('os');
|
36 | var module_exists = require('module-exists');
|
37 | var child_process = require('child_process');
|
38 | var qewd = require('../lib/master');
|
39 | var uuid = require('uuid/v4');
|
40 |
|
41 | function getDirectories(path) {
|
42 | return fs.readdirSync(path).filter(function(file) {
|
43 | return fs.statSync(path + '/' + file).isDirectory();
|
44 | });
|
45 | }
|
46 |
|
47 | function createModuleMap(cwd, config) {
|
48 | var qewdAppsPath = cwd + '/qewd-apps';
|
49 | if (fs.existsSync(qewdAppsPath)) {
|
50 | if (!config.moduleMap) {
|
51 | config.moduleMap = {};
|
52 | }
|
53 | var appList = getDirectories(qewdAppsPath);
|
54 | appList.forEach(function(appName) {
|
55 | var appPath = qewdAppsPath + '/' + appName;
|
56 | var indexPath = appPath + '/index.js';
|
57 | var handlerList = getDirectories(appPath);
|
58 |
|
59 |
|
60 | if (handlerList.length > 0) {
|
61 | var text;
|
62 |
|
63 | var reqPath = path.join(__dirname, 'qewdAppHandler');
|
64 | var appPath2 = path.normalize(appPath);
|
65 | if (os.platform() === 'win32') {
|
66 | reqPath = reqPath.split('\\').join('\\\\');
|
67 | appPath2 = appPath2.split('\\').join('\\\\');
|
68 | }
|
69 | text = "module.exports = require('" + reqPath + "')('" + appPath2 + "');"
|
70 | fs.writeFileSync(indexPath, text);
|
71 | }
|
72 | if (fs.existsSync(indexPath)) {
|
73 | config.moduleMap[appName] = appPath;
|
74 | }
|
75 | });
|
76 | }
|
77 | }
|
78 |
|
79 | function installModule(moduleName, modulePath) {
|
80 | var pieces = moduleName.split('@');
|
81 | var rootName;
|
82 | if (moduleName.startsWith('@')) {
|
83 | rootName = '@' + pieces[1];
|
84 | }
|
85 | else {
|
86 | rootName = pieces[0];
|
87 | }
|
88 | if (!module_exists(rootName) && !fs.existsSync(modulePath + '/node_modules/' + rootName)) {
|
89 | var prefix = '';
|
90 | if (typeof modulePath !== 'undefined') {
|
91 | prefix = ' --prefix ' + modulePath;
|
92 | }
|
93 | child_process.execSync('npm install --unsafe-perm ' + moduleName + prefix, {stdio:[0,1,2]});
|
94 | console.log('\n' + moduleName + ' installed');
|
95 | }
|
96 | else {
|
97 | console.log(moduleName + ' already installed');
|
98 | }
|
99 | }
|
100 |
|
101 | function installModules(cwd) {
|
102 | var npmModules;
|
103 | var modulePath;
|
104 | if (fs.existsSync(cwd + '/install_modules.json')) {
|
105 | if (!fs.existsSync(cwd + '/node_modules')) {
|
106 | fs.mkdirSync(cwd + '/node_modules');
|
107 | }
|
108 |
|
109 | process.env.NODE_PATH = cwd + '/node_modules:' + process.env.NODE_PATH;
|
110 | require('module').Module._initPaths();
|
111 |
|
112 | npmModules = require(cwd + '/install_modules.json');
|
113 | npmModules.forEach(function(moduleName) {
|
114 | console.log('\nInstalling module ' + moduleName + ' to ' + cwd);
|
115 | installModule(moduleName, cwd);
|
116 | });
|
117 | console.log('** NODE_PATH = ' + process.env.NODE_PATH);
|
118 | }
|
119 | }
|
120 |
|
121 | function linkMonitor(cwd, name) {
|
122 | if (name !== '') {
|
123 | name = '/' + name;
|
124 | var path1 = cwd + name;
|
125 | if (process.env.mode && process.env.microservice) {
|
126 | path1 = cwd;
|
127 | }
|
128 | if (!fs.existsSync(path1)) {
|
129 | fs.mkdirSync(path1);
|
130 | }
|
131 | }
|
132 | var webServerRootPath = cwd + name + '/www';
|
133 | if (process.env.mode && process.env.microservice) {
|
134 | webServerRootPath = cwd + '/www';
|
135 | }
|
136 | if (!fs.existsSync(webServerRootPath)) {
|
137 | fs.mkdirSync(webServerRootPath);
|
138 | }
|
139 | if (process.platform === 'win32') {
|
140 | fs.copySync(process.cwd() + '/node_modules/qewd-monitor/www', webServerRootPath + '/qewd-monitor');
|
141 | fs.copySync(process.cwd() + '/node_modules/ewd-client/lib/proto/ewd-client.js', webServerRootPath + '/ewd-client.js');
|
142 | let fromPath = process.cwd() + '/www/qewd-client.js';
|
143 | let toPath = webServerRootPath + '/qewd-client.js';
|
144 | if (!fs.existsSync(toPath) && fs.existsSync(fromPath)) {
|
145 | fs.copySync(fromPath, toPath);
|
146 | }
|
147 | fromPath = process.cwd() + '/www/mg-webComponents.js';
|
148 | toPath = webServerRootPath + '/mg-webComponents.js';
|
149 | if (!fs.existsSync(toPath) && fs.existsSync(fromPath)) {
|
150 | fs.copySync(fromPath, toPath);
|
151 | }
|
152 | fromPath = process.cwd() + '/www/components';
|
153 | toPath = webServerRootPath + '/components';
|
154 | if (!fs.existsSync(toPath) && fs.existsSync(fromPath)) {
|
155 | fs.copySync(fromPath, toPath);
|
156 | }
|
157 | fromPath = process.cwd() + '/www/qewd-monitor-adminui';
|
158 | toPath = webServerRootPath + '/qewd-monitor-adminui';
|
159 | if (!fs.existsSync(toPath) && fs.existsSync(fromPath)) {
|
160 | fs.copySync(fromPath, toPath);
|
161 | }
|
162 | }
|
163 | else {
|
164 |
|
165 | let samePath = (process.cwd() + '/www' === webServerRootPath);
|
166 |
|
167 | var cmd = 'ln -sf ' + process.cwd() + '/node_modules/qewd-monitor/www ' + webServerRootPath + '/qewd-monitor';
|
168 | child_process.execSync(cmd, {stdio:[0,1,2]});
|
169 |
|
170 | cmd = 'ln -sf ' + process.cwd() + '/node_modules/ewd-client/lib/proto/ewd-client.js ' + webServerRootPath + '/ewd-client.js';
|
171 | child_process.execSync(cmd, {stdio:[0,1,2]});
|
172 |
|
173 | if (!samePath) {
|
174 |
|
175 | if (fs.existsSync(process.cwd() + '/www/qewd-client.js')) {
|
176 | cmd = 'ln -sf ' + process.cwd() + '/www/qewd-client.js ' + webServerRootPath + '/qewd-client.js';
|
177 | child_process.execSync(cmd, {stdio:[0,1,2]});
|
178 | }
|
179 |
|
180 | if (fs.existsSync(process.cwd() + '/www/mg-webComponents.js')) {
|
181 | cmd = 'ln -sf ' + process.cwd() + '/www/mg-webComponents.js ' + webServerRootPath + '/mg-webComponents.js';
|
182 | child_process.execSync(cmd, {stdio:[0,1,2]});
|
183 |
|
184 | if (!fs.existsSync(webServerRootPath + '/components')) {
|
185 | fs.mkdirSync(webServerRootPath + '/components');
|
186 | }
|
187 |
|
188 | if (fs.existsSync(process.cwd() + '/www/components/adminui') && !fs.existsSync(webServerRootPath + '/components/adminui')) {
|
189 | fs.mkdirSync(webServerRootPath + '/components/adminui');
|
190 | cmd = 'cp -r ' + process.cwd() + '/www/components/adminui ' + webServerRootPath + '/components';
|
191 | child_process.execSync(cmd, {stdio:[0,1,2]});
|
192 | }
|
193 |
|
194 | if (fs.existsSync(process.cwd() + '/www/components/leaflet') && !fs.existsSync(webServerRootPath + '/components/leaflet')) {
|
195 | fs.mkdirSync(webServerRootPath + '/components/leaflet');
|
196 | cmd = 'cp -r ' + process.cwd() + '/www/components/leaflet ' + webServerRootPath + '/components';
|
197 | child_process.execSync(cmd, {stdio:[0,1,2]});
|
198 | }
|
199 |
|
200 | if (fs.existsSync(process.cwd() + '/www/components/d3') && !fs.existsSync(webServerRootPath + '/components/d3')) {
|
201 | fs.mkdirSync(webServerRootPath + '/components/d3');
|
202 | cmd = 'cp -r ' + process.cwd() + '/www/components/d3 ' + webServerRootPath + '/components';
|
203 | child_process.execSync(cmd, {stdio:[0,1,2]});
|
204 | }
|
205 |
|
206 | if (fs.existsSync(process.cwd() + '/www/qewd-monitor-adminui') && !fs.existsSync(webServerRootPath + '/qewd-monitor-adminui')) {
|
207 | fs.mkdirSync(webServerRootPath + '/qewd-monitor-adminui');
|
208 | cmd = 'cp -r ' + process.cwd() + '/www/qewd-monitor-adminui ' + webServerRootPath;
|
209 | child_process.execSync(cmd, {stdio:[0,1,2]});
|
210 | }
|
211 | }
|
212 | }
|
213 |
|
214 | if (!fs.existsSync(cwd + '/qewd-apps/qewd-monitor-adminui')) {
|
215 | fs.mkdirSync(cwd + '/qewd-apps/qewd-monitor-adminui');
|
216 |
|
217 | cmd = 'mv ' + webServerRootPath + '/qewd-monitor-adminui/qewd-apps/* ' + cwd + '/qewd-apps/qewd-monitor-adminui';
|
218 | child_process.execSync(cmd, {stdio:[0,1,2]});
|
219 |
|
220 | cmd = 'rm -r ' + webServerRootPath + '/qewd-monitor-adminui/qewd-apps';
|
221 | child_process.execSync(cmd, {stdio:[0,1,2]});
|
222 | }
|
223 | }
|
224 | }
|
225 |
|
226 | function unlinkMonitor(cwd, name) {
|
227 | if (name !== '') name = '/' + name;
|
228 | var path = cwd + name + '/www/qewd-monitor'
|
229 | if (process.env.mode && process.env.microservice) {
|
230 | path = cwd + '/www/qewd-monitor';
|
231 | }
|
232 | if (fs.existsSync(path)) {
|
233 | var cmd = 'unlink ' + path;
|
234 | child_process.execSync(cmd, {stdio:[0,1,2]});
|
235 | }
|
236 | }
|
237 |
|
238 | function updateRoutes(json) {
|
239 | fs.writeFileSync('/opt/qewd/mapped/configuration/routes.json', JSON.stringify(json, null, 2));
|
240 | }
|
241 |
|
242 | function addImportRoute(config_data, routes) {
|
243 | var startMode = 'normal';
|
244 | if (!config_data.microservices) return startMode;
|
245 |
|
246 | var on_microservices = [];
|
247 | config_data.microservices.forEach(function(ms) {
|
248 | if (ms.apis && ms.apis.import && !ms.apis.imported) {
|
249 |
|
250 | on_microservices.push(ms.name);
|
251 | }
|
252 | });
|
253 |
|
254 | if (on_microservices.length > 0) {
|
255 |
|
256 | startMode = 'import';
|
257 |
|
258 |
|
259 |
|
260 | routes.push({
|
261 | uri: '/qewd/importRoutes/:destination',
|
262 | method: 'POST',
|
263 | on_microservices: on_microservices,
|
264 | authenticate: false,
|
265 | bypassJWTCheck: true
|
266 | });
|
267 |
|
268 | updateRoutes(routes);
|
269 | }
|
270 | return startMode;
|
271 | }
|
272 |
|
273 | function setup(isDocker, service_name, isNative) {
|
274 |
|
275 | if (isNative) {
|
276 | process.env.qewd_service_name = service_name;
|
277 | process.env.qewd_isNative = true;
|
278 | if (service_name !== 'orchestrator') {
|
279 | process.env.mode = 'microservice';
|
280 | }
|
281 | }
|
282 |
|
283 | var cwd = process.cwd();
|
284 | if (service_name) {
|
285 | if (isNative) {
|
286 |
|
287 | }
|
288 | else {
|
289 | cwd = cwd + '/' + service_name;
|
290 | }
|
291 | }
|
292 | var ms_name = process.env.microservice;
|
293 | var mode = process.env.mode;
|
294 | var startupMode = 'normal';
|
295 |
|
296 | if (isDocker) {
|
297 | cwd = cwd + '/mapped';
|
298 | installModules(cwd);
|
299 | }
|
300 |
|
301 | var config_data;
|
302 | console.log('** loading ' + cwd + '/configuration/config.json');
|
303 | try {
|
304 | config_data = require(cwd + '/configuration/config.json');
|
305 | }
|
306 | catch(err) {
|
307 | config_data = {
|
308 |
|
309 | };
|
310 | }
|
311 |
|
312 | |
313 |
|
314 |
|
315 |
|
316 |
|
317 |
|
318 |
|
319 |
|
320 | var routes;
|
321 | var ms_config;
|
322 | var routes_data;
|
323 | var ms_index = {};
|
324 | var webServerRootPath = process.cwd() + '/www/';
|
325 | var serviceName;
|
326 |
|
327 | if (ms_name || mode) {
|
328 | if (ms_name) {
|
329 | webServerRootPath = cwd + '/' + ms_name + '/www/';
|
330 | }
|
331 |
|
332 | if (config_data.microservices) {
|
333 | config_data.microservices.forEach(function(microservice, index) {
|
334 | ms_index[microservice.name] = index;
|
335 | if (microservice.name === ms_name) {
|
336 | ms_config = microservice;
|
337 | }
|
338 | });
|
339 | }
|
340 |
|
341 | if (!mode && !ms_config) {
|
342 | console.log('Error: Unable to find configuration details for a microservice named ' + ms_name);
|
343 | return;
|
344 | }
|
345 |
|
346 | if (mode) {
|
347 | ms_config = config_data;
|
348 | }
|
349 | if (!ms_config.qewd) {
|
350 | ms_config.qewd = {};
|
351 | }
|
352 |
|
353 | if (ms_config.qewd['qewd-monitor'] !== false) {
|
354 |
|
355 | if (ms_name) {
|
356 | linkMonitor(cwd, ms_name);
|
357 | }
|
358 | else {
|
359 | linkMonitor(cwd, '');
|
360 | }
|
361 | }
|
362 | else {
|
363 | unlinkMonitor(cwd, ms_name);
|
364 | }
|
365 |
|
366 | }
|
367 | else {
|
368 |
|
369 |
|
370 |
|
371 | if (config_data.orchestrator) {
|
372 | if (isDocker || service_name) {
|
373 | webServerRootPath = cwd + '/orchestrator/www/';
|
374 |
|
375 |
|
376 |
|
377 |
|
378 | serviceName = 'orchestrator';
|
379 | }
|
380 | else {
|
381 | webServerRootPath = cwd + '/www/';
|
382 | serviceName = '';
|
383 | }
|
384 | if (config_data.orchestrator['qewd-monitor'] !== false) {
|
385 |
|
386 | linkMonitor(cwd, serviceName);
|
387 | }
|
388 | else {
|
389 | unlinkMonitor(cwd, serviceName);
|
390 | }
|
391 | }
|
392 | else {
|
393 | if (isDocker || service_name) {
|
394 | if (config_data.microservices) {
|
395 |
|
396 | webServerRootPath = cwd + '/orchestrator/www/';
|
397 | serviceName = 'orchestrator';
|
398 |
|
399 | linkMonitor(cwd, serviceName);
|
400 | }
|
401 | else {
|
402 |
|
403 | webServerRootPath = cwd + '/www/';
|
404 | serviceName = '';
|
405 |
|
406 | if (config_data['qewd-monitor'] !== false) {
|
407 |
|
408 | linkMonitor(cwd, serviceName);
|
409 | }
|
410 | else {
|
411 | unlinkMonitor(cwd, serviceName);
|
412 | }
|
413 | }
|
414 | }
|
415 | else {
|
416 | webServerRootPath = cwd + '/www/';
|
417 | serviceName = '';
|
418 | if (!config_data.qewd || (config_data.qewd && config_data.qewd['qewd-monitor'] !== false)) {
|
419 |
|
420 | linkMonitor(cwd, serviceName);
|
421 | }
|
422 | else {
|
423 | unlinkMonitor(cwd, serviceName);
|
424 | }
|
425 | }
|
426 | }
|
427 |
|
428 | try {
|
429 | routes_data = require(cwd + '/configuration/routes.json');
|
430 | }
|
431 | catch(err) {
|
432 | routes_data = [];
|
433 | }
|
434 |
|
435 | routes = [];
|
436 | var roots = {};
|
437 | }
|
438 |
|
439 | var transform = require('qewd-transform-json').transform;
|
440 | var helpers = {
|
441 | getBodyParser(bodyParser) {
|
442 | if (typeof bodyParser !== 'undefined' || bodyParser !== '') {
|
443 | try {
|
444 | return require(bodyParser);
|
445 | }
|
446 | catch(err) {
|
447 | return false;
|
448 | }
|
449 | }
|
450 | else {
|
451 | console.log('No bodyParser specified - use default');
|
452 | return false;
|
453 | }
|
454 | }
|
455 | };
|
456 |
|
457 | var default_db = 'gtm';
|
458 | if (isDocker) {
|
459 | default_db = 'dbx';
|
460 | }
|
461 |
|
462 | var config_template = {
|
463 | managementPassword: '=> either(qewd.managementPassword, "keepThisSecret!")',
|
464 | serverName: '=> either(qewd.serverName, "QEWD Server")',
|
465 | port: '=> either(qewd.port, 8080)',
|
466 | poolSize: '=> either(qewd.poolSize, 2)',
|
467 | database: {
|
468 | type: '=> either(qewd.database.type, default_db)',
|
469 | params: '=> either(qewd.database.params, "<!delete>")',
|
470 | },
|
471 | webServer: '{<qewd.webServer>}',
|
472 | ssl: '{<qewd.ssl>}',
|
473 | webServerRootPath: webServerRootPath,
|
474 | cors: '=> either(qewd.cors, true)',
|
475 | bodyParser: '=> getBodyParser(qewd.bodyParser)',
|
476 | mode: '=> either(qewd.mode, "production")',
|
477 | max_queue_length: '{<qewd.max_queue_length>}',
|
478 | use_worker_threads: '{<qewd.use_worker_threads>}'
|
479 | };
|
480 |
|
481 | var config;
|
482 | var addMiddlewarePath;
|
483 |
|
484 | if (ms_name) {
|
485 | config = transform(config_template, ms_config, helpers);
|
486 | addMiddlewarePath = cwd + '/' + ms_name + '/addMiddleware.js';
|
487 | }
|
488 | else {
|
489 | if (isDocker || service_name) {
|
490 | if (config_data.orchestrator) {
|
491 | config = transform(config_template, config_data.orchestrator, helpers);
|
492 | }
|
493 | else {
|
494 | config = transform(config_template, config_data, helpers);
|
495 | }
|
496 | if (config_data.microservices) {
|
497 | addMiddlewarePath = cwd + '/orchestrator/addMiddleware.js';
|
498 | }
|
499 | else {
|
500 | addMiddlewarePath = cwd + '/addMiddleware.js';
|
501 | }
|
502 | }
|
503 | else {
|
504 | config = transform(config_template, config_data, helpers);
|
505 | addMiddlewarePath = cwd + '/addMiddleware.js';
|
506 | }
|
507 | }
|
508 | if (fs.existsSync(addMiddlewarePath)) {
|
509 | config.addMiddlewareUp = require(addMiddlewarePath);
|
510 | }
|
511 | config.qewd_up = true;
|
512 | config.permit_application_switch = config_data.permit_application_switch;
|
513 |
|
514 |
|
515 |
|
516 | if (process.env.qewd_service_name) {
|
517 | config.service_name = process.env.qewd_service_name
|
518 | }
|
519 | if (process.env.mode && process.env.microservice) {
|
520 | config.service_name = process.env.microservice;
|
521 | }
|
522 |
|
523 | |
524 |
|
525 |
|
526 |
|
527 |
|
528 |
|
529 |
|
530 |
|
531 |
|
532 |
|
533 | if (isDocker || service_name) {
|
534 |
|
535 | if (ms_name || mode === 'microservice') {
|
536 |
|
537 |
|
538 | if (!mode) createModuleMap(cwd + '/' + ms_name, config);
|
539 |
|
540 | var routePath;
|
541 | if (ms_name && !service_name) {
|
542 | routePath = ms_config.name;
|
543 | }
|
544 | else {
|
545 |
|
546 |
|
547 | routePath = config_data.ms_name || mode || service_name;
|
548 | }
|
549 |
|
550 | routes = [{
|
551 | path: routePath,
|
552 | module: __dirname + '/ms_handlers',
|
553 | errors: {
|
554 | notfound: {
|
555 | text: 'Resource Not Recognised',
|
556 | statusCode: 404
|
557 | }
|
558 | }
|
559 | }];
|
560 |
|
561 | try {
|
562 | console.log('loading ' + cwd + '/configuration/routes.json');
|
563 | routes_data = require(cwd + '/configuration/routes.json');
|
564 | }
|
565 | catch(err) {
|
566 | console.log('unable to load ' + cwd + '/configuration/routes.json');
|
567 | routes_data = [];
|
568 | }
|
569 |
|
570 |
|
571 |
|
572 |
|
573 |
|
574 |
|
575 |
|
576 | if (mode === 'microservice' && !config_data.imported) {
|
577 |
|
578 | startupMode = 'export';
|
579 |
|
580 | var importRouteFound = false;
|
581 | routes_data.forEach(function(route) {
|
582 | if (route.uri === '/qewd/importRoutes/:destination') {
|
583 | importRouteFound = true;
|
584 | }
|
585 | });
|
586 |
|
587 | if (!importRouteFound) {
|
588 | routes_data.push({
|
589 | uri: '/qewd/importRoutes/:destination',
|
590 | method: 'POST',
|
591 | handler: 'importRoutes',
|
592 | authenticate: false,
|
593 | bypassJWTCheck: true
|
594 | });
|
595 |
|
596 | updateRoutes(routes_data);
|
597 | }
|
598 |
|
599 | var apiPath = cwd + '/apis';
|
600 | if (!fs.existsSync(apiPath)) {
|
601 | fs.mkdirSync(apiPath);
|
602 | }
|
603 | apiPath = cwd + '/apis/importRoutes';
|
604 | if (!fs.existsSync(apiPath)) {
|
605 | fs.mkdirSync(apiPath);
|
606 | }
|
607 | var cmd = 'cp ' + process.cwd() + '/node_modules/qewd/up/exportRoutesFromMs.js ' + cwd + '/apis/importRoutes/index.js';
|
608 | child_process.execSync(cmd, {stdio:[0,1,2]});
|
609 | cmd = 'cp ' + process.cwd() + '/node_modules/qewd/up/stopMSAfterExport.js ' + cwd + '/apis/importRoutes/onMSResponse.js';
|
610 | child_process.execSync(cmd, {stdio:[0,1,2]});
|
611 |
|
612 | }
|
613 |
|
614 |
|
615 | routes_data.forEach(function(route) {
|
616 | if (route.from_microservices) {
|
617 | route.from_microservices.forEach(function(ms) {
|
618 | if (ms === ms_name) {
|
619 | if (route.on_microservice) {
|
620 | if (!ms_config.connections) {
|
621 | ms_config.connections = [];
|
622 | }
|
623 | ms_config.connections.push(route.on_microservice);
|
624 | }
|
625 | }
|
626 | });
|
627 | }
|
628 | });
|
629 |
|
630 | if (ms_config.connections) {
|
631 | config.u_services = {
|
632 | destinations: {}
|
633 | };
|
634 |
|
635 | ms_config.connections.forEach(function(ms_name) {
|
636 | var index = ms_index[ms_name];
|
637 | if (typeof index !== 'undefined') {
|
638 | var ms_info = config_data.microservices[index];
|
639 | var host = ms_info.host || ms_info.name;
|
640 | if (!host.startsWith('http://') && !host.startsWith('https://')) {
|
641 | host = 'http://' + host;
|
642 | }
|
643 | var port = ms_info.port || 8080;
|
644 | if (port !== 80 && port !== 443) {
|
645 | host = host + ':' + port;
|
646 | }
|
647 | config.u_services.destinations[ms_info.name] = {
|
648 | host: host,
|
649 | application: ms_info.name
|
650 | };
|
651 | }
|
652 | });
|
653 |
|
654 |
|
655 | var ms_routes = [];
|
656 | routes_data.forEach(function(route) {
|
657 | if (route.from_microservices) {
|
658 | route.from_microservices.forEach(function(from_ms) {
|
659 | if (from_ms === ms_name) {
|
660 | ms_routes.push(route);
|
661 | }
|
662 | });
|
663 | }
|
664 | });
|
665 | if (ms_routes.length > 0) {
|
666 | config.u_services.routes = [];
|
667 | ms_routes.forEach(function(route) {
|
668 | config.u_services.routes.push({
|
669 | path: route.uri,
|
670 | method: route.method,
|
671 | destination: route.on_microservice
|
672 | });
|
673 | });
|
674 | }
|
675 | }
|
676 |
|
677 | }
|
678 | else {
|
679 |
|
680 |
|
681 |
|
682 |
|
683 | startupMode = addImportRoute(config_data, routes_data)
|
684 |
|
685 |
|
686 |
|
687 | createModuleMap(cwd, config);
|
688 |
|
689 |
|
690 |
|
691 |
|
692 |
|
693 | if (config_data.microservices && Array.isArray(config_data.microservices)) {
|
694 | config.u_services = {
|
695 | destinations: {},
|
696 | routes: []
|
697 | };
|
698 | var destinations = config.u_services.destinations;
|
699 | config_data.microservices.forEach(function(microservice) {
|
700 |
|
701 | var host;
|
702 | var port;
|
703 |
|
704 | if (microservice.members) {
|
705 |
|
706 | destinations[microservice.name] = {
|
707 | destinations: microservice.members
|
708 | }
|
709 | }
|
710 | else {
|
711 |
|
712 |
|
713 | host = microservice.host || microservice.name;
|
714 | if (!host.startsWith('http://') && !host.startsWith('https://')) {
|
715 | host = 'http://' + host;
|
716 | }
|
717 | port = microservice.port || 8080;
|
718 | if (port !== 80 && port !== 443) {
|
719 | host = host + ':' + port;
|
720 | }
|
721 |
|
722 | destinations[microservice.name] = {
|
723 | host: host,
|
724 | application: microservice.name
|
725 | };
|
726 | }
|
727 | });
|
728 |
|
729 | routes_data.forEach(function(route) {
|
730 | var routeObj;
|
731 | var onOrchResponseFn;
|
732 |
|
733 | if (route.on_microservice || route.on_microservices) {
|
734 |
|
735 | if (route.from_microservices) {
|
736 |
|
737 | var onConductor = false;
|
738 | route.from_microservices.forEach(function(ms_name) {
|
739 | if (ms_name === 'orchestrator') {
|
740 | onConductor = true;
|
741 | }
|
742 | });
|
743 | if (!onConductor) return;
|
744 | }
|
745 |
|
746 | routeObj = {
|
747 | path: route.uri,
|
748 | method: route.method,
|
749 | destination: route.on_microservice
|
750 | };
|
751 |
|
752 | if (route.authenticate === false) {
|
753 | routeObj.bypassJWTCheck = true;
|
754 | }
|
755 |
|
756 | |
757 |
|
758 |
|
759 |
|
760 |
|
761 |
|
762 |
|
763 |
|
764 |
|
765 |
|
766 |
|
767 |
|
768 |
|
769 | if (route.handler) {
|
770 | onOrchResponsePaths = [
|
771 | cwd + '/' + route.on_microservice + '/' + route.handler + '/onOrchResponse.js',
|
772 | cwd + '/' + route.on_microservice + '/apis/' + route.handler + '/onOrchResponse.js',
|
773 | cwd + '/onOrchResponse/' + route.on_microservice + '/' + route.handler + '.js'
|
774 | ];
|
775 | for (var i = 0; i < onOrchResponsePaths.length; i++) {
|
776 | console.log('checking onOrchResponsePath: ' + onOrchResponsePaths[i]);
|
777 | if (fs.existsSync(onOrchResponsePaths[i])) {
|
778 | try {
|
779 | onOrchResponseFn = require(onOrchResponsePaths[i]);
|
780 | console.log('onOrchResponse handler loaded from ' + onOrchResponsePaths[i]);
|
781 | }
|
782 | catch(err) {
|
783 | console.log('** Warning - onOrchResponse handler could not be loaded from ' + onOrchResponsePaths[i]);
|
784 | }
|
785 | break;
|
786 | }
|
787 | }
|
788 | }
|
789 |
|
790 | if (onOrchResponseFn) {
|
791 | routeObj.onResponse = function(args) {
|
792 | var _this = this;
|
793 |
|
794 | function handleResponse(obj) {
|
795 | if (!obj.message) {
|
796 | obj = {
|
797 | message: obj
|
798 | };
|
799 | }
|
800 | args.handleResponse.call(_this, obj);
|
801 | }
|
802 |
|
803 | function forwardToMS(message, callback) {
|
804 | var msgObj = message;
|
805 | if (!msgObj.headers) {
|
806 | msgObj.headers = {};
|
807 | }
|
808 | msgObj.headers.authorization = 'Bearer ' + args.responseObj.message.token;
|
809 |
|
810 | var status = args.send(msgObj, callback);
|
811 |
|
812 | if (status === false) {
|
813 | callback({error: 'No such route: ' + message.method + ' ' + message.path})
|
814 | }
|
815 | }
|
816 |
|
817 | function getJWTProperty(name) {
|
818 | return _this.jwt.handlers.getProperty(name, args.responseObj.message.token);
|
819 | }
|
820 |
|
821 | return onOrchResponseFn.call(this, args.responseObj, args.message, forwardToMS, handleResponse, getJWTProperty);
|
822 | };
|
823 | }
|
824 |
|
825 | config.u_services.routes.push(routeObj);
|
826 | }
|
827 |
|
828 | else if (route.router) {
|
829 |
|
830 |
|
831 | var onRequestPath = cwd + '/orchestrator/routers/' + route.router + '.js';
|
832 |
|
833 | routeObj = {
|
834 | path: route.uri,
|
835 | method: route.method
|
836 | };
|
837 | if (fs.existsSync(onRequestPath)) {
|
838 | routeObj.onRequest = require(onRequestPath);
|
839 | console.log('Adding onRequest handler for ' + route.uri + ': ' + onRequestPath);
|
840 | }
|
841 | config.u_services.routes.push(routeObj);
|
842 | }
|
843 |
|
844 | });
|
845 | }
|
846 | else {
|
847 | console.log('*** orchestrator without any microservices ***');
|
848 | }
|
849 |
|
850 | }
|
851 |
|
852 | if (!config_data.jwt || !config_data.jwt.secret) {
|
853 | config_data.jwt = {
|
854 | secret: uuid()
|
855 | };
|
856 |
|
857 | fs.writeFileSync(cwd + '/configuration/config.json', JSON.stringify(config_data, null, 2));
|
858 | }
|
859 | config.jwt = Object.assign({}, config_data.jwt);
|
860 | }
|
861 | else {
|
862 |
|
863 | createModuleMap(cwd, config);
|
864 | }
|
865 |
|
866 | if (!ms_name && !mode) {
|
867 |
|
868 | routes_data.forEach(function(route) {
|
869 | if (route.else) return;
|
870 |
|
871 | var path_root = '/' + route.uri.split('/')[1];
|
872 | if (!roots[path_root]) {
|
873 |
|
874 | var routeObj = {
|
875 | path: path_root,
|
876 | module: __dirname + '/handlers'
|
877 | };
|
878 |
|
879 |
|
880 | var handlerPath = cwd;
|
881 |
|
882 | var orchestratorHandlerPath = cwd + '/orchestrator';
|
883 | if (fs.existsSync(orchestratorHandlerPath)) {
|
884 | handlerPath = orchestratorHandlerPath;
|
885 | }
|
886 |
|
887 | var onWSRequestPath = handlerPath + '/onWSRequest.js';
|
888 | console.log('onWSRequestPath: ' + onWSRequestPath);
|
889 | if (fs.existsSync(onWSRequestPath)) {
|
890 | routeObj.beforeRouter = [require(onWSRequestPath)];
|
891 | }
|
892 |
|
893 |
|
894 | var onWSResponsePath = handlerPath + '/onWSResponse.js';
|
895 | console.log('onWSResponsePath: ' + onWSResponsePath);
|
896 | if (fs.existsSync(onWSResponsePath)) {
|
897 | routeObj.afterRouter = [require(onWSResponsePath)];
|
898 | }
|
899 |
|
900 | routes.push(routeObj);
|
901 | roots[path_root] = true;
|
902 | }
|
903 | });
|
904 | }
|
905 |
|
906 | return {
|
907 | routes: routes,
|
908 | config: config,
|
909 | cwd: cwd,
|
910 | startupMode: startupMode
|
911 | };
|
912 | }
|
913 |
|
914 | module.exports = function(isDocker, serviceName, isNative) {
|
915 |
|
916 | var results = setup(isDocker, serviceName, isNative);
|
917 |
|
918 | console.log('** results = ' + JSON.stringify(results, null, 2));
|
919 |
|
920 | if (!results) return;
|
921 | var config = results.config;
|
922 | var routes = results.routes;
|
923 | var startupMode = results.startupMode;
|
924 | var cwd = results.cwd;
|
925 |
|
926 |
|
927 |
|
928 | var ms_name = process.env.microservice;
|
929 |
|
930 | var onStartedPath;
|
931 | var onStartedPath2;
|
932 |
|
933 | if (ms_name) {
|
934 | onStartedPath = cwd + '/' + ms_name + '/onStarted.js';
|
935 | }
|
936 | else {
|
937 | onStartedPath = cwd + '/orchestrator/onStarted.js';
|
938 | onStartedPath2 = cwd + '/onStarted.js';
|
939 | }
|
940 |
|
941 | if (isDocker) {
|
942 |
|
943 | if (startupMode === 'export') {
|
944 | console.log('\n===============================================');
|
945 | console.log(' This QEWD-Up MicroService has started in');
|
946 | console.log(' export mode. When the Orchestrator');
|
947 | console.log(' starts and connects to this MicroService,');
|
948 | console.log(' it will export its routes to the');
|
949 | console.log(' Orchestrator, its JWT secret will be');
|
950 | console.log(' changed to the one used by the Orchestrator');
|
951 | console.log(' and it will then shut down.');
|
952 | console.log(' ');
|
953 | console.log(' You should then restart this MicroService');
|
954 | console.log('===============================================');
|
955 | console.log(' ');
|
956 | }
|
957 |
|
958 | if (startupMode === 'import') {
|
959 | console.log('\n===============================================');
|
960 | console.log(' This QEWD-Up Orchestrator has started in');
|
961 | console.log(' import mode. When it connects to each');
|
962 | console.log(' MicroService, it will import its routes.');
|
963 | console.log(' When all MicroService routes are imported');
|
964 | console.log(' the Orchestrator will shut down.');
|
965 | console.log(' ');
|
966 | console.log(' You should then restart the Orchestrator');
|
967 | console.log('===============================================');
|
968 | console.log(' ');
|
969 | }
|
970 |
|
971 | var exportObj = {
|
972 | config: config,
|
973 | routes: routes
|
974 | };
|
975 |
|
976 | if (fs.existsSync(onStartedPath)) {
|
977 | exportObj.onStarted = require(onStartedPath);
|
978 | }
|
979 | else if (fs.existsSync(onStartedPath2)) {
|
980 | exportObj.onStarted = require(onStartedPath2);
|
981 | }
|
982 | return exportObj;
|
983 | }
|
984 | else {
|
985 |
|
986 | if (config.database && config.database.type === 'gtm') {
|
987 |
|
988 | try {
|
989 | console.log('Running down YottaDB...');
|
990 | child_process.execSync(process.env.ydb_dist + '/mupip rundown -region DEFAULT', {stdio:[0,1,2]});
|
991 | child_process.execSync(process.env.ydb_dist + '/mupip rundown -region qewdreg', {stdio:[0,1,2]});
|
992 | console.log('Rundown completed');
|
993 | }
|
994 | catch(err) {
|
995 | console.log('Error running down YottaDB: ' + err);
|
996 | console.log('Recovering journal...');
|
997 | try {
|
998 | child_process.execSync(process.env.ydb_dist + '/mupip journal -recover -backward ' + process.env.ydb_dir + '/' + process.env.ydb_rel + '/g/yottadb.mjl', {stdio:[0,1,2]});
|
999 | console.log('Journal recovered');
|
1000 | }
|
1001 | catch(err) {
|
1002 | console.log('YottaDB is probably already in use');
|
1003 | }
|
1004 | }
|
1005 | }
|
1006 |
|
1007 | console.log('config: ' + JSON.stringify(config, null, 2));
|
1008 | console.log('routes: ' + JSON.stringify(routes, null, 2));
|
1009 |
|
1010 | var q = qewd.start(config, routes);
|
1011 | var xp = qewd.intercept();
|
1012 |
|
1013 | if (fs.existsSync(onStartedPath)) {
|
1014 | require(onStartedPath).call(q, config, xp.app, xp.qx.router, xp.qx);
|
1015 | }
|
1016 | else if (fs.existsSync(onStartedPath2)) {
|
1017 | require(onStartedPath2).call(q, config, xp.app, xp.qx.router, xp.qx);
|
1018 | }
|
1019 | }
|
1020 | };
|