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