diff --git a/CHANGELOG.md b/CHANGELOG.md index a08b716fe0..6485176d2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to the Zowe Installer will be documented in this file. ## `2.17.0` ## New features and enhancements +- Enhancement: `zwe components install` and `zwe components upgrade` now checks the schema validity of any application framework plugins present within a component, so that you will know better if a component is valid prior to running Zowe. [#3866](https://github.com/zowe/zowe-install-packaging/pull/3866) - Enhancement: Added zowe.network.server.tls.attls and zowe.network.client.tls.attls as booleans for controlling global or per-component way to tell Zowe servers that they should operate in a mode compatible with an AT-TLS setup. [#3463](https://github.com/zowe/zowe-install-packaging/pull/3463) ## `2.16.0` diff --git a/bin/commands/components/install/extract/index.ts b/bin/commands/components/install/extract/index.ts index 576a3f3c12..9a7685904d 100644 --- a/bin/commands/components/install/extract/index.ts +++ b/bin/commands/components/install/extract/index.ts @@ -150,6 +150,20 @@ export function execute(componentFile: string, autoEncoding?: string, upgrade?: common.printErrorAndExit(`Error ZWEL0167E: Cannot find component name from ${componentFile} package manifest`, undefined, 167); } common.printDebug(`- Component name found as ${componentName}`); + + // If the component has appfw plugins, their validity should be checked against appfw plugin schema. + // If invalid, the installation will exit with an error message. + if (manifest.appfwPlugins) { + manifest.appfwPlugins.forEach((appfwPlugin: {path: string})=> { + let result = component.getPluginDefinition(pathoid.resolve(tmpDir, appfwPlugin.path), true); + //Normally, getPluginDefinition would quit upon failure. But we want to cleanup the tmpDir before that. + // So, we pass true to allow it to continue, check for null, and then remove the tmpdir and exit if so. + if (result === null) { + fs.rmrf(tmpDir); + std.exit(1); + } + }); + } const destinationDir = pathoid.resolve(targetDir, componentName); const bkpDir = pathoid.resolve(targetDir, `${componentName}_zwebkp`); diff --git a/bin/libs/component.ts b/bin/libs/component.ts index ddf6eb3037..457a12364c 100644 --- a/bin/libs/component.ts +++ b/bin/libs/component.ts @@ -114,47 +114,52 @@ function showExceptions(e: any,depth: number): void { } } -export function getPluginDefinition(pluginRootPath:string) { +export function getPluginDefinition(pluginRootPath:string, continueOnFailure?: boolean) { const pluginDefinitionPath = `${pluginRootPath}/pluginDefinition.json`; + const configId = `appfwPlugin:${pluginRootPath}`; + + const printer = continueOnFailure ? common.printError : common.printErrorAndExit; if (fs.fileExists(pluginDefinitionPath)) { let status; - if ((status = CONFIG_MGR.addConfig(pluginRootPath))) { - common.printErrorAndExit(`Could not add config for ${pluginRootPath}, status=${status}`); + if ((status = CONFIG_MGR.addConfig(configId))) { + printer(`Could not add config for ${pluginRootPath}, status=${status}`); return null; } - if ((status = CONFIG_MGR.loadSchemas(pluginRootPath, PLUGIN_DEF_SCHEMAS))) { - common.printErrorAndExit(`Could not load schemas ${PLUGIN_DEF_SCHEMAS} for plugin ${pluginRootPath}, status=${status}`); + if ((status = CONFIG_MGR.loadSchemas(configId, PLUGIN_DEF_SCHEMAS))) { + printer(`Could not load schemas ${PLUGIN_DEF_SCHEMAS} for plugin ${pluginRootPath}, status=${status}`); return null; } - if ((status = CONFIG_MGR.setConfigPath(pluginRootPath, `FILE(${pluginDefinitionPath})`))) { - common.printErrorAndExit(`Could not set config path for ${pluginDefinitionPath}, status=${status}`); + if ((status = CONFIG_MGR.setConfigPath(configId, `FILE(${pluginDefinitionPath})`))) { + printer(`Could not set config path for ${pluginDefinitionPath}, status=${status}`); return null; } - if ((status = CONFIG_MGR.loadConfiguration(pluginRootPath))) { - common.printErrorAndExit(`Could not load config for ${pluginDefinitionPath}, status=${status}`); + if ((status = CONFIG_MGR.loadConfiguration(configId))) { + printer(`Could not load config for ${pluginDefinitionPath}, status=${status}`); return null; } - let validation = CONFIG_MGR.validate(pluginRootPath); + let validation = CONFIG_MGR.validate(configId); if (validation.ok){ if (validation.exceptionTree){ common.printError(`Validation of ${pluginDefinitionPath} against schema ${PLUGIN_DEF_SCHEMA_ID} found invalid JSON Schema data`); showExceptions(validation.exceptionTree, 0); - std.exit(1); + if (!continueOnFailure) { + std.exit(1); + } return null; } else { - return CONFIG_MGR.getConfigData(pluginRootPath); + return CONFIG_MGR.getConfigData(configId); } } else { - common.printErrorAndExit(`Error occurred on validation of ${pluginDefinitionPath} against schema ${PLUGIN_DEF_SCHEMA_ID} `); + printer(`Error occurred on validation of ${pluginDefinitionPath} against schema ${PLUGIN_DEF_SCHEMA_ID} `); return null; } } else { - common.printErrorAndExit(`Plugin at ${pluginRootPath} has no pluginDefinition.json`); + printer(`Plugin at ${pluginRootPath} has no pluginDefinition.json`); return null; } }