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