From 09b4df5af72847f25fa3ce855682113b7e75145d Mon Sep 17 00:00:00 2001 From: siva kumar Date: Wed, 6 Jan 2021 17:26:24 +0530 Subject: [PATCH] [ACA-4227] [APS] Create a script to check Process Services Management plugin status before running e2e tests (#6486) * [ACA-4227] Create a generic script to check plugin status before running e2e tests by plugin name * * Added governace env check * * Added AAE plugin check * * Updated script * small improvements, add uiName parameter for the command * * Fixed comments * * Moved check-plugin script in the common place * * Added table format to show plugin status Co-authored-by: adomi --- lib/cli/scripts/check-plugin-env.ts | 56 +++++++++++++++ lib/cli/scripts/plugins/check-env.ts | 58 +++++++++++++++ lib/cli/scripts/plugins/plugin-config.ts | 44 ++++++++++++ lib/cli/scripts/plugins/plugin-model.ts | 12 ++++ .../process-automation-check-plugin.ts | 55 +++++++++++++++ .../plugins/process-automation-health.ts | 70 +++++++++++++++++++ .../plugins/process-service-check-plugin.ts | 54 ++++++++++++++ .../plugins/process-services-health.ts | 64 +++++++++++++++++ 8 files changed, 413 insertions(+) create mode 100644 lib/cli/scripts/check-plugin-env.ts create mode 100644 lib/cli/scripts/plugins/check-env.ts create mode 100644 lib/cli/scripts/plugins/plugin-config.ts create mode 100644 lib/cli/scripts/plugins/plugin-model.ts create mode 100644 lib/cli/scripts/plugins/process-automation-check-plugin.ts create mode 100644 lib/cli/scripts/plugins/process-automation-health.ts create mode 100644 lib/cli/scripts/plugins/process-service-check-plugin.ts create mode 100644 lib/cli/scripts/plugins/process-services-health.ts diff --git a/lib/cli/scripts/check-plugin-env.ts b/lib/cli/scripts/check-plugin-env.ts new file mode 100644 index 0000000000..f2be860be0 --- /dev/null +++ b/lib/cli/scripts/check-plugin-env.ts @@ -0,0 +1,56 @@ +import { PluginTarget } from './plugins/plugin-model'; +import { CheckEnv } from './plugins/check-env'; +import program = require('commander'); +import { ProcessServiceCheckPlugin } from './plugins/process-service-check-plugin'; +import { ProcessAutomationCheckPlugin } from './plugins/process-automation-check-plugin'; + +let pluginEnv; + +export default async function main(_args: string[]) { + program + .version('0.1.0') + .option('--host [type]', 'Remote environment host') + .option('--pluginName [type]', 'pluginName ') + .option('--appName [type]', 'appName ') + .option('-p, --password [type]', 'password ') + .option('-u, --username [type]', 'username ') + .option('--ui, --uiName [type]', 'uiName') + .parse(process.argv); + + pluginEnv = new CheckEnv(program.host, program.username, program.password); + await pluginEnv.checkEnv(); + + if (program.pluginName === PluginTarget.processService) { + await checkProcessServicesPlugin(); + } + + if (program.pluginName === PluginTarget.processAutomation) { + await checkProcessAutomationPlugin(); + } +} + +async function checkProcessServicesPlugin() { + const processServiceCheckPlugin = new ProcessServiceCheckPlugin( + { + host: program.host, + name: PluginTarget.processService, + appName: null, + uiName: null + }, + pluginEnv.alfrescoJsApi + ); + await processServiceCheckPlugin.checkProcessServicesPlugin(); +} + +async function checkProcessAutomationPlugin() { + const processAutomationCheckPlugin = new ProcessAutomationCheckPlugin( + { + host: program.host, + name: PluginTarget.processAutomation, + appName: program.appName, + uiName: program.uiName + }, + pluginEnv.alfrescoJsApi + ); + await processAutomationCheckPlugin.checkProcessAutomationPlugin(); +} diff --git a/lib/cli/scripts/plugins/check-env.ts b/lib/cli/scripts/plugins/check-env.ts new file mode 100644 index 0000000000..c7bb7084cd --- /dev/null +++ b/lib/cli/scripts/plugins/check-env.ts @@ -0,0 +1,58 @@ +import { logger } from './../logger'; +import alfrescoApi = require('@alfresco/js-api'); + +export class CheckEnv { + _alfrescoJsApi: any; + TIMEOUT = 6000; + MAX_RETRY = 10; + counter = 0; + + constructor( + private host: string, + private username: string, + private password: string + ) {} + + async checkEnv() { + try { + this.alfrescoJsApi = new alfrescoApi.AlfrescoApiCompatibility( { + provider: 'ALL', + hostBpm: this.host, + hostEcm: this.host, + authType: 'OAUTH', + oauth2: { + host: `${this.host}/auth/realms/alfresco`, + clientId: 'alfresco', + scope: 'openid' + } + }); + await this.alfrescoJsApi.login(this.username, this.password); + } catch (e) { + logger.error('Login error environment down or inaccessible'); + this.counter++; + if (this.MAX_RETRY === this.counter) { + logger.error('Give up'); + process.exit(1); + } else { + logger.error( + `Retry in 1 minute at main();tempt N ${this.counter}` + ); + this.sleep(this.TIMEOUT); + this.checkEnv(); + } + } + } + + public get alfrescoJsApi() { + return this._alfrescoJsApi; + } + + public set alfrescoJsApi(alfrescoJsApi: any) { + this._alfrescoJsApi = alfrescoJsApi; + } + + sleep(delay) { + const start = new Date().getTime(); + while (new Date().getTime() < start + delay) {} + } +} diff --git a/lib/cli/scripts/plugins/plugin-config.ts b/lib/cli/scripts/plugins/plugin-config.ts new file mode 100644 index 0000000000..d4de367300 --- /dev/null +++ b/lib/cli/scripts/plugins/plugin-config.ts @@ -0,0 +1,44 @@ +import { PluginInterface } from './plugin-model'; +import { logger } from '../logger'; + +export class PluginConfiguration { + constructor( + private plugInInfo: PluginInterface, + private alfrescoJsApi: any + ) {} + + async getAppConfig(url: string) { + return this.callCustomApi(url); + } + + async callCustomApi(url: string) { + const pathParams = {}, + headerParams = {}, + formParams = {}, + bodyParam = {}, + queryParams = {}, + contentTypes = ['application/json'], + accepts = ['application/json']; + try { + const response = await this.alfrescoJsApi.oauth2Auth.callCustomApi( + url, + 'GET', + pathParams, + queryParams, + headerParams, + formParams, + bodyParam, + contentTypes, + accepts + ); + + return response; + } catch (error) { + logger.error( + `${this.plugInInfo.host} is not reachable error: `, + error + ); + return {}; + } + } +} diff --git a/lib/cli/scripts/plugins/plugin-model.ts b/lib/cli/scripts/plugins/plugin-model.ts new file mode 100644 index 0000000000..414159670e --- /dev/null +++ b/lib/cli/scripts/plugins/plugin-model.ts @@ -0,0 +1,12 @@ +export enum PluginTarget { + processService = 'processService', + processAutomation = 'processAutomation', + governance = 'governance' +} + +export interface PluginInterface { + name: string; + host: string; + appName: string; + uiName: string; +} diff --git a/lib/cli/scripts/plugins/process-automation-check-plugin.ts b/lib/cli/scripts/plugins/process-automation-check-plugin.ts new file mode 100644 index 0000000000..5d6b0bf48b --- /dev/null +++ b/lib/cli/scripts/plugins/process-automation-check-plugin.ts @@ -0,0 +1,55 @@ +import { PluginInterface } from './plugin-model'; +import { logger } from '../logger'; +import { ProcessAutomationHealth } from './process-automation-health'; + +export class ProcessAutomationCheckPlugin { + processAutomationHealth: ProcessAutomationHealth; + + constructor( + private plugInInfo: PluginInterface, + private alfrescoJsApi: any + ) { + this.processAutomationHealth = new ProcessAutomationHealth( + this.plugInInfo, + this.alfrescoJsApi + ); + } + + async checkProcessAutomationPlugin() { + let pluginStatus; + try { + const isPluginEnabled = await this.processAutomationHealth.isPluginEnabledFromAppConfiguration(); + const isBackendActive = await this.processAutomationHealth.checkBackendHealth(); + + if (isPluginEnabled && isBackendActive) { + logger.info( + `The plugin ${ + this.plugInInfo.name + } has been correctly configured` + ); + + pluginStatus = [{ PluginName: this.plugInInfo.name, Status: 'Active', BE: 'Enabled', FE: 'Enabled' }]; + console.table(pluginStatus); + } else { + this.logConfigurationError(); + pluginStatus = [{ PluginName: this.plugInInfo.name, Status: 'Inactive', BE: isBackendActive ? 'Enabled' : 'Disabled', FE: isPluginEnabled ? 'Enabled' : 'Disabled' }]; + console.table(pluginStatus); + process.exit(1); + } + } catch (e) { + this.logConfigurationError(e); + pluginStatus = [{ PluginName: this.plugInInfo.name, Status: 'Inactive', BE: 'Disabled', FE: 'Disabled' }]; + console.table(pluginStatus); + process.exit(1); + } + } + + private logConfigurationError(error?: any) { + logger.error( + `The plugin ${ + this.plugInInfo.name + } has not been correctly configured`, + error + ); + } +} diff --git a/lib/cli/scripts/plugins/process-automation-health.ts b/lib/cli/scripts/plugins/process-automation-health.ts new file mode 100644 index 0000000000..77681639f0 --- /dev/null +++ b/lib/cli/scripts/plugins/process-automation-health.ts @@ -0,0 +1,70 @@ +import { PluginInterface } from './plugin-model'; +import { logger } from '../logger'; +import { PluginConfiguration } from './plugin-config'; + +export class ProcessAutomationHealth { + config: PluginConfiguration; + + constructor( + private plugInInfo: PluginInterface, + private alfrescoJsApi: any + ) { + this.config = new PluginConfiguration( + this.plugInInfo, + this.alfrescoJsApi + ); + } + + async isPluginEnabledFromAppConfiguration() { + try { + const url = `${this.plugInInfo.host}/${this.plugInInfo.appName}/ui/${this.plugInInfo.uiName}/app.config.json`; + const appConfig = await this.config.getAppConfig(url); + let isEnabled = true; + if (appConfig && appConfig.plugins && appConfig.plugins[this.plugInInfo.name]) { + logger.info( + `The plugin ${ + this.plugInInfo.name + } has been correctly configured in app.config.json` + ); + } else { + this.logConfigurationError(); + isEnabled = false; + } + + return isEnabled; + } catch (error) { + this.logConfigurationError(error); + return false; + } + } + + async checkBackendHealth() { + const url = `${this.plugInInfo.host}/${this.plugInInfo.appName}/rb/actuator/health`; + let isBackendActive = true; + try { + const response = await this.config.callCustomApi(url); + if (response.status === 'UP') { + logger.info(`${this.plugInInfo.host} is UP!`); + } else { + logger.error(`${this.plugInInfo.host} is DOWN `); + isBackendActive = false; + } + return isBackendActive; + } catch (error) { + logger.error( + `${this.plugInInfo.host} is not reachable error: `, + error + ); + return false; + } + } + + private logConfigurationError(error?: any) { + logger.error( + `The plugin ${ + this.plugInInfo.name + } has not been correctly configured in app.config.json`, + error + ); + } +} diff --git a/lib/cli/scripts/plugins/process-service-check-plugin.ts b/lib/cli/scripts/plugins/process-service-check-plugin.ts new file mode 100644 index 0000000000..a1c4a80716 --- /dev/null +++ b/lib/cli/scripts/plugins/process-service-check-plugin.ts @@ -0,0 +1,54 @@ +import { PluginInterface } from './plugin-model'; +import { logger } from '../logger'; +import { ProcessServiceHealth } from './process-services-health'; + +export class ProcessServiceCheckPlugin { + processServiceHealth: ProcessServiceHealth; + + constructor( + private plugInInfo: PluginInterface, + private alfrescoJsApi: any + ) { + this.processServiceHealth = new ProcessServiceHealth( + this.plugInInfo, + this.alfrescoJsApi + ); + } + + async checkProcessServicesPlugin() { + let pluginStatus; + try { + const isPluginEnabled = await this.processServiceHealth.isPluginEnabledFromAppConfiguration(); + const isBackendActive = await this.processServiceHealth.checkBackendHealth(); + + if (isPluginEnabled && isBackendActive) { + logger.info( + `The plugin ${ + this.plugInInfo.name + } has been correctly configured` + ); + pluginStatus = [{ PluginName: this.plugInInfo.name, Status: `${'Active'}`, BE: 'Enabled', FE: 'Enabled' }]; + console.table(pluginStatus); + } else { + this.logConfigurationError(); + pluginStatus = [{ PluginName: this.plugInInfo.name, Status: 'Inactive', BE: isBackendActive ? 'Enabled' : 'Disabled', FE: isPluginEnabled ? 'Enabled' : 'Disabled' }]; + console.table(pluginStatus); + process.exit(1); + } + } catch (e) { + this.logConfigurationError(e); + pluginStatus = [{ PluginName: this.plugInInfo.name, Status: 'Inactive', BE: 'Disabled', FE: 'Disabled' }]; + console.table(pluginStatus); + process.exit(1); + } + } + + private logConfigurationError(error?: any) { + logger.error( + `The plugin ${ + this.plugInInfo.name + } has not been correctly configured`, + error + ); + } +} diff --git a/lib/cli/scripts/plugins/process-services-health.ts b/lib/cli/scripts/plugins/process-services-health.ts new file mode 100644 index 0000000000..8d379fe2ef --- /dev/null +++ b/lib/cli/scripts/plugins/process-services-health.ts @@ -0,0 +1,64 @@ +import { PluginInterface } from './plugin-model'; +import { logger } from '../logger'; +import { PluginConfiguration } from './plugin-config'; + +export class ProcessServiceHealth { + + config: PluginConfiguration; + + constructor(private plugInInfo: PluginInterface, private alfrescoJsApi: any) { + this.config = new PluginConfiguration(this.plugInInfo, this.alfrescoJsApi); + } + + async isPluginEnabledFromAppConfiguration() { + try { + const url = `${this.plugInInfo.host}/app.config.json`; + const appConfig = await this.config.getAppConfig(url); + let isEnabled = true; + if (appConfig && appConfig.plugins && appConfig.plugins[this.plugInInfo.name]) { + logger.info( + `The plugin ${ + this.plugInInfo.name + } has been correctly configured in app.config.json` + ); + } else { + this.logConfigurationError(); + return (isEnabled = false); + } + + return isEnabled; + } catch (error) { + this.logConfigurationError(error); + return false; + } + } + + async checkBackendHealth() { + try { + const systemProperties = await this.alfrescoJsApi.activiti.systemPropertiesApi.getProperties(); + let isBackendActive = true; + if (systemProperties) { + logger.info(`${this.plugInInfo.host} is UP!`); + } else { + logger.error(`${this.plugInInfo.host} is DOWN `); + isBackendActive = false; + } + return isBackendActive; + } catch (error) { + logger.error( + `${this.plugInInfo.host} is not reachable error: `, + error + ); + return false; + } + } + + private logConfigurationError(error?: any) { + logger.error( + `The plugin ${ + this.plugInInfo.name + } has not been correctly configured in app.config.json`, + error + ); + } +}