Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Validate appfw plugins schema during component install #3866

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
14 changes: 14 additions & 0 deletions bin/commands/components/install/extract/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`);
Expand Down
33 changes: 19 additions & 14 deletions bin/libs/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
Expand Down
Loading