UNPKG

35.1 kBJavaScriptView Raw
1/*
2
3 ----------------------------------------------------------------------------
4 | qewd-up: Rapid QEWD API Development |
5 | |
6 | Copyright (c) 2018-20 M/Gateway Developments Ltd, |
7 | Redhill, Surrey UK. |
8 | All rights reserved. |
9 | |
10 | http://www.mgateway.com |
11 | Email: rtweed@mgateway.com |
12 | |
13 | |
14 | Licensed under the Apache License, Version 2.0 (the "License"); |
15 | you may not use this file except in compliance with the License. |
16 | You may obtain a copy of the License at |
17 | |
18 | http://www.apache.org/licenses/LICENSE-2.0 |
19 | |
20 | Unless required by applicable law or agreed to in writing, software |
21 | distributed under the License is distributed on an "AS IS" BASIS, |
22 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
23 | See the License for the specific language governing permissions and |
24 | limitations under the License. |
25 ----------------------------------------------------------------------------
26
27 2 July 2020
28
29*/
30
31//console.log('Loading /up/run.js in process ' + process.pid);
32
33var fs = require('fs-extra');
34var path = require('path');
35var os = require('os');
36var module_exists = require('module-exists');
37var child_process = require('child_process');
38var qewd = require('../lib/master');
39var uuid = require('uuid/v4'); // loaded as dependency of ewd-session
40
41function getDirectories(path) {
42 return fs.readdirSync(path).filter(function(file) {
43 return fs.statSync(path + '/' + file).isDirectory();
44 });
45}
46
47function 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 // if handler modules exist, create the dynamic handler for this path
59 // otherwise use the existing index.js
60 if (handlerList.length > 0) {
61 var text;
62 //text = "module.exports = require('" + __dirname + "/qewdAppHandler" + "')('" + appPath + "');"
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
79function 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
101function 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
121function 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
226function 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
238function updateRoutes(json) {
239 fs.writeFileSync('/opt/qewd/mapped/configuration/routes.json', JSON.stringify(json, null, 2));
240}
241
242function 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 // this microservice needs to be imported
250 on_microservices.push(ms.name);
251 }
252 });
253
254 if (on_microservices.length > 0) {
255
256 startMode = 'import';
257
258 // add temporary route to allow import of microservice routes
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
273function 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 // leave cwd alone
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 //orchestrator: {}
309 };
310 }
311
312 /*
313 if (!isDocker && !config_data.orchestrator && config_data.qewd) {
314 config_data.orchestrator = {
315 qewd: config_data.qewd
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 // this is running a microservice container
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 //console.log('1 enabling qewd-monitor');
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 // not a microservice - either native or docker monolith, or docker orchestrator
370
371 if (config_data.orchestrator) {
372 if (isDocker || service_name) {
373 webServerRootPath = cwd + '/orchestrator/www/';
374 //orchPath = cwd + '/orchestrator';
375 //if (!fs.existsSync(orchPath)) {
376 // fs.mkdirSync(orchPath);
377 //}
378 serviceName = 'orchestrator';
379 }
380 else {
381 webServerRootPath = cwd + '/www/';
382 serviceName = '';
383 }
384 if (config_data.orchestrator['qewd-monitor'] !== false) {
385 //console.log('2 enabling qewd-monitor');
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 // this is Docker orchestrator
396 webServerRootPath = cwd + '/orchestrator/www/';
397 serviceName = 'orchestrator';
398 //console.log('3 enabling qewd-monitor *');
399 linkMonitor(cwd, serviceName);
400 }
401 else {
402 // Docker monolith
403 webServerRootPath = cwd + '/www/';
404 serviceName = '';
405
406 if (config_data['qewd-monitor'] !== false) {
407 //console.log('4 enabling qewd-monitor');
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 //console.log('5 enabling qewd-monitor');
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 // ** set service name if running orchestrator or microservice standalone
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 console.log('process.env.qewd_service_name = ' + process.env.qewd_service_name);
525 console.log('process.env.mode = ' + process.env.mode);
526 console.log('process.env.microservice = ' + process.env.microservice);
527 console.log('isDocker = ' + isDocker);
528 console.log('service_name = ' + service_name);
529 console.log('ms_name = ' + ms_name);
530 console.log('config_data = ' + JSON.stringify(config_data, null, 2));
531 */
532
533 if (isDocker || service_name) {
534
535 if (ms_name || mode === 'microservice') {
536 // This is a micro-service, not the orchestrator
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 // standalone MS running in microservice mode
546 // if running integrated microservice natively, use service_name
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 // if this is a standalone microservice running in microservice mode,
571 // AND the imported flag has not yet been set, then add the temporary
572 // route that will accept the request from the orchestrator so the
573 // microservice's routes can be imported into the orchestrator.
574 // Also add the handler API & method for it
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 // dynamically create connections info from routes if not already defined in the config.json information
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; // default to Docker 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 // This is the orchestrator (or Docker monolith)
680
681 // check if microservices need importing, and if so, add import route
682
683 startupMode = addImportRoute(config_data, routes_data)
684
685 // Add module map if necessary
686
687 createModuleMap(cwd, config);
688
689 // Add in microservice definitions if present
690
691 //console.log('config_data.microservices: ' + JSON.stringify(config_data.microservices, null, 2));
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 // group destination
706 destinations[microservice.name] = {
707 destinations: microservice.members
708 }
709 }
710 else {
711 // physical endpoint destination
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 // is this route not sourced by conductor? If so, ignore on conductor
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 //var onRequestPath = cwd + '/' + route.on_microservice + '/handlers/' + route.handler + '/onRequest.js';
759 var onRequestPath = cwd + '/' + route.on_microservice + '/' + route.handler + '/onRequest.js';
760 console.log('Checking for onRequest path: ' + onRequestPath);
761 if (fs.existsSync(onRequestPath)) {
762 routeObj.onRequest = require(onRequestPath);
763 console.log('Adding onRequest handler for ' + route.uri + ': ' + onRequestPath);
764 }
765
766 */
767
768 //var onResponsePath = cwd + '/' + route.on_microservice + '/handlers/' + route.handler + '/onResponse.js';
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 //console.log('sending ' + JSON.stringify(msgObj, null, 2));
810 var status = args.send(msgObj, callback);
811 //console.log('status = ' + status);
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 // dynamically-controlled routing to other API
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 // write it back to cwd + '/configuration/config.json'
857 fs.writeFileSync(cwd + '/configuration/config.json', JSON.stringify(config_data, null, 2));
858 }
859 config.jwt = Object.assign({}, config_data.jwt); // prevent it being simply by reference
860 }
861 else {
862 // native app
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 //var handlerPath = cwd + '/apis';
880 var handlerPath = cwd;
881 //var orchestratorHandlerPath = cwd + '/orchestrator/apis';
882 var orchestratorHandlerPath = cwd + '/orchestrator';
883 if (fs.existsSync(orchestratorHandlerPath)) {
884 handlerPath = orchestratorHandlerPath;
885 }
886 //var beforeRouterPath = handlerPath + path_root + '/beforeRouter.js';
887 var onWSRequestPath = handlerPath + '/onWSRequest.js';
888 console.log('onWSRequestPath: ' + onWSRequestPath);
889 if (fs.existsSync(onWSRequestPath)) {
890 routeObj.beforeRouter = [require(onWSRequestPath)];
891 }
892
893 //var afterRouterPath = handlerPath + path_root + '/afterRouter.js';
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
914module.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 //console.log('routes: ' + JSON.stringify(routes, null, 2));
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};