From 5fd58de7f1befc1fedb589e7e6a79c88be2ff2c3 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Thu, 7 Mar 2024 14:58:06 -0500 Subject: [PATCH 01/18] Remove use of ncp and mkdirp Signed-off-by: 1000TurquoisePogs --- lib/initInstance.js | 22 ++++---- lib/initUtils.js | 5 +- lib/zluxArgs.js | 1 - package-lock.json | 124 ++++++++------------------------------------ package.json | 3 +- 5 files changed, 36 insertions(+), 119 deletions(-) diff --git a/lib/initInstance.js b/lib/initInstance.js index 4aa2b1f3..e9bed843 100644 --- a/lib/initInstance.js +++ b/lib/initInstance.js @@ -16,9 +16,7 @@ const yamlConfig = require('../../zlux-server-framework/utils/yamlConfig'); const initUtils = require('./initUtils'); //const upgradeInstance = require('./upgradeInstance'); const os = require('os'); -const ncp = require('ncp').ncp; const { execSync } = require('child_process'); -const mkdirp = require('mkdirp'); const haInstanceId = yamlConfig.getCurrentHaInstanceId(); @@ -44,43 +42,43 @@ const versionLocation = path.join(destination, 'component.json'); config.productDir = path.join(__dirname, '..', 'defaults'); //Begin generate any missing folders -mkdirp.sync(destination, {mode: initUtils.FOLDER_MODE}); +fs.mkdirSync(destination, {mode: initUtils.FOLDER_MODE, recursive: true}); if (!config.siteDir) { config.siteDir = path.join(destination, 'site'); } const sitePluginStorage = path.join(config.siteDir, 'ZLUX', 'pluginStorage'); -mkdirp.sync(sitePluginStorage, {mode: initUtils.FOLDER_MODE}); +fs.mkdirSync(sitePluginStorage, {mode: initUtils.FOLDER_MODE, recursive: true}); if (!config.instanceDir) { config.instanceDir = destination; } const instancePluginStorage = path.join(config.instanceDir, 'ZLUX', 'pluginStorage'); -mkdirp.sync(instancePluginStorage, {mode: initUtils.FOLDER_MODE}); +fs.mkdirSync(instancePluginStorage, {mode: initUtils.FOLDER_MODE, recursive: true}); const recognizersPluginStorage = path.join(config.instanceDir, 'ZLUX/pluginStorage', 'org.zowe.zlux.ng2desktop/recognizers'); -mkdirp.sync(recognizersPluginStorage, {mode: initUtils.FOLDER_MODE}); +fs.mkdirSync(recognizersPluginStorage, {mode: initUtils.FOLDER_MODE, recursive: true}); const actionsPluginStorage = path.join(config.instanceDir, 'ZLUX/pluginStorage/org.zowe.zlux.ng2desktop', 'actions'); -mkdirp.sync(actionsPluginStorage, {mode: initUtils.FOLDER_MODE}); +fs.mkdirSync(actionsPluginStorage, {mode: initUtils.FOLDER_MODE, recursive: true}); const instanceConfig = path.join(config.instanceDir, 'serverConfig'); //750 specifically, to keep server config secure -mkdirp.sync(instanceConfig, {mode: 0o0750}); +fs.mkdirSync(instanceConfig, {mode: 0o0750}); if (!config.groupsDir) { config.groupsDir = path.join(config.instanceDir, 'groups'); } -mkdirp.sync(config.groupsDir, {mode: initUtils.FOLDER_MODE}); +fs.mkdirSync(config.groupsDir, {mode: initUtils.FOLDER_MODE, recursive: true}); if (!config.usersDir) { config.usersDir = path.join(config.instanceDir, 'users'); } -mkdirp.sync(config.usersDir, {mode: initUtils.FOLDER_MODE}); +fs.mkdirSync(config.usersDir, {mode: initUtils.FOLDER_MODE, recursive: true}); if (!config.pluginsDir) { config.pluginsDir = path.join(destination, 'plugins'); } -mkdirp.sync(config.pluginsDir, {mode: initUtils.FOLDER_MODE}); +fs.mkdirSync(config.pluginsDir, {mode: initUtils.FOLDER_MODE, recursive: true}); function generateComponentJson() { let componentJsonContent; @@ -144,7 +142,7 @@ try { if (siteStorage.length == 0 && instanceStorage.length == 0) { console.log("ZWED5012I - Copying default plugin preferences into instance"); if (os.platform() == 'win32') { - ncp(path.join(config.productDir, 'ZLUX', 'pluginStorage'), instancePluginStorage, function(err){ + fs.cp(path.join(config.productDir, 'ZLUX', 'pluginStorage'), instancePluginStorage, {recursive: true, force: true}, function(err){ if (err) { console.warn('ZWED5005W - Warning: error while copying plugin preferences into instance',err); process.exit(1); diff --git a/lib/initUtils.js b/lib/initUtils.js index 3bdef778..8399c410 100644 --- a/lib/initUtils.js +++ b/lib/initUtils.js @@ -10,7 +10,6 @@ const fs = require('fs'); const path = require('path'); -const mkdirp = require('mkdirp'); const ZLUX_ROOT_DIR = path.join(__dirname, '..'); const DEFAULT_PLUGINS_DIR = path.join(ZLUX_ROOT_DIR, 'defaults', 'plugins'); @@ -78,7 +77,7 @@ module.exports.registerBundledPlugin = registerBundledPlugin; module.exports.setTerminalDefaults = function(configDestination, instanceItems) { if (instanceItems.indexOf('org.zowe.terminal.vt.json') != -1) { let defaultConfigDir = path.join(configDestination,'org.zowe.terminal.vt','sessions'); - mkdirp.sync(defaultConfigDir); + fs.mkdirSync(defaultConfigDir, {recursive: true}); try { fs.writeFileSync(path.join(defaultConfigDir,'_defaultVT.json'), JSON.stringify({host:process.env['ZWED_SSH_HOST'] ? process.env['ZWED_SSH_HOST'] : "", @@ -94,7 +93,7 @@ module.exports.setTerminalDefaults = function(configDestination, instanceItems) security = process.env['ZWED_TN3270_SECURITY']; } let defaultConfigDir = path.join(configDestination,'org.zowe.terminal.tn3270','sessions'); - mkdirp.sync(defaultConfigDir); + fs.mkdirSync(defaultConfigDir, {recursive: true}); try { let tn3270Json = {host:process.env['ZWED_TN3270_HOST'] ? process.env['ZWED_TN3270_HOST'] : "", port: process.env['ZWED_TN3270_PORT'] ? process.env['ZWED_TN3270_PORT'] : 23, diff --git a/lib/zluxArgs.js b/lib/zluxArgs.js index 5aca76c4..138ece4d 100644 --- a/lib/zluxArgs.js +++ b/lib/zluxArgs.js @@ -16,7 +16,6 @@ const argParser = require('zlux-server-framework/utils/argumentParser'); const jsonUtils = require('zlux-server-framework/lib/jsonUtils'); const mergeUtils = require('zlux-server-framework/utils/mergeUtils'); const yamlConfig = require('zlux-server-framework/utils/yamlConfig'); -const mkdirp = require('mkdirp'); const cluster = require('cluster'); const MVD_ARGS = [ diff --git a/package-lock.json b/package-lock.json index 797db2c5..9ff5f6ad 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,13 @@ { "name": "zlux-app-server", "version": "1.0.0", - "lockfileVersion": 2, + "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "zlux-app-server", "version": "1.0.0", "dependencies": { - "mkdirp": "~0.5.1", "zlux-server-framework": "file:../zlux-server-framework" } }, @@ -16,125 +15,48 @@ "version": "0.0.0-zlux.version.replacement", "license": "EPL-2.0", "dependencies": { - "@rocketsoftware/eureka-js-client": "~4.5.3", + "@rocketsoftware/eureka-js-client": "~4.5.6", "@rocketsoftware/express-ws": "^5.0.0", "accept-language-parser": "~1.5.0", - "axios": "~1.6.7", - "bluebird": "~3.5.1", - "body-parser": "~1.18.3", - "cookie-parser": "~1.4.3", + "axios": "^1.6.7", + "bluebird": "3.7.2", + "body-parser": "~1.20.2", + "cookie-parser": "~1.4.6", "diffie-hellman": "^5.0.3", - "express": "~4.16.3", - "express-session": "~1.15.6", - "express-static-gzip": "~1.1.3", - "glob": "~7.1.3", - "graceful-fs": "~4.1.15", - "ipaddr.js": "~1.8.0", - "js-yaml": "~3.13.1", - "lodash": "~4.17.21", - "mkdirp": "~0.5.1", - "ncp": "~2.0.0", - "node-forge": "~1.3.0", + "express": "~4.18.3", + "express-session": "~1.18.0", + "express-static-gzip": "~2.1.7", + "graceful-fs": "~4.2.11", + "ipaddr.js": "~2.1.0", + "node-forge": "~1.3.1", "normalize-url": "~7.0.0", "require-from-string": "~2.0.2", - "rimraf": "~2.6.3", - "semver": "~5.5.1", + "semver": "~7.6.0", "swagger-parser": "~10.0.3", "ws": "^6.2.2", - "yaml": "~1.10.2", - "yauzl": "~2.10.0" + "yaml": "~2.4.1", + "yauzl": "~3.1.2" }, "devDependencies": { - "@types/connect": "3.4.32", - "@types/express": "~4.16.1", - "@types/express-serve-static-core": "4.17.7", - "@types/node": "~6.0.0", + "@types/connect": "3.4.35", + "@types/express": "4.17.17", + "@types/express-serve-static-core": "4.17.35", + "@types/mime": "3.0.1", + "@types/node": "~16.18.0", "@types/qs": "6.9.3", "chai": "~4.2.0", "chai-http": "~4.2.0", - "mocha": "~8.4.0", - "typescript": "2.7.1" + "mocha": "~10.2.0", + "typescript": "~5.0.0" }, "optionalDependencies": { + "fsevents": "~2.3.2", "keyring_js": "~1.1.0" } }, - "node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "node_modules/mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "mkdirp": "bin/cmd.js" - } - }, "node_modules/zlux-server-framework": { "resolved": "../zlux-server-framework", "link": true } - }, - "dependencies": { - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==" - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "requires": { - "minimist": "^1.2.5" - } - }, - "zlux-server-framework": { - "version": "file:../zlux-server-framework", - "requires": { - "@rocketsoftware/eureka-js-client": "~4.5.3", - "@rocketsoftware/express-ws": "^5.0.0", - "@types/connect": "3.4.32", - "@types/express": "~4.16.1", - "@types/express-serve-static-core": "4.17.7", - "@types/node": "~6.0.0", - "@types/qs": "6.9.3", - "accept-language-parser": "~1.5.0", - "axios": "~1.6.7", - "bluebird": "~3.5.1", - "body-parser": "~1.18.3", - "chai": "~4.2.0", - "chai-http": "~4.2.0", - "cookie-parser": "~1.4.3", - "diffie-hellman": "^5.0.3", - "express": "~4.16.3", - "express-session": "~1.15.6", - "express-static-gzip": "~1.1.3", - "glob": "~7.1.3", - "graceful-fs": "~4.1.15", - "ipaddr.js": "~1.8.0", - "js-yaml": "~3.13.1", - "keyring_js": "~1.1.0", - "lodash": "~4.17.21", - "mkdirp": "~0.5.1", - "mocha": "~8.4.0", - "ncp": "~2.0.0", - "node-forge": "~1.3.0", - "normalize-url": "~7.0.0", - "require-from-string": "~2.0.2", - "rimraf": "~2.6.3", - "semver": "~5.5.1", - "swagger-parser": "~10.0.3", - "typescript": "2.7.1", - "ws": "^6.2.2", - "yaml": "~1.10.2", - "yauzl": "~2.10.0" - } - } } } diff --git a/package.json b/package.json index ba40c9e2..f443f99e 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,6 @@ "test": "echo \"Warning: no test specified\" && exit 0" }, "dependencies": { - "zlux-server-framework": "file:../zlux-server-framework", - "mkdirp": "~0.5.1" + "zlux-server-framework": "file:../zlux-server-framework" } } From 369ec32d383d570446984e787b489c135587383e Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Fri, 5 Apr 2024 13:03:04 -0400 Subject: [PATCH 02/18] Fix defaults to allow attls Signed-off-by: 1000TurquoisePogs --- defaults/serverConfig/defaults.yaml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/defaults/serverConfig/defaults.yaml b/defaults/serverConfig/defaults.yaml index 53969eef..bddc7b63 100644 --- a/defaults/serverConfig/defaults.yaml +++ b/defaults/serverConfig/defaults.yaml @@ -18,6 +18,15 @@ components: debug: false node: hostname: "${{ function a(){ if (process.env.ZWE_INTERNAL_HOST) { return process.env.ZWE_INTERNAL_HOST; } else if (process.env.ZWE_haInstance_hostname) { return process.env.ZWE_haInstance_hostname; } else { return undefined; } }; a() }}" + http: "${{ function a() { + if (components['app-server'].zowe?.network?.server?.attls === true) { + return { 'port': components['app-server'].port || Number(7556)}; + } else if (zowe.network?.server?.attls === true) { + return { 'port': components['app-server'].port || Number(7556)}; + } else { + return undefined; + } }; + a() }}" https: ipAddresses: "${{ function a(){ let addresses; @@ -33,7 +42,11 @@ components: } else { return addresses } }; a() }}" port: "${{ function a(){ - if (process.env.ZWED_SERVER_HTTPS_PORT) { + if (components['app-server'].zowe?.server?.attls === true) { + return undefined; + } else if (zowe?.server?.attls === true) { + return undefined; + } else if (process.env.ZWED_SERVER_HTTPS_PORT) { return Number(process.env.ZWED_SERVER_HTTPS_PORT); } else if (components['app-server'].port) { return components['app-server'].port; From 7498e3a3c29352e2259f6ba1c20bd5393a81a879 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Mon, 8 Apr 2024 13:54:05 -0400 Subject: [PATCH 03/18] Update zowe.server to zowe.network.server Signed-off-by: 1000TurquoisePogs --- defaults/serverConfig/defaults.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/defaults/serverConfig/defaults.yaml b/defaults/serverConfig/defaults.yaml index bddc7b63..660e276e 100644 --- a/defaults/serverConfig/defaults.yaml +++ b/defaults/serverConfig/defaults.yaml @@ -42,9 +42,9 @@ components: } else { return addresses } }; a() }}" port: "${{ function a(){ - if (components['app-server'].zowe?.server?.attls === true) { + if (components['app-server'].zowe?.network?.server?.attls === true) { return undefined; - } else if (zowe?.server?.attls === true) { + } else if (zowe?.network?.server?.attls === true) { return undefined; } else if (process.env.ZWED_SERVER_HTTPS_PORT) { return Number(process.env.ZWED_SERVER_HTTPS_PORT); From 386c51076ae2e2ebdc2428f7f3f0abd89ec802a7 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Mon, 8 Apr 2024 13:56:56 -0400 Subject: [PATCH 04/18] server.attls to server.tls.attls Signed-off-by: 1000TurquoisePogs --- defaults/serverConfig/defaults.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/defaults/serverConfig/defaults.yaml b/defaults/serverConfig/defaults.yaml index 660e276e..e665265d 100644 --- a/defaults/serverConfig/defaults.yaml +++ b/defaults/serverConfig/defaults.yaml @@ -19,9 +19,9 @@ components: node: hostname: "${{ function a(){ if (process.env.ZWE_INTERNAL_HOST) { return process.env.ZWE_INTERNAL_HOST; } else if (process.env.ZWE_haInstance_hostname) { return process.env.ZWE_haInstance_hostname; } else { return undefined; } }; a() }}" http: "${{ function a() { - if (components['app-server'].zowe?.network?.server?.attls === true) { + if (components['app-server'].zowe?.network?.server?.tls?.attls === true) { return { 'port': components['app-server'].port || Number(7556)}; - } else if (zowe.network?.server?.attls === true) { + } else if (zowe.network?.server?.tls?.attls === true) { return { 'port': components['app-server'].port || Number(7556)}; } else { return undefined; @@ -42,9 +42,9 @@ components: } else { return addresses } }; a() }}" port: "${{ function a(){ - if (components['app-server'].zowe?.network?.server?.attls === true) { + if (components['app-server'].zowe?.network?.server?.tls?.attls === true) { return undefined; - } else if (zowe?.network?.server?.attls === true) { + } else if (zowe?.network?.server?.tls?.attls === true) { return undefined; } else if (process.env.ZWED_SERVER_HTTPS_PORT) { return Number(process.env.ZWED_SERVER_HTTPS_PORT); From fc336e4299c841f5a9363920ef6a41984ec8caf8 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Tue, 28 May 2024 13:38:55 +0200 Subject: [PATCH 05/18] Update CHANGELOG.md Signed-off-by: 1000TurquoisePogs --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e39541b..13c32faf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,9 @@ All notable changes to the Zlux App Server package will be documented in this file. +## v2.17.0 +- Enhancement: app-server can now use Zowe's standardized and simplified AT-TLS configuration simply by toggling `zowe.network.server.tls.attls: true` or `components.app-server.zowe.network.server.tls.attls: true`. If you wish to control client tls separately from server tls, you can also use `zowe.network.client.tls.attls` or `components.app-server.zowe.network.client.tls.attls`. (#300) + ## v2.16.0 - Bugfix: Removed message saying node not found prior to discovery of node. Now, you will only get an error message if node is not found after lookup in NODE_HOME. From c97f44132a6a5589bb0cc3b57b7c68c46702bac2 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Fri, 14 Jun 2024 11:25:29 +0200 Subject: [PATCH 06/18] Update zss.apiml_static_reg.yaml.template Signed-off-by: 1000TurquoisePogs --- zss.apiml_static_reg.yaml.template | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/zss.apiml_static_reg.yaml.template b/zss.apiml_static_reg.yaml.template index b8eedebb..576568f4 100644 --- a/zss.apiml_static_reg.yaml.template +++ b/zss.apiml_static_reg.yaml.template @@ -4,7 +4,7 @@ services: description: 'Zowe System Services is an HTTPS and Websocket server that makes it easy to have secure, powerful web APIs backed by low-level z/OS constructs. It contains services for essential z/OS abilities such as working with files, datasets, and ESMs, but is also extensible by REST and Websocket "Dataservices" which are optionally present in App Framework "Plugins".' catalogUiTileId: zss instanceBaseUrls: - - ${ZSS_PROTOCOL}://${ZWED_agent_host}:${ZSS_PORT}/ + - https://${ZWED_agent_host}:${ZSS_PORT}/ homePageRelativeUrl: routedServices: - gatewayUrl: api/v1 @@ -17,4 +17,4 @@ services: catalogUiTiles: zss: title: Zowe System Services (ZSS) - description: Zowe System Services is an HTTPS and Websocket server that makes it easy to have secure, powerful web APIs backed by low-level z/OS constructs. \ No newline at end of file + description: Zowe System Services is an HTTPS and Websocket server that makes it easy to have secure, powerful web APIs backed by low-level z/OS constructs. From 7904ce10fec12663e803780937b252d017e25c3e Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Fri, 14 Jun 2024 11:27:22 +0200 Subject: [PATCH 07/18] Remove conditional setup of https Signed-off-by: 1000TurquoisePogs --- bin/configure.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/bin/configure.sh b/bin/configure.sh index 499eaac1..6baada1e 100755 --- a/bin/configure.sh +++ b/bin/configure.sh @@ -28,11 +28,6 @@ if [ "$ZWE_components_gateway_enabled" = "true" ]; then if [ "${ZWE_RUN_ON_ZOS}" != "true" ]; then zss_def_template="zss.apiml_static_reg.yaml.template" export ZSS_PORT="${ZWE_components_zss_port}" - if [ "${ZWE_components_zss_tls}" != "false" ]; then - export ZSS_PROTOCOL=https - else - export ZSS_PROTOCOL=http - fi if [ -n "${ZWE_STATIC_DEFINITIONS_DIR}" ]; then zss_registration_yaml=${ZWE_STATIC_DEFINITIONS_DIR}/zss.apiml_static_reg_yaml_template.${ZWE_CLI_PARAMETER_HA_INSTANCE}.yml @@ -43,7 +38,6 @@ if [ "$ZWE_components_gateway_enabled" = "true" ]; then fi unset ZSS_PORT - unset ZSS_PROTOCOL fi fi fi From 535986f5defb35a657fd0f4f4d9c662ec87254bc Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Fri, 14 Jun 2024 11:28:32 +0200 Subject: [PATCH 08/18] Update CHANGELOG.md Signed-off-by: 1000TurquoisePogs --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13c32faf..a751b02d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to the Zlux App Server package will be documented in this file. ## v2.17.0 -- Enhancement: app-server can now use Zowe's standardized and simplified AT-TLS configuration simply by toggling `zowe.network.server.tls.attls: true` or `components.app-server.zowe.network.server.tls.attls: true`. If you wish to control client tls separately from server tls, you can also use `zowe.network.client.tls.attls` or `components.app-server.zowe.network.client.tls.attls`. (#300) +- Enhancement: app-server can now use Zowe's standardized and simplified AT-TLS configuration simply by toggling `zowe.network.server.tls.attls: true` or `components.app-server.zowe.network.server.tls.attls: true`. If you wish to control client tls separately from server tls, you can also use `zowe.network.client.tls.attls` or `components.app-server.zowe.network.client.tls.attls`. (#300) (#302) ## v2.16.0 - Bugfix: Removed message saying node not found prior to discovery of node. Now, you will only get an error message if node is not found after lookup in NODE_HOME. From ae69a66642ae4b27fb71be8339760e3680b678fc Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Fri, 14 Jun 2024 11:31:46 +0200 Subject: [PATCH 09/18] Update start.sh Signed-off-by: 1000TurquoisePogs --- bin/start.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/bin/start.sh b/bin/start.sh index c8d5510d..6c24f83d 100755 --- a/bin/start.sh +++ b/bin/start.sh @@ -95,12 +95,6 @@ if [ "$ZWE_components_app_server_dns_lookupOrder" = "ipv6" ]; then ZLUX_DNS_ORDER="--dns-result-order=verbatim" fi -# not all versions of node support the above (14.18+ generally) so we can just try it to see what happens. -v4_check=$(${NODE_BIN} ${ZLUX_DNS_ORDER} -e "console.log('success');") -if [ "${v4_check}" != "success" ]; then - ZLUX_DNS_ORDER= -fi - if [ -z "${ZWED_FLAGS}" ]; then ZWED_FLAGS="${ZLUX_DNS_ORDER} --harmony " fi From c474f27e0c8e148c455c2b7aad4d72c7694be85e Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Fri, 14 Jun 2024 11:37:31 +0200 Subject: [PATCH 10/18] Update CHANGELOG.md Signed-off-by: 1000TurquoisePogs --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a751b02d..c14492c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ All notable changes to the Zlux App Server package will be documented in this file. ## v2.17.0 -- Enhancement: app-server can now use Zowe's standardized and simplified AT-TLS configuration simply by toggling `zowe.network.server.tls.attls: true` or `components.app-server.zowe.network.server.tls.attls: true`. If you wish to control client tls separately from server tls, you can also use `zowe.network.client.tls.attls` or `components.app-server.zowe.network.client.tls.attls`. (#300) (#302) +- Enhancement: app-server can now use Zowe's standardized and simplified AT-TLS configuration simply by toggling `zowe.network.server.tls.attls: true` or `components.app-server.zowe.network.server.tls.attls: true`. If you wish to control client tls separately from server tls, you can also use `zowe.network.client.tls.attls` or `components.app-server.zowe.network.client.tls.attls`. (#300) (#303) ## v2.16.0 - Bugfix: Removed message saying node not found prior to discovery of node. Now, you will only get an error message if node is not found after lookup in NODE_HOME. From 126645af029da15616cc3389d644af7e01457a90 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Fri, 14 Jun 2024 11:37:38 +0200 Subject: [PATCH 11/18] Update CHANGELOG.md Signed-off-by: 1000TurquoisePogs --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 13c32faf..5cdafe4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to the Zlux App Server package will be documented in this fi ## v2.17.0 - Enhancement: app-server can now use Zowe's standardized and simplified AT-TLS configuration simply by toggling `zowe.network.server.tls.attls: true` or `components.app-server.zowe.network.server.tls.attls: true`. If you wish to control client tls separately from server tls, you can also use `zowe.network.client.tls.attls` or `components.app-server.zowe.network.client.tls.attls`. (#300) +- Enhancement: Remove dns check specific to node 14 and below to reduce startup time. Node 14 has not been supported since september 2023. (#304) ## v2.16.0 - Bugfix: Removed message saying node not found prior to discovery of node. Now, you will only get an error message if node is not found after lookup in NODE_HOME. From 8e7e97205ccc798cfe4f78a86a4545ff3b83033f Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Fri, 14 Jun 2024 12:07:00 +0200 Subject: [PATCH 12/18] Delete plugins-init.sh as it is also no longer used Signed-off-by: 1000TurquoisePogs --- CHANGELOG.md | 1 + bin/configure.sh | 9 -- bin/init/plugins-init.js | 221 ------------------------------------ bin/init/plugins-init.sh | 51 --------- lib/initInstance.js | 47 +++++++- lib/initUtils.js | 239 ++++++++++++++++++++++++++++++++++++++- 6 files changed, 282 insertions(+), 286 deletions(-) delete mode 100644 bin/init/plugins-init.js delete mode 100644 bin/init/plugins-init.sh diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cdafe4a..849d2ee1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to the Zlux App Server package will be documented in this file. ## v2.17.0 +- Enhancement: The app-server configure stage performance increased due to combining two seperate processes in this stage (plugins-init.js and initInstance.js) into one. (#304) - Enhancement: app-server can now use Zowe's standardized and simplified AT-TLS configuration simply by toggling `zowe.network.server.tls.attls: true` or `components.app-server.zowe.network.server.tls.attls: true`. If you wish to control client tls separately from server tls, you can also use `zowe.network.client.tls.attls` or `components.app-server.zowe.network.client.tls.attls`. (#300) - Enhancement: Remove dns check specific to node 14 and below to reduce startup time. Node 14 has not been supported since september 2023. (#304) diff --git a/bin/configure.sh b/bin/configure.sh index 499eaac1..c8819c8a 100755 --- a/bin/configure.sh +++ b/bin/configure.sh @@ -52,12 +52,3 @@ fi . ./init/node-init.sh cd ../lib CONFIG_FILE=$ZWE_CLI_PARAMETER_CONFIG $NODE_BIN initInstance.js - -cd ${COMPONENT_HOME}/share/zlux-app-server/bin/init -if [ "${ZWE_components_app_server_zowe_useConfigmgr}" = "false" ]; then - . ./plugins-init.sh -elif [ "${ZWE_zowe_useConfigmgr}" = "true" ]; then - _CEE_RUNOPTS="XPLINK(ON),HEAPPOOLS(OFF)" ${ZWE_zowe_runtimeDirectory}/bin/utils/configmgr -script "${ZWE_zowe_runtimeDirectory}/components/app-server/share/zlux-app-server/bin/init/plugins-init.js" -else - . ./plugins-init.sh -fi diff --git a/bin/init/plugins-init.js b/bin/init/plugins-init.js deleted file mode 100644 index d99e7de6..00000000 --- a/bin/init/plugins-init.js +++ /dev/null @@ -1,221 +0,0 @@ -/* - This program and the accompanying materials are - made available under the terms of the Eclipse Public License v2.0 which accompanies - this distribution, and is available at https://www.eclipse.org/legal/epl-v20.html - - SPDX-License-Identifier: EPL-2.0 - - Copyright Contributors to the Zowe Project. -*/ - -import * as os from 'os'; -import * as zos from 'zos'; -import * as std from 'std'; -import * as xplatform from 'xplatform'; -import * as fs from '../../../../../../bin/libs/fs'; -import * as common from '../../../../../../bin/libs/common'; -import * as componentlib from '../../../../../../bin/libs/component'; -import { PathAPI as pathoid } from '../../../../../../bin/libs/pathoid'; - -common.printFormattedDebug("ZWED", "plugins-init", `Started plugins-init.js, platform=${os.platform}`); - -const runtimeDirectory=std.getenv('ZWE_zowe_runtimeDirectory'); -const extensionDirectory=std.getenv('ZWE_zowe_extensionDirectory'); -const workspaceDirectory=std.getenv('ZWE_zowe_workspaceDirectory'); -const recognizerDirectory=workspaceDirectory+'/app-server/ZLUX/pluginStorage/org.zowe.zlux.ng2desktop/recognizers'; -const actionsDirectory=workspaceDirectory+'/app-server/ZLUX/pluginStorage/org.zowe.zlux.ng2desktop/actions'; - -const installedComponentsEnv=std.getenv('ZWE_INSTALLED_COMPONENTS'); -const installedComponents = installedComponentsEnv ? installedComponentsEnv.split(',') : null; - -const enabledComponentsEnv=std.getenv('ZWE_ENABLED_COMPONENTS'); -const enabledComponents = enabledComponentsEnv ? enabledComponentsEnv.split(',') : null; - -const pluginPointerDirectory = `${workspaceDirectory}/app-server/plugins`; - -function deleteFile(path) { - return os.remove(path); -} - -function registerPlugin(pluginPath, pluginDefinition) { - const pointerPath = `${pluginPointerDirectory}/${pluginDefinition.identifier}.json`; - let location, relativeTo; - if (pluginPath.startsWith(runtimeDirectory)) { - relativeTo = "$ZWE_zowe_runtimeDirectory"; - location = pluginPath.substring(runtimeDirectory.length); - if (location.startsWith('/')) { - location = location.substring(1); - } - - xplatform.storeFileUTF8(pointerPath, xplatform.AUTO_DETECT, JSON.stringify({ - "identifier": pluginDefinition.identifier, - "pluginLocation": location, - "relativeTo": relativeTo - }, null, 2)); - } else { - xplatform.storeFileUTF8(pointerPath, xplatform.AUTO_DETECT, JSON.stringify({ - "identifier": pluginDefinition.identifier, - "pluginLocation": pluginPath - }, null, 2)); - } - registerApp2App(pluginPath, pluginDefinition.identifier, pluginDefinition.pluginVersion); -} - - - -function registerApp2App(pluginDirectory, pluginId, pluginVersion) { - common.printFormattedDebug("ZWED", "plugins-init", `app2app for ${pluginId}`); - copyRecognizers(pluginDirectory, pluginId, pluginVersion); - copyActions(pluginDirectory, pluginId, pluginVersion); -} - -function deregisterPlugin(pluginDefinition) { - const filePath = `${pluginPointerDirectory}/${pluginDefinition.identifier}.json`; - if (fs.fileExists(filePath, true)) { - const rc = deleteFile(filePath); - if (rc !== 0) { - common.printFormattedError("ZWED", "plugins-init", `Could not deregister plugin ${pluginDefinition.identifier}, delete ${filePath} failed, error=${rc}`); - } - return rc !== 0; - } else { - return deregisterApp2App(pluginDefinition.identifier); - } -} - -function deregisterApp2App(appId) { - const actionPath = pathoid.join(actionsDirectory, appId); - if (fs.fileExists(actionPath, true)) { - const rc = deleteFile(actionPath); - if (rc !== 0) { - common.printFormattedError("ZWED", "plugins-init", `Could not deregister plugin ${appId}, delete ${actionPath} failed, error=${rc}`); - } - return rc === 0; - } - //TODO how to deregister recognizer? -} - -function copyRecognizers(appDir, appId, appVers) { - let recognizers; - let recognizersKeys; - let configRecognizers; - const pluginRecognizersLocation = pathoid.join(appDir, "config", "recognizers"); - - - if (fs.directoryExists(pluginRecognizersLocation)) { // Get recognizers in a plugin's appDir/config/xxx location - common.printFormattedDebug("ZWED", "plugins-init", `rec ${pluginRecognizersLocation} exists`); - fs.getFilesInDirectory(pluginRecognizersLocation).forEach(filename => { - const filepath = pathoid.resolve(pluginRecognizersLocation, filename); - const filepathConfig = pathoid.resolve(pathoid.join(recognizerDirectory, filename)); - - recognizers = JSON.parse(xplatform.loadFileUTF8(filepath, xplatform.AUTO_DETECT)).recognizers; - recognizersKeys = Object.keys(recognizers) - for (const key of recognizersKeys) { // Add metadata for plugin version & plugin identifier of origin (though objects don't have to be plugin specific) - recognizers[key].pluginVersion = appVers; - recognizers[key].pluginIdentifier = appId; - recognizers[key].key = appId + ":" + key + ":" + recognizers[key].id; // pluginid_that_provided_it:index(or_name)_in_that_provider:actionid - } - common.printFormattedDebug("ZWED", "plugins-init", `ZWED0301I Found ${filepath} in config for '${appId}'`); - common.printFormattedDebug("ZWED", "plugins-init", `Going to merge into ${filepathConfig}`); - try { // Get pre-existing recognizers in config, if any - configRecognizers = fs.fileExists(filepathConfig) ? JSON.parse(xplatform.loadFileUTF8(filepathConfig, xplatform.AUTO_DETECT)).recognizers : {}; - const configRecognizersKeys = Object.keys(configRecognizers); - for (const configKey of configRecognizersKeys) { // Traverse config recognizers - for (const key of recognizersKeys) { // Traverse plugin recognizers - if (configRecognizers[configKey].key && recognizers[key].key && configRecognizers[configKey].key == recognizers[key].key) { // TODO: Need to implement real keys for Recognizers - configRecognizers[configKey] = recognizers[key]; // Choose the recognizers originating from plugin - } - } - } - recognizers = Object.assign(configRecognizers, recognizers); // If found, combine the ones found in config with ones found in plugin - } catch (e) { - common.printFormattedError("ZWED", "plugins-init", `Error: Invalid JSON for ${filepathConfig}`); - } - - if (recognizers) { // Attempt to copy recognizers over to config location for Desktop access later - try { //TODO: Doing recognizers.recognizers is redundant. We may want to consider refactoring in the future - xplatform.storeFileUTF8(filepathConfig, xplatform.AUTO_DETECT, '{ "recognizers":' + JSON.stringify(recognizers) + '}'); - common.printFormattedInfo("ZWED", "plugins-init", "ZWED0294I Successfully loaded " + Object.keys(recognizers).length + " recognizers for '" + appId + "' into config at "+filepathConfig); - } catch (e) { - common.printFormattedError("ZWED", "plugins-init", `ZWED0177W Unable to load ${recognizers} for '${appId}' into config`); - } - } - - }); - } - common.printFormattedDebug("ZWED", "plugins-init", `Done rec`); -} - -function copyActions(appDir, appId, appVers) { - let actions; - let actionsKeys; - const pluginActionsLocation = pathoid.join(appDir, "config", "actions", appId); - - if (fs.fileExists(pluginActionsLocation)) { - common.printFormattedDebug("ZWED", "plugins-init", `act ${pluginActionsLocation} exists`); - try { // Get actions in a plugin's appDir/config/xxx location - actions = JSON.parse(xplatform.loadFileUTF8(pluginActionsLocation, xplatform.AUTO_DETECT)).actions; - actionsKeys = Object.keys(actions) - for (const key of actionsKeys) { // Add metadata for plugin version & plugin identifier of origin (though objects don't have to be plugin specific) - actions[key].pluginVersion = appVers; - actions[key].pluginIdentifier = appId; - } - common.printFormattedDebug("ZWED", "plugins-init", `ZWED0301I Found ${actions} in config for '${appId}'`); - } catch (e) { - common.printFormattedError("ZWED", "plugins-init", `Error: Malformed JSON in ${pluginActionsLocation}`); - } - - if (actions) { // Attempt to copy actions over to config location for Desktop access later - try { //TODO: Doing actions.actions is redundant. We may want to consider refactoring in the future - xplatform.storeFileUTF8(pathoid.join(actionsDirectory, appId), xplatform.AUTO_DETECT, '{ "actions":' + JSON.stringify(actions) + '}'); - common.printFormattedInfo("ZWED", "plugins-init", "ZWED0295I Successfully loaded " + actions.length + " actions for '" + appId + "' into config at "+pathoid.join(actionsDirectory, appId)); - } catch (e) { - common.printFormattedError("ZWED", "plugins-init", `ZWED0177W Unable to load ${actions} for '${appId}' into config`); - } - } - } - common.printFormattedDebug("ZWED", "plugins-init", `done act`); -} - - -if (!fs.directoryExists(pluginPointerDirectory, true)) { - const rc = os.mkdir(pluginPointerDirectory, 0o770); - if (rc < 0) { - common.printFormattedError("ZWED", "plugins-init", `Could not create pluginsDir=${pluginPointerDirectory}, err=${rc}`); - std.exit(2); - } -} - -common.printFormattedDebug("ZWED", "plugins-init", "Start iteration"); - -//A port of https://github.com/zowe/zlux-app-server/blob/v2.x/staging/bin/init/plugins-init.sh - -installedComponents.forEach(function(installedComponent) { - const componentDirectory = componentlib.findComponentDirectory(installedComponent); - if (componentDirectory) { - const enabled = enabledComponents.includes(installedComponent); - common.printFormattedDebug("ZWED", "plugins-init", `Checking plugins for component=${installedComponent}, enabled=${enabled}`); - - const manifest = componentlib.getManifest(componentDirectory); - if (manifest.appfwPlugins) { - manifest.appfwPlugins.forEach(function (manifestPluginRef) { - const path = manifestPluginRef.path; - const fullPath = `${componentDirectory}/${path}` - const pluginDefinition = componentlib.getPluginDefinition(fullPath); - if (pluginDefinition) { - if (enabled) { - common.printFormattedInfo("ZWED", "plugins-init", `Registering plugin ${fullPath}`); - registerPlugin(fullPath, pluginDefinition); - } else { - common.printFormattedDebug("ZWED", "plugins-init", `Deregistering plugin ${fullPath}`); - deregisterPlugin(pluginDefinition); - } - } else { - common.printFormattedError("ZWED", "plugins-init", `Skipping plugin at ${fullPath} due to pluginDefinition missing or invalid`); - } - }); - } - } else { - common.printFormattedError("ZWED", "plugins-init", `Warning: Could not remove app framework plugins for extension ${installedComponent} because its directory could not be found within ${extensionDirectory}`); - } -}); - diff --git a/bin/init/plugins-init.sh b/bin/init/plugins-init.sh deleted file mode 100644 index 24c0d414..00000000 --- a/bin/init/plugins-init.sh +++ /dev/null @@ -1,51 +0,0 @@ -# $1=whether to use nodejs or not for installing (affects app2app installation) -# $2=whether to check pc bit of zss services - -# ZWE_zowe_runtimeDirectory -# ZWE_zowe_extensionDirectory -# ZWE_INSTALLED_COMPONENTS=api-catalog,apiml-common-lib,app-server,caching-service,common-java-lib,discovery,explorer-jes,explorer-mvs,explorer-uss,files-api,gateway,jobs-api,launcher,metrics-service,zss,process-manager -# ZWE_ENABLED_COMPONENTS=api-catalog,app-server,caching-service,discovery,explorer-jes,explorer-mvs,explorer-uss,gateway,zss - -echo "Using runtime=${ZWE_zowe_runtimeDirectory} and extensions=${ZWE_zowe_extensionDirectory}" -echo "Checking installed=${ZWE_INSTALLED_COMPONENTS}" -echo "Checking enabled=${ZWE_ENABLED_COMPONENTS}" - -. ../utils/plugin-utils.sh - -plugins_dir=$(getPluginsDir) - -for installed_component in $(echo "${ZWE_INSTALLED_COMPONENTS}" | sed "s/,/ /g"); do - extension_path=$(find_component_directory ${installed_component}) - if [ -d "${extension_path}" ]; then - is_enabled=false - for enabled_component in $(echo "${ZWE_ENABLED_COMPONENTS}" | sed "s/,/ /g"); do - if [ "${enabled_component}" = "${installed_component}" ]; then - is_enabled=true - fi - done - - echo "Checking plugins for component=${installed_component}, enabled=${is_enabled}" - - # HERE: can we do this without any nodejs? probably no, but lets use the zowe install packaging utils. - # init-plugins.js $is_enabled "${extension_path}" - - iterator=0 - plugin_folder=$(read_component_manifest "${extension_path}" .appfwPlugins.[${iterator}].path) - while [ -n "${plugin_folder}" ]; do - fullpath="$extension_path/${plugin_folder}" - if [ "$is_enabled" = "true" ]; then - echo "Registering plugin ${fullpath}" - # NOTE: relativeTo does not need to be handled here because this process occurs every start so the results should be "portable" by update on restart - - INSTALL_NO_NODE=$1 ../install-app.sh "$fullpath" "${plugins_dir}" - else - echo "Deregistering plugin ${fullpath}" - ../uninstall-app.sh "$fullpath" "${plugins_dir}" - fi - iterator=`expr $iterator + 1` - plugin_folder=$(read_component_manifest "${extension_path}" .appfwPlugins.[${iterator}].path) - done - else - echo "Warning: Could not remove app framework plugins for extension ${installed_component} because its directory could not be found within ${ZWE_zowe_extensionDirectory}" - fi -done diff --git a/lib/initInstance.js b/lib/initInstance.js index e9bed843..a6ea7647 100644 --- a/lib/initInstance.js +++ b/lib/initInstance.js @@ -10,6 +10,7 @@ const fs = require('fs'); const path = require('path'); +const YAML = require('yaml'); const argParser = require('../../zlux-server-framework/utils/argumentParser'); const mergeUtils = require('../../zlux-server-framework/utils/mergeUtils'); const yamlConfig = require('../../zlux-server-framework/utils/yamlConfig'); @@ -18,6 +19,7 @@ const initUtils = require('./initUtils'); const os = require('os'); const { execSync } = require('child_process'); +initUtils.printFormattedDebug(`Started initInstance.js, platform=${os.platform()}`); const haInstanceId = yamlConfig.getCurrentHaInstanceId(); let config = {}; @@ -148,13 +150,11 @@ if (siteStorage.length == 0 && instanceStorage.length == 0) { process.exit(1); } generateComponentJson() - process.exit(0); }); } else { execSync("cp -r "+path.join(config.productDir, 'ZLUX', 'pluginStorage')+" "+path.join(config.instanceDir, 'ZLUX')); execSync("chmod -R 770 "+instancePluginStorage); generateComponentJson() - process.exit(0); } } @@ -198,3 +198,46 @@ if (siteStorage.length == 0 && instanceStorage.length == 0) { // } catch (e) { // //skip process // } + +const RUNTIME_DIRECTORY=process.env.ZWE_zowe_runtimeDirectory; +const EXTENSION_DIRECTORY=process.env.ZWE_zowe_extensionDirectory; + +const INSTALLED_COMPONENTS_ENV=process.env.ZWE_INSTALLED_COMPONENTS; +const INSTALLED_COMPONENTS = INSTALLED_COMPONENTS_ENV ? INSTALLED_COMPONENTS_ENV.split(',') : []; + +const ENABLED_COMPONENTS_ENV=process.env.ZWE_ENABLED_COMPONENTS; +const ENABLED_COMPONENTS = ENABLED_COMPONENTS_ENV ? ENABLED_COMPONENTS_ENV.split(',') : []; + + +initUtils.printFormattedDebug("Start component iteration"); + +INSTALLED_COMPONENTS.forEach(function(installedComponent) { + const componentDirectory = initUtils.findComponentDirectory(RUNTIME_DIRECTORY, EXTENSION_DIRECTORY, installedComponent); + if (componentDirectory) { + const enabled = ENABLED_COMPONENTS.includes(installedComponent); + initUtils.printFormattedDebug(`Checking plugins for component=${installedComponent}, enabled=${enabled}`); + + const manifest = YAML.parse(fs.readFileSync(initUtils.getManifestPath(componentDirectory), 'utf8')); + if (manifest.appfwPlugins) { + manifest.appfwPlugins.forEach(function (manifestPluginRef) { + const path = manifestPluginRef.path; + const fullPath = `${componentDirectory}/${path}` + const pluginDefinition = `${fullPath}/pluginDefinition.json`; + if (pluginDefinition && initUtils.fileExists(pluginDefinition)) { + if (enabled) { + initUtils.printFormattedInfo(`Registering plugin ${fullPath}`); + initUtils.registerPlugin(fullPath, pluginDefinition, config.pluginsDir, actionsPluginStorage, recognizersPluginStorage, RUNTIME_DIRECTORY); + } else { + initUtils.printFormattedDebug(`Deregistering plugin ${fullPath}`); + initUtils.deregisterPlugin(pluginDefinition, config.pluginsDir, actionsPluginStorage); + } + } else { + initUtils.printFormattedError(`Skipping plugin at ${fullPath} due to pluginDefinition missing or invalid`); + } + }); + } + } else { + initUtils.printFormattedError(`Warning: Could not remove app framework plugins for extension ${installedComponent} because its directory could not be found within ${EXTENSION_DIRECTORY}`); + } +}); + diff --git a/lib/initUtils.js b/lib/initUtils.js index 8399c410..c3e26fcf 100644 --- a/lib/initUtils.js +++ b/lib/initUtils.js @@ -9,12 +9,18 @@ */ const fs = require('fs'); +const os = require('os'); const path = require('path'); const ZLUX_ROOT_DIR = path.join(__dirname, '..'); const DEFAULT_PLUGINS_DIR = path.join(ZLUX_ROOT_DIR, 'defaults', 'plugins'); -module.exports.FOLDER_MODE = 0o0770; -module.exports.FILE_MODE = 0o0770; +const USERNAME = os.userInfo().username; +const LOG_LEVEL = process.env.ZWE_PRIVATE_LOG_LEVEL_ZWELS; +const PRINT_DEBUG = LOG_LEVEL == 'DEBUG' || LOG_LEVEL == 'TRACE'; +const FILE_MODE = 0o770; +const FOLDER_MODE = 0o770; +module.exports.FOLDER_MODE = FOLDER_MODE; +module.exports.FILE_MODE = FILE_MODE; module.exports.registerBundledPlugins = function(destination, configDestination, oldPlugins, filePermission) { @@ -25,10 +31,237 @@ module.exports.registerBundledPlugins = function(destination, configDestination, }); } + + +function printFormattedMessage(level, message) { + var d = new Date(); +// d.setTime(d.getTime()-Logger.offsetMs); + var dateString = d.toISOString(); + dateString = dateString.substring(0,dateString.length-1).replace('T',' '); + console.log(`${dateString} ${USERNAME} ${level} (plugins-init) ${message}`); +} + +function printFormattedError(message) { + printFormattedMessage('ERROR', message); +} +module.exports.printFormattedError = printFormattedError; + +function printFormattedInfo(message) { + printFormattedMessage('INFO', message); +} +module.exports.printFormattedInfo = printFormattedInfo; + + +function printFormattedDebug(message) { + if (PRINT_DEBUG) { + printFormattedMessage('DEBUG', message); + } +} +module.exports.printFormattedDebug = printFormattedDebug; + +function getManifestPath(componentDir) { + if (fileExists(`${componentDir}/manifest.yaml`)) { + return `${componentDir}/manifest.yaml`; + } else if (fileExists(`${componentDir}/manifest.yml`)) { + return `${componentDir}/manifest.yml`; + } else if (fileExists(`${componentDir}/manifest.yaml`)) { + return `${componentDir}/manifest.json`; + } + return undefined; +} +module.exports.getManifestPath = getManifestPath; + +function findComponentDirectory(runtimeDirectory, extensionDirectory, componentId) { + if (directoryExists(`${runtimeDirectory}/components/${componentId}`)) { + return `${runtimeDirectory}/components/${componentId}`; + } else if (extensionDirectory && directoryExists(`${extensionDirectory}/${componentId}`)) { + return `${extensionDirectory}/${componentId}`; + } + return undefined; +} +module.exports.findComponentDirectory = findComponentDirectory; + + +function directoryExists(directory) { + try { + let stat = fs.statSync(directory); + if (stat) { + return stat.isDirectory(); + } else { + return false; + } + } catch (e) { + return false; + } +} +module.exports.directoryExits = directoryExists; + +function fileExists(file) { + try { + let stat = fs.statSync(file); + if (stat) { + return !stat.isDirectory(); + } else { + return false; + } + } catch (e) { + return false; + } +} +module.exports.fileExists = fileExists; + + +function deregisterPlugin(pluginDefinition, pluginPointerDirectory, actionsDirectory) { + const filePath = `${pluginPointerDirectory}/${pluginDefinition.identifier}.json`; + if (fileExists(filePath, true)) { + try { + fs.unlinkSync(filePath); + } catch (e) { + printFormattedError(`Could not deregister plugin ${pluginDefinition.identifier}, delete ${filePath} failed, error=${e}`); + } + return true; + } else { + return deregisterApp2App(pluginDefinition.identifier, actionsDirectory); + } +} +module.exports.deregisterPlugin = deregisterPlugin; + +function deregisterApp2App(appId, actionsDirectory) { + const actionPath = path.join(actionsDirectory, appId); + if (fileExists(actionPath, true)) { + try { + fs.unlinkSync(actionPath); + } catch (e) { + printFormattedError(`Could not deregister plugin ${appId}, delete ${actionPath} failed, error=${e}`); + } + return true; + } + //TODO how to deregister recognizer? +} +module.exports.deregisterApp2App = deregisterApp2App; + + + +function registerApp2App(pluginDirectory, pluginId, pluginVersion, pluginActionsLocation, pluginRecognizersLocation) { + printFormattedDebug(`app2app for ${pluginId}`); + copyRecognizers(pluginDirectory, pluginId, pluginVersion, pluginRecognizersLocation); + copyActions(pluginDirectory, pluginId, pluginVersion, pluginActionsLocation); +} +module.exports.registerApp2App = registerApp2App; + +function copyRecognizers(appDir, appId, appVers, pluginRecognizersLocation) { + let recognizers; + let recognizersKeys; + let configRecognizers; + const pluginRecognizersLocation = path.join(appDir, "config", "recognizers"); + + + if (directoryExists(pluginRecognizersLocation)) { // Get recognizers in a plugin's appDir/config/xxx location + printFormattedDebug(`rec ${pluginRecognizersLocation} exists`); + fs.getFilesInDirectory(pluginRecognizersLocation).forEach(filename => { + const filepath = path.resolve(pluginRecognizersLocation, filename); + const filepathConfig = path.resolve(path.join(recognizerDirectory, filename)); + + recognizers = JSON.parse(fs.readFileSync(filepath, 'utf8')).recognizers; + recognizersKeys = Object.keys(recognizers) + for (const key of recognizersKeys) { // Add metadata for plugin version & plugin identifier of origin (though objects don't have to be plugin specific) + recognizers[key].pluginVersion = appVers; + recognizers[key].pluginIdentifier = appId; + recognizers[key].key = appId + ":" + key + ":" + recognizers[key].id; // pluginid_that_provided_it:index(or_name)_in_that_provider:actionid + } + printFormattedDebug(`ZWED0301I Found ${filepath} in config for '${appId}'`); + printFormattedDebug(`Going to merge into ${filepathConfig}`); + try { // Get pre-existing recognizers in config, if any + configRecognizers = fileExists(filepathConfig) ? JSON.parse(fs.readFileSync(filepathConfig, 'utf8')).recognizers : {}; + const configRecognizersKeys = Object.keys(configRecognizers); + for (const configKey of configRecognizersKeys) { // Traverse config recognizers + for (const key of recognizersKeys) { // Traverse plugin recognizers + if (configRecognizers[configKey].key && recognizers[key].key && configRecognizers[configKey].key == recognizers[key].key) { // TODO: Need to implement real keys for Recognizers + configRecognizers[configKey] = recognizers[key]; // Choose the recognizers originating from plugin + } + } + } + recognizers = Object.assign(configRecognizers, recognizers); // If found, combine the ones found in config with ones found in plugin + } catch (e) { + printFormattedError(`Error: Invalid JSON for ${filepathConfig}`); + } + + if (recognizers) { // Attempt to copy recognizers over to config location for Desktop access later + try { //TODO: Doing recognizers.recognizers is redundant. We may want to consider refactoring in the future + fs.writeFileSync(filepathConfig, '{ "recognizers":' + JSON.stringify(recognizers) + '}', + {encoding: 'utf8', mode: FILE_MODE}); + console.log("ZWED", "plugins-init", "ZWED0294I Successfully loaded " + Object.keys(recognizers).length + " recognizers for '" + appId + "' into config at "+filepathConfig); + } catch (e) { + printFormattedError(`ZWED0177W Unable to load ${recognizers} for '${appId}' into config`); + } + } + + }); + } + printFormattedDebug(`Done rec`); +} + +function copyActions(appDir, appId, appVers, pluginActionsLocation) { + let actions; + let actionsKeys; + const pluginActionsLocation = path.join(appDir, "config", "actions", appId); + + if (fileExists(pluginActionsLocation)) { + printFormattedDebug(`act ${pluginActionsLocation} exists`); + try { // Get actions in a plugin's appDir/config/xxx location + actions = JSON.parse(fs.readFileSync(pluginActionsLocation, 'utf8')).actions; + actionsKeys = Object.keys(actions) + for (const key of actionsKeys) { // Add metadata for plugin version & plugin identifier of origin (though objects don't have to be plugin specific) + actions[key].pluginVersion = appVers; + actions[key].pluginIdentifier = appId; + } + printFormattedDebug(`ZWED0301I Found ${actions} in config for '${appId}'`); + } catch (e) { + printFormattedError(`Error: Malformed JSON in ${pluginActionsLocation}`); + } + + if (actions) { // Attempt to copy actions over to config location for Desktop access later + try { //TODO: Doing actions.actions is redundant. We may want to consider refactoring in the future + fs.writeFileSync(path.join(actionsDirectory, appId), '{ "actions":' + JSON.stringify(actions) + '}', + {encoding: 'utf8', mode: FILE_MODE}); + printFormattedInfo("ZWED0295I Successfully loaded " + actions.length + " actions for '" + appId + "' into config at "+path.join(actionsDirectory, appId)); + } catch (e) { + printFormattedError(`ZWED0177W Unable to load ${actions} for '${appId}' into config`); + } + } + } + printFormattedDebug(`done act`); +} + + +function registerPlugin(pluginPath, pluginDefinition, pluginPointerDirectory, pluginActionsLocation, pluginRecognizersLocation, runtimeDirectory) { + const pointerPath = `${pluginPointerDirectory}/${pluginDefinition.identifier}.json`; + let location, relativeTo; + if (pluginPath.startsWith(runtimeDirectory)) { + relativeTo = "$ZWE_zowe_runtimeDirectory"; + location = pluginPath.substring(runtimeDirectory.length); + if (location.startsWith('/')) { + location = location.substring(1); + } + + fs.writeFileSync(pointerPath, JSON.stringify({ + "identifier": pluginDefinition.identifier, + "pluginLocation": location, + "relativeTo": relativeTo + }, null, 2), {encoding: 'utf8', mode: FILE_MODE}); + } else { + fs.writeFileSync(pointerPath, JSON.stringify({ + "identifier": pluginDefinition.identifier, + "pluginLocation": pluginPath + }, null, 2), {encoding: 'utf8', mode: FILE_MODE}); + } + registerApp2App(pluginPath, pluginDefinition.identifier, pluginDefinition.pluginVersion, pluginActionsLocation, pluginRecognizersLocation); +} +module.exports.registerPlugin = registerPlugin; + /** @param pluginID Identifier of a plugin @param outputDir plugins directory where plugin identifier file will be placed - @param filePermission permission of new file if created @param oldPlugins array of plugins seen at destination prior to creation of new plugins @throws filenotfound error if plugin requested is not a bundled plugin. */ From f553328a3fb6e0accfae900b4da9310cd64e829a Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Fri, 14 Jun 2024 12:16:30 +0200 Subject: [PATCH 13/18] Fix missing comment Signed-off-by: 1000TurquoisePogs --- lib/initUtils.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/initUtils.js b/lib/initUtils.js index c3e26fcf..a4960b1e 100644 --- a/lib/initUtils.js +++ b/lib/initUtils.js @@ -262,6 +262,7 @@ module.exports.registerPlugin = registerPlugin; /** @param pluginID Identifier of a plugin @param outputDir plugins directory where plugin identifier file will be placed + @param filePermission permission of new file if created @param oldPlugins array of plugins seen at destination prior to creation of new plugins @throws filenotfound error if plugin requested is not a bundled plugin. */ From 3bf60e8153e768f3f98f8a3bc3ac44f621c37f25 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Fri, 14 Jun 2024 12:29:16 +0200 Subject: [PATCH 14/18] Add YAML library for reading. This is already used in zlux-server-framework Signed-off-by: 1000TurquoisePogs --- package-lock.json | 56 ++++++++++++++++++++++++++++++++++++++++++++++- package.json | 1 + 2 files changed, 56 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index e22b38c5..c57f16ef 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8,10 +8,64 @@ "name": "zlux-app-server", "version": "1.0.0", "dependencies": { + "yaml": "~2.4.5", "zlux-server-framework": "file:../zlux-server-framework" } }, - "../zlux-server-framework": {}, + "../zlux-server-framework": { + "version": "0.0.0-zlux.version.replacement", + "license": "EPL-2.0", + "dependencies": { + "@rocketsoftware/eureka-js-client": "~4.5.7", + "@rocketsoftware/express-ws": "^5.0.0", + "accept-language-parser": "~1.5.0", + "axios": "^1.6.8", + "bluebird": "3.7.2", + "body-parser": "~1.20.2", + "cookie-parser": "~1.4.6", + "diffie-hellman": "^5.0.3", + "express": "~4.19.2", + "express-session": "~1.18.0", + "express-static-gzip": "~2.1.7", + "graceful-fs": "~4.2.11", + "ipaddr.js": "~2.1.0", + "node-forge": "~1.3.1", + "normalize-url": "~7.0.0", + "require-from-string": "~2.0.2", + "semver": "~7.6.0", + "swagger-parser": "~10.0.3", + "ws": "^6.2.2", + "yaml": "~2.4.1", + "yauzl": "~3.1.2" + }, + "devDependencies": { + "@types/connect": "3.4.35", + "@types/express": "4.17.17", + "@types/express-serve-static-core": "4.17.35", + "@types/mime": "3.0.1", + "@types/node": "~16.18.0", + "@types/qs": "6.9.3", + "chai": "~4.2.0", + "chai-http": "~4.2.0", + "mocha": "~10.2.0", + "typescript": "~5.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2", + "keyring_js": "~1.1.0" + } + }, + "node_modules/yaml": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/zlux-server-framework": { "resolved": "../zlux-server-framework", "link": true diff --git a/package.json b/package.json index f443f99e..e86efb5b 100644 --- a/package.json +++ b/package.json @@ -10,6 +10,7 @@ "test": "echo \"Warning: no test specified\" && exit 0" }, "dependencies": { + "yaml": "~2.4.5", "zlux-server-framework": "file:../zlux-server-framework" } } From db2f7341b007dfbb5356d7d36a4027d3756c68d3 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Fri, 14 Jun 2024 14:34:57 +0200 Subject: [PATCH 15/18] Fix wrong variable names after testing Signed-off-by: 1000TurquoisePogs --- lib/initInstance.js | 5 +++-- lib/initUtils.js | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/lib/initInstance.js b/lib/initInstance.js index a6ea7647..0477775a 100644 --- a/lib/initInstance.js +++ b/lib/initInstance.js @@ -224,12 +224,13 @@ INSTALLED_COMPONENTS.forEach(function(installedComponent) { const fullPath = `${componentDirectory}/${path}` const pluginDefinition = `${fullPath}/pluginDefinition.json`; if (pluginDefinition && initUtils.fileExists(pluginDefinition)) { + const pluginDefinitionJson = JSON.parse(fs.readFileSync(pluginDefinition, 'utf8')); if (enabled) { initUtils.printFormattedInfo(`Registering plugin ${fullPath}`); - initUtils.registerPlugin(fullPath, pluginDefinition, config.pluginsDir, actionsPluginStorage, recognizersPluginStorage, RUNTIME_DIRECTORY); + initUtils.registerPlugin(fullPath, pluginDefinitionJson, config.pluginsDir, actionsPluginStorage, recognizersPluginStorage, RUNTIME_DIRECTORY); } else { initUtils.printFormattedDebug(`Deregistering plugin ${fullPath}`); - initUtils.deregisterPlugin(pluginDefinition, config.pluginsDir, actionsPluginStorage); + initUtils.deregisterPlugin(pluginDefinitionJson, config.pluginsDir, actionsPluginStorage); } } else { initUtils.printFormattedError(`Skipping plugin at ${fullPath} due to pluginDefinition missing or invalid`); diff --git a/lib/initUtils.js b/lib/initUtils.js index a4960b1e..b3c8d7cb 100644 --- a/lib/initUtils.js +++ b/lib/initUtils.js @@ -149,7 +149,7 @@ function registerApp2App(pluginDirectory, pluginId, pluginVersion, pluginActions } module.exports.registerApp2App = registerApp2App; -function copyRecognizers(appDir, appId, appVers, pluginRecognizersLocation) { +function copyRecognizers(appDir, appId, appVers, recognizerDirectory) { let recognizers; let recognizersKeys; let configRecognizers; @@ -201,7 +201,7 @@ function copyRecognizers(appDir, appId, appVers, pluginRecognizersLocation) { printFormattedDebug(`Done rec`); } -function copyActions(appDir, appId, appVers, pluginActionsLocation) { +function copyActions(appDir, appId, appVers, actionsDirectory) { let actions; let actionsKeys; const pluginActionsLocation = path.join(appDir, "config", "actions", appId); From 7e1d67d339dd7563a1b2149f96d236ef6aa42035 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Thu, 20 Jun 2024 13:22:15 +0200 Subject: [PATCH 16/18] Fix missing getFilesInDirectory function by using readdirSync Signed-off-by: 1000TurquoisePogs --- lib/initUtils.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/initUtils.js b/lib/initUtils.js index b3c8d7cb..4161e966 100644 --- a/lib/initUtils.js +++ b/lib/initUtils.js @@ -158,7 +158,9 @@ function copyRecognizers(appDir, appId, appVers, recognizerDirectory) { if (directoryExists(pluginRecognizersLocation)) { // Get recognizers in a plugin's appDir/config/xxx location printFormattedDebug(`rec ${pluginRecognizersLocation} exists`); - fs.getFilesInDirectory(pluginRecognizersLocation).forEach(filename => { + fs.readdirSync(pluginRecognizersLocation, {withFileTypes: true}).filter(statObj=> statObj.isFile()) + .forEach((statObj) => { + const filename = statObj.name; const filepath = path.resolve(pluginRecognizersLocation, filename); const filepathConfig = path.resolve(path.join(recognizerDirectory, filename)); From 2522f2675ef198588a40c410b4c229e5f33d7321 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Thu, 20 Jun 2024 14:00:52 +0200 Subject: [PATCH 17/18] Handle mkdirp throwing eexist Signed-off-by: 1000TurquoisePogs --- lib/initInstance.js | 18 +++++++++--------- lib/initUtils.js | 14 ++++++++++++-- 2 files changed, 21 insertions(+), 11 deletions(-) diff --git a/lib/initInstance.js b/lib/initInstance.js index 0477775a..d261f708 100644 --- a/lib/initInstance.js +++ b/lib/initInstance.js @@ -44,43 +44,43 @@ const versionLocation = path.join(destination, 'component.json'); config.productDir = path.join(__dirname, '..', 'defaults'); //Begin generate any missing folders -fs.mkdirSync(destination, {mode: initUtils.FOLDER_MODE, recursive: true}); +initUtils.mkdirp(destination, initUtils.FOLDER_MODE); if (!config.siteDir) { config.siteDir = path.join(destination, 'site'); } const sitePluginStorage = path.join(config.siteDir, 'ZLUX', 'pluginStorage'); -fs.mkdirSync(sitePluginStorage, {mode: initUtils.FOLDER_MODE, recursive: true}); +initUtils.mkdirp(sitePluginStorage, initUtils.FOLDER_MODE); if (!config.instanceDir) { config.instanceDir = destination; } const instancePluginStorage = path.join(config.instanceDir, 'ZLUX', 'pluginStorage'); -fs.mkdirSync(instancePluginStorage, {mode: initUtils.FOLDER_MODE, recursive: true}); +initUtils.mkdirp(instancePluginStorage, initUtils.FOLDER_MODE); const recognizersPluginStorage = path.join(config.instanceDir, 'ZLUX/pluginStorage', 'org.zowe.zlux.ng2desktop/recognizers'); -fs.mkdirSync(recognizersPluginStorage, {mode: initUtils.FOLDER_MODE, recursive: true}); +initUtils.mkdirp(recognizersPluginStorage, initUtils.FOLDER_MODE); const actionsPluginStorage = path.join(config.instanceDir, 'ZLUX/pluginStorage/org.zowe.zlux.ng2desktop', 'actions'); -fs.mkdirSync(actionsPluginStorage, {mode: initUtils.FOLDER_MODE, recursive: true}); +initUtils.mkdirp(actionsPluginStorage, initUtils.FOLDER_MODE); const instanceConfig = path.join(config.instanceDir, 'serverConfig'); //750 specifically, to keep server config secure -fs.mkdirSync(instanceConfig, {mode: 0o0750}); +initUtils.mkdirp(instanceConfig, 0o0750}); if (!config.groupsDir) { config.groupsDir = path.join(config.instanceDir, 'groups'); } -fs.mkdirSync(config.groupsDir, {mode: initUtils.FOLDER_MODE, recursive: true}); +initUtils.mkdirp(config.groupsDir, initUtils.FOLDER_MODE); if (!config.usersDir) { config.usersDir = path.join(config.instanceDir, 'users'); } -fs.mkdirSync(config.usersDir, {mode: initUtils.FOLDER_MODE, recursive: true}); +initUtils.mkdirp(config.usersDir, initUtils.FOLDER_MODE); if (!config.pluginsDir) { config.pluginsDir = path.join(destination, 'plugins'); } -fs.mkdirSync(config.pluginsDir, {mode: initUtils.FOLDER_MODE, recursive: true}); +initUtils.mkdirp(config.pluginsDir, initUtils.FOLDER_MODE); function generateComponentJson() { let componentJsonContent; diff --git a/lib/initUtils.js b/lib/initUtils.js index 4161e966..3fc7f579 100644 --- a/lib/initUtils.js +++ b/lib/initUtils.js @@ -31,6 +31,16 @@ module.exports.registerBundledPlugins = function(destination, configDestination, }); } +function mkdirp(directory, mode) { + try { + fs.mkdirSync(directory, {mode: mode, recursive: true}); + } catch (e) { + if (e.code != 'EEXIST') { + throw e; + } + } +} +module.exports.mkdirp = mkdirp; function printFormattedMessage(level, message) { @@ -313,7 +323,7 @@ module.exports.registerBundledPlugin = registerBundledPlugin; module.exports.setTerminalDefaults = function(configDestination, instanceItems) { if (instanceItems.indexOf('org.zowe.terminal.vt.json') != -1) { let defaultConfigDir = path.join(configDestination,'org.zowe.terminal.vt','sessions'); - fs.mkdirSync(defaultConfigDir, {recursive: true}); + mkdirp(defaultConfigDir); try { fs.writeFileSync(path.join(defaultConfigDir,'_defaultVT.json'), JSON.stringify({host:process.env['ZWED_SSH_HOST'] ? process.env['ZWED_SSH_HOST'] : "", @@ -329,7 +339,7 @@ module.exports.setTerminalDefaults = function(configDestination, instanceItems) security = process.env['ZWED_TN3270_SECURITY']; } let defaultConfigDir = path.join(configDestination,'org.zowe.terminal.tn3270','sessions'); - fs.mkdirSync(defaultConfigDir, {recursive: true}); + mkdirp(defaultConfigDir); try { let tn3270Json = {host:process.env['ZWED_TN3270_HOST'] ? process.env['ZWED_TN3270_HOST'] : "", port: process.env['ZWED_TN3270_PORT'] ? process.env['ZWED_TN3270_PORT'] : 23, From fb79d6019d57e91c93a430db605b664d51721ab9 Mon Sep 17 00:00:00 2001 From: 1000TurquoisePogs Date: Fri, 21 Jun 2024 14:10:36 +0200 Subject: [PATCH 18/18] Fix syntax error on mkdirp call Signed-off-by: 1000TurquoisePogs --- lib/initInstance.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/initInstance.js b/lib/initInstance.js index d261f708..04080d9e 100644 --- a/lib/initInstance.js +++ b/lib/initInstance.js @@ -64,7 +64,7 @@ initUtils.mkdirp(actionsPluginStorage, initUtils.FOLDER_MODE); const instanceConfig = path.join(config.instanceDir, 'serverConfig'); //750 specifically, to keep server config secure -initUtils.mkdirp(instanceConfig, 0o0750}); +initUtils.mkdirp(instanceConfig, 0o0750); if (!config.groupsDir) { config.groupsDir = path.join(config.instanceDir, 'groups');