From 914376bb1db19d28067b93ffee4ed65ac1e78bc9 Mon Sep 17 00:00:00 2001 From: Remie Bolte Date: Fri, 13 Dec 2024 12:04:34 +0100 Subject: [PATCH] feat: add ability to restart cluster after app installation --- src/apt/helpers/getAppLicense.ts | 23 +++++ src/apt/helpers/getAptDirectory.ts | 2 +- src/apt/helpers/getHostLicense.ts | 2 +- src/apt/helpers/installApp.ts | 112 ++++++++++++++++++++----- src/apt/helpers/runLuceneTimingTest.ts | 10 ++- src/apt/helpers/runPerformanceTest.ts | 10 ++- src/apt/helpers/runScalabilityTest.ts | 10 ++- src/apt/messages.ts | 9 +- src/apt/performance.ts | 3 + src/apt/scalability.ts | 3 + src/commands/apt.ts | 14 +++- src/commands/install.ts | 12 ++- src/types/DCAPT.ts | 8 ++ src/types/Install.ts | 28 ++++++- 14 files changed, 215 insertions(+), 31 deletions(-) create mode 100644 src/apt/helpers/getAppLicense.ts diff --git a/src/apt/helpers/getAppLicense.ts b/src/apt/helpers/getAppLicense.ts new file mode 100644 index 0000000..c265abe --- /dev/null +++ b/src/apt/helpers/getAppLicense.ts @@ -0,0 +1,23 @@ +import { input } from '@inquirer/prompts'; +import { existsSync, readFileSync } from 'fs'; + +import { app3hour } from '../../helpers/licences' +import { provisioning } from '../messages'; + + +export const getAppLicense = (license?: string, force?: boolean) => { + + const appLicense = license && existsSync(license) ? readFileSync(license, 'utf8') : license; + + if (force) { + return appLicense || app3hour; + } + + console.log(provisioning.askForAppLicense); + + return input({ + message: `License`, + default: appLicense || app3hour, + required: true + }); +} \ No newline at end of file diff --git a/src/apt/helpers/getAptDirectory.ts b/src/apt/helpers/getAptDirectory.ts index 3e7b516..cfcfc92 100644 --- a/src/apt/helpers/getAptDirectory.ts +++ b/src/apt/helpers/getAptDirectory.ts @@ -7,7 +7,7 @@ import simpleGit from 'simple-git'; import { emptyLine } from '../messages'; -export const getAptDictory = async (cwd: string, mustUseDefaultConfiguration: boolean, force?: boolean) => { +export const getAptDictory = async (cwd?: string, mustUseDefaultConfiguration?: boolean, force?: boolean) => { // Translate common relative paths to absolute paths let result: string = cwd ? cwd.startsWith('~/') diff --git a/src/apt/helpers/getHostLicense.ts b/src/apt/helpers/getHostLicense.ts index 7c33ed3..a5fce37 100644 --- a/src/apt/helpers/getHostLicense.ts +++ b/src/apt/helpers/getHostLicense.ts @@ -14,7 +14,7 @@ export const getHostLicense = (product: TSupportedApplications, license?: string return productLicense || timebomb[product]; } - console.log(provisioning.askForLicense); + console.log(provisioning.askForHostLicense); return input({ message: `License`, diff --git a/src/apt/helpers/installApp.ts b/src/apt/helpers/installApp.ts index e8b24bf..0126804 100644 --- a/src/apt/helpers/installApp.ts +++ b/src/apt/helpers/installApp.ts @@ -6,8 +6,14 @@ import { createWriteStream, mkdirSync, rmSync } from 'fs'; import { homedir } from 'os'; import { join } from 'path'; -import { app3hour } from '../../helpers/licences'; import { registerLicense, uploadToUPM, waitForPluginToBeEnabled } from '../../helpers/upm'; +import { TInstallOptions } from '../../types/Install'; +import { getAppLicense } from './getAppLicense'; +import { getAptDictory } from './getAptDirectory'; +import { getAWSCredentials } from './getAWSCredentials'; +import { getEnvironmentName } from './getEnvironmentName'; +import { getProduct } from './getProduct'; +import { restartCluster } from './restartCluster'; const progressBar = new SingleBar({ format: ' [{bar}] {percentage}% | ETA: {eta_formatted}m', @@ -50,18 +56,25 @@ const download = async (addonKey: string) => { return tmpFile; } -export const installApp = async (baseUrl: string, appKey?: string, license: string = app3hour, username: string = 'admin', password: string = 'admin', force?: boolean) => { +export const installApp = async (options: TInstallOptions) => { + + // Set default value for username/password + const username = options.username || 'admin'; + const password = options.password || 'admin'; // If we are in non-interactive mode, we will download it from MPAC - if (force) { + if (options.force) { // In order to do so, we need an appkey. If this is not provided, throw a hissy fit - if (!appKey) { + if (!options.appKey) { throw new Error('Failed to automatically install app into cluster, `appKey` was not provided'); } + // Get the app license + const appLicense = await getAppLicense(options.license, options.force); + // Download the file from MPAC - const file = await download(appKey); + const file = await download(options.appKey); let count = 0; let timerId = null; @@ -72,10 +85,10 @@ export const installApp = async (baseUrl: string, appKey?: string, license: stri if (count === 0) { console.log(` - Installing the app (${appKey}) into the cluster using the Universal Plugin Manager REST API`); + Installing the app (${options.appKey}) into the cluster using the Universal Plugin Manager REST API`); } else { console.log(` - Retrying installation of the app (${appKey}) into the cluster using the Universal Plugin Manager REST API (attempt ${count + 1})`); + Retrying installation of the app (${options.appKey}) into the cluster using the Universal Plugin Manager REST API (attempt ${count + 1})`); } // Show a progress bar @@ -83,19 +96,48 @@ export const installApp = async (baseUrl: string, appKey?: string, license: stri timerId = setInterval(() => progressBar.increment(), 1000); // Upload it into the cluster using the UPM REST API - const isInstalled = await uploadToUPM(baseUrl, file, username, password, false); + const isInstalled = await uploadToUPM(options.baseUrl, file, username, password, false); if (!isInstalled) { throw new Error('Failed to install app into the cluster using the Universal Plugin Manager REST API'); } + // Check if we need to restart the application container + if (options.restartAfterInstall) { + + // For restarts, the product option is required + if (!options.product) { + console.log(' Failed to restart application, required option `product` is missing'); + + // For restarts, the environment option is required + } else if (!options.environment) { + console.log(' Failed to restart application, required option `product` is missing'); + + // Ok, good to go! + } else { + // Oh right, we also need DCAPT in order to be able to restart the cluster + const cwd = await getAptDictory(options.cwd, false, options.force); + + // We are now going to restart the cluster and hope for the best + console.log(` Restarting ${options.product} to ensure app installation`); + await restartCluster({ + cwd, + product: options.product, + environment: options.environment, + aws_access_key_id: options.aws_access_key_id, + aws_secret_access_key: options.aws_secret_access_key, + force: options.force + }); + } + } + // Wait for the plugin to be enabled - const isEnabled = await waitForPluginToBeEnabled(appKey, baseUrl, username, password, false); + const isEnabled = await waitForPluginToBeEnabled(options.appKey, options.baseUrl, username, password, false); if (!isEnabled) { throw new Error('The app could not be enabled on the cluster, please refer to the application log files for more information'); } // Register the license (use the 3 hour timebomb in non-interactive mode) - const isLicensed = await registerLicense(appKey, license, baseUrl, username, password, false); + const isLicensed = await registerLicense(options.appKey, appLicense, options.baseUrl, username, password, false); if (!isLicensed) { throw new Error('The license could not be applied for the app on the cluster, please refer to the application log files for more information'); } @@ -123,7 +165,7 @@ export const installApp = async (baseUrl: string, appKey?: string, license: stri rmSync(file, { force: true }); // Tell them we succeeded - console.log(`✔ Finished installing the app (${appKey})`); + console.log(`✔ Finished installing the app (${options.appKey})`); // If we're in interactive mode, let's be nice } else { @@ -150,16 +192,12 @@ export const installApp = async (baseUrl: string, appKey?: string, license: stri // Ask them nicely for the app key const addonKey = await input({ message: 'Please provide the key of the app to be installed', - default: appKey, + default: options.appKey, required: true }); // Ask them nicely for the app license to be used - const appLicense = await input({ - message: `License`, - default: license, - required: true - }); + const appLicense = await getAppLicense(options.license, options.force); // Ask them nicely for the username const adminUsername = await input({ @@ -174,6 +212,11 @@ export const installApp = async (baseUrl: string, appKey?: string, license: stri validate: item => typeof item === 'string' && item.length > 0 }); + // Ask them nicely if we need to restart the application + const restartAfterInstall = await confirm({ + message: 'Restart the host application after installation?', + }); + // Tell them we are starting console.log(` Installing the app (${addonKey}) into the cluster using the Universal Plugin Manager REST API`); @@ -186,19 +229,46 @@ export const installApp = async (baseUrl: string, appKey?: string, license: stri const file = await download(addonKey); // Upload it into the cluster using the UPM REST API - const isInstalled = await uploadToUPM(baseUrl, file, adminUsername, adminPassword, false); + const isInstalled = await uploadToUPM(options.baseUrl, file, adminUsername, adminPassword, false); if (!isInstalled) { throw new Error('Failed to install app into the cluster using the Universal Plugin Manager REST API'); } + // Check if we need to restart the application container + if (restartAfterInstall) { + + // Ask them nicely for the host product + const product = options.product || await getProduct(); + + // Ask for the AWS credentials + const [ aws_access_key_id, aws_secret_access_key ] = await getAWSCredentials(product, options.force); + + // Ask for the environment name + const environment = options.environment || await getEnvironmentName(); + + // Oh right, we also need DCAPT in order to be able to restart the cluster + const cwd = await getAptDictory(options.cwd, false, options.force); + + // We are now going to restart the cluster and hope for the best + console.log(` Restarting ${options.product} to ensure app installation`); + await restartCluster({ + cwd, + product: product, + environment: environment, + aws_access_key_id: aws_access_key_id, + aws_secret_access_key: aws_secret_access_key, + force: options.force + }); + } + // Wait for the plugin to be enabled - const isEnabled = await waitForPluginToBeEnabled(addonKey, baseUrl, adminUsername, adminPassword, false); + const isEnabled = await waitForPluginToBeEnabled(addonKey, options.baseUrl, adminUsername, adminPassword, false); if (!isEnabled) { throw new Error('The app could not be enabled on the cluster, please refer to the application log files for more information'); } // Register the provided license - const isLicensed = await registerLicense(addonKey, appLicense, baseUrl, adminUsername, adminPassword, false); + const isLicensed = await registerLicense(addonKey, appLicense, options.baseUrl, adminUsername, adminPassword, false); if (!isLicensed) { throw new Error('The license could not be applied for the app on the cluster, please refer to the application log files for more information'); } @@ -221,7 +291,7 @@ export const installApp = async (baseUrl: string, appKey?: string, license: stri You can now install the app manually into the cluster. Please go to the following page: - ${baseUrl}/plugins/servlet/upm?source=side_nav_manage_addons + ${options.baseUrl}/plugins/servlet/upm?source=side_nav_manage_addons `); // Make them grovel diff --git a/src/apt/helpers/runLuceneTimingTest.ts b/src/apt/helpers/runLuceneTimingTest.ts index bd90e2c..9066738 100644 --- a/src/apt/helpers/runLuceneTimingTest.ts +++ b/src/apt/helpers/runLuceneTimingTest.ts @@ -56,7 +56,15 @@ export const runLuceneTimingTest = async (stage: TPerformanceTestTypes, options: const baseUrl = options.baseUrl || await getClusterURL(cwd, options.product); // Install the app into the cluster - await installApp(baseUrl, options.appKey, options.appLicense, 'admin', 'admin', options.force); + await installApp({ + baseUrl, + appKey: options.appKey, + license: options.appLicense, + username: 'admin', + password: 'admin', + restartAfterInstall: options.restartAfterInstall, + force: options.force + }); // Inform the user that we will now start the Lucene index test console.log(messages.startTest); diff --git a/src/apt/helpers/runPerformanceTest.ts b/src/apt/helpers/runPerformanceTest.ts index 160180c..1a583a6 100644 --- a/src/apt/helpers/runPerformanceTest.ts +++ b/src/apt/helpers/runPerformanceTest.ts @@ -108,7 +108,15 @@ export const runPerformanceTest = async (stage: TPerformanceTestTypes, options: if (stage === 'regression') { // Install the app into the cluster - await installApp(baseUrl, options.appKey, options.appLicense, 'admin', 'admin', options.force); + await installApp({ + baseUrl, + appKey: options.appKey, + license: options.appLicense, + username: 'admin', + password: 'admin', + restartAfterInstall: options.restartAfterInstall, + force: options.force + }); } diff --git a/src/apt/helpers/runScalabilityTest.ts b/src/apt/helpers/runScalabilityTest.ts index 9ffaf5c..aaebe55 100644 --- a/src/apt/helpers/runScalabilityTest.ts +++ b/src/apt/helpers/runScalabilityTest.ts @@ -92,7 +92,15 @@ export const runScalabilityTest = async (stage: TScalabilityTestTypes, options: const baseUrl = await getClusterURL(cwd, options.product); // Install the app into the cluster - await installApp(baseUrl, options.appKey, options.appLicense, 'admin', 'admin', options.force); + await installApp({ + baseUrl, + appKey: options.appKey, + license: options.appLicense, + username: 'admin', + password: 'admin', + restartAfterInstall: options.restartAfterInstall, + force: options.force + }); // Allow users to set a different test duration (for validation purposes) const duration = await getDuration(options.force); diff --git a/src/apt/messages.ts b/src/apt/messages.ts index cce5329..96d203f 100644 --- a/src/apt/messages.ts +++ b/src/apt/messages.ts @@ -116,13 +116,20 @@ export const provisioning = { This will allow you to create multiple clusters (i.e. for different host products) and to identify which cluster to use during testing & teardown. `, - askForLicense: ` + askForHostLicense: ` The host product requires a valid license. By default we use the 72h developer license provided by Atlassian. If you need a more extensive license, you can generate an evaluation license from my.atlassian.com or ask Atlassian Marketplace Developer Support for a test license. `, + askForAppLicense: ` +The app requires a valid license. + +By default we use the 3 hour timebomb license provided by Atlassian. If you need a more extensive license, +you can generate an evaluation license from my.atlassian.com or ask Atlassian Marketplace Developer Support for a test license. +`, + ready: ` We have now gathered all the information required to provision the cluster. diff --git a/src/apt/performance.ts b/src/apt/performance.ts index 3b665df..8407849 100644 --- a/src/apt/performance.ts +++ b/src/apt/performance.ts @@ -47,6 +47,7 @@ export const Performance = async (options: TAPTPerformanceTestArgs) => { aws_secret_access_key, license, appKey: options.appKey, + restartAfterInstall: options.restartAfterInstall, force: options.force }, Run1); @@ -64,6 +65,7 @@ export const Performance = async (options: TAPTPerformanceTestArgs) => { aws_secret_access_key, license, appKey: options.appKey, + restartAfterInstall: options.restartAfterInstall, force: options.force }, LuceneTimingTest) @@ -81,6 +83,7 @@ export const Performance = async (options: TAPTPerformanceTestArgs) => { aws_secret_access_key, license, appKey: options.appKey, + restartAfterInstall: options.restartAfterInstall, force: options.force }, Run2); diff --git a/src/apt/scalability.ts b/src/apt/scalability.ts index c312435..da26e93 100644 --- a/src/apt/scalability.ts +++ b/src/apt/scalability.ts @@ -41,6 +41,7 @@ export const Scalability = async (options: TAPTScalabilityTestArgs) => { license, appKey: options.appKey, appLicense: options.appLicense, + restartAfterInstall: options.restartAfterInstall, force: options.force }, ScalabilityTestMessages); @@ -56,6 +57,7 @@ export const Scalability = async (options: TAPTScalabilityTestArgs) => { license, appKey: options.appKey, appLicense: options.appLicense, + restartAfterInstall: options.restartAfterInstall, force: options.force }, ScalabilityTestMessages); @@ -71,6 +73,7 @@ export const Scalability = async (options: TAPTScalabilityTestArgs) => { license, appKey: options.appKey, appLicense: options.appLicense, + restartAfterInstall: options.restartAfterInstall, force: options.force }, ScalabilityTestMessages); diff --git a/src/commands/apt.ts b/src/commands/apt.ts index 15f779b..e6fda98 100644 --- a/src/commands/apt.ts +++ b/src/commands/apt.ts @@ -50,6 +50,7 @@ const DefaultCommand = () => ({ environment: options.environment, appKey: options.appKey, appLicense: options.appLicense, + restartAfterInstall: options.restartAfterInstall, timestamp: options.timestamp, force: options.force }); @@ -65,6 +66,7 @@ const DefaultCommand = () => ({ environment: options.environment, appKey: options.appKey, appLicense: options.appLicense, + restartAfterInstall: options.restartAfterInstall, timestamp: options.timestamp, force: options.force }); @@ -122,6 +124,7 @@ const PerformanceTestCommand = () => ({ environment: options.environment, appKey: options.appKey, appLicense: options.appLicense, + restartAfterInstall: options.restartAfterInstall, timestamp: options.timestamp, force: options.force }); @@ -190,6 +193,7 @@ const ScalabilityTestCommand = () => ({ environment: options.environment, appKey: options.appKey, appLicense: options.appLicense, + restartAfterInstall: options.restartAfterInstall, timestamp: options.timestamp, force: options.force }); @@ -292,7 +296,6 @@ const TeardownCommand = () => ({ } }) - program .name('dcdx apt') .showHelpAfterError(true); @@ -303,6 +306,7 @@ program .addOption(new Option('--environment ', 'The environment name')) .addOption(new Option('--license ', 'The host product license, either as a path to a file or the license itself')) .addOption(new Option('--appKey ', 'The key of the app (for automated installation)')) + .addOption(new Option('--restartAfterInstall', 'Restart the container after installing the app').default(false)) .addOption(new Option('--ts, --timestamp ', 'The timestamp of the test run, which can be used to continue an existing test execution')) .addOption(new Option('-O, --outputDir ', 'Specify the directory where to store the results of the App Performance Toolkit')) .addOption(new Option('--cwd ', 'Specify the working directory where to find the App Performance Toolkit').default(cwd())) @@ -327,6 +331,7 @@ program .addOption(new Option('--environment ', 'The environment name')) .addOption(new Option('--license ', 'The host product license, either as a path to a file or the license itself')) .addOption(new Option('--appKey ', 'The key of the app (for automated installation)')) + .addOption(new Option('--restartAfterInstall', 'Restart the container after installing the app').default(false)) .addOption(new Option('--ts, --timestamp ', 'The timestamp of the test run, which can be used to continue an existing test execution')) .addOption(new Option('-O, --outputDir ', 'Specify the directory where to store the results of the App Performance Toolkit')) .addOption(new Option('--cwd ', 'Specify the working directory where to find the App Performance Toolkit').default(cwd())) @@ -340,6 +345,7 @@ program .addOption(new Option('--environment ', 'The environment name')) .addOption(new Option('--license ', 'The host product license, either as a path to a file or the license itself')) .addOption(new Option('--appKey ', 'The key of the app (for automated installation)')) + .addOption(new Option('--restartAfterInstall', 'Restart the container after installing the app').default(false)) .addOption(new Option('--ts, --timestamp ', 'The timestamp of the test run, which can be used to continue an existing test execution')) .addOption(new Option('-O, --outputDir ', 'Specify the directory where to store the results of the App Performance Toolkit')) .addOption(new Option('--cwd ', 'Specify the working directory where to find the App Performance Toolkit').default(cwd())) @@ -353,6 +359,7 @@ program .addOption(new Option('--environment ', 'The environment name')) .addOption(new Option('--license ', 'The host product license, either as a path to a file or the license itself')) .addOption(new Option('--appKey ', 'The key of the app (for automated installation)')) + .addOption(new Option('--restartAfterInstall', 'Restart the container after installing the app').default(false)) .addOption(new Option('--ts, --timestamp ', 'The timestamp of the test run, which can be used to continue an existing test execution')) .addOption(new Option('-O, --outputDir ', 'Specify the directory where to store the results of the App Performance Toolkit')) .addOption(new Option('--cwd ', 'Specify the working directory where to find the App Performance Toolkit').default(cwd())) @@ -380,7 +387,6 @@ program .addOption(new Option('--environment ', 'The environment name')) .addOption(new Option('--license ', 'The host product license, either as a path to a file or the license itself')) .addOption(new Option('--ts, --timestamp ', 'The timestamp of the test run, which can be used to continue an existing test execution')) - .addOption(new Option('--appKey ', 'The key of the app (for automated installation)')) .addOption(new Option('-O, --outputDir ', 'Specify the directory where to store the results of the App Performance Toolkit')) .addOption(new Option('--cwd ', 'Specify the working directory where to find the App Performance Toolkit').default(cwd())) .addOption(new Option('-y, --force', 'Use default values for input questions when available').default(false)) @@ -394,6 +400,7 @@ program .addOption(new Option('--license ', 'The host product license, either as a path to a file or the license itself')) .addOption(new Option('--ts, --timestamp ', 'The timestamp of the test run, which can be used to continue an existing test execution')) .addOption(new Option('--appKey ', 'The key of the app (for automated installation)')) + .addOption(new Option('--restartAfterInstall', 'Restart the container after installing the app').default(false)) .addOption(new Option('-O, --outputDir ', 'Specify the directory where to store the results of the App Performance Toolkit')) .addOption(new Option('--cwd ', 'Specify the working directory where to find the App Performance Toolkit').default(cwd())) .addOption(new Option('-y, --force', 'Use default values for input questions when available').default(false)) @@ -407,6 +414,7 @@ program .addOption(new Option('--license ', 'The host product license, either as a path to a file or the license itself')) .addOption(new Option('--ts, --timestamp ', 'The timestamp of the test run, which can be used to continue an existing test execution')) .addOption(new Option('--appKey ', 'The key of the app (for automated installation)')) + .addOption(new Option('--restartAfterInstall', 'Restart the container after installing the app').default(false)) .addOption(new Option('-O, --outputDir ', 'Specify the directory where to store the results of the App Performance Toolkit')) .addOption(new Option('--cwd ', 'Specify the working directory where to find the App Performance Toolkit').default(cwd())) .addOption(new Option('-y, --force', 'Use default values for input questions when available').default(false)) @@ -420,6 +428,7 @@ program .addOption(new Option('--license ', 'The host product license, either as a path to a file or the license itself')) .addOption(new Option('--ts, --timestamp ', 'The timestamp of the test run, which can be used to continue an existing test execution')) .addOption(new Option('--appKey ', 'The key of the app (for automated installation)')) + .addOption(new Option('--restartAfterInstall', 'Restart the container after installing the app').default(false)) .addOption(new Option('-O, --outputDir ', 'Specify the directory where to store the results of the App Performance Toolkit')) .addOption(new Option('--cwd ', 'Specify the working directory where to find the App Performance Toolkit').default(cwd())) .addOption(new Option('-y, --force', 'Use default values for input questions when available').default(false)) @@ -433,6 +442,7 @@ program .addOption(new Option('--license ', 'The host product license, either as a path to a file or the license itself')) .addOption(new Option('--ts, --timestamp ', 'The timestamp of the test run, which can be used to continue an existing test execution')) .addOption(new Option('--appKey ', 'The key of the app (for automated installation)')) + .addOption(new Option('--restartAfterInstall', 'Restart the container after installing the app').default(false)) .addOption(new Option('-O, --outputDir ', 'Specify the directory where to store the results of the App Performance Toolkit')) .addOption(new Option('--cwd ', 'Specify the working directory where to find the App Performance Toolkit').default(cwd())) .addOption(new Option('-y, --force', 'Use default values for input questions when available').default(false)) diff --git a/src/commands/install.ts b/src/commands/install.ts index 254fee3..86fcb79 100644 --- a/src/commands/install.ts +++ b/src/commands/install.ts @@ -7,6 +7,7 @@ import { glob } from 'glob'; import { resolve } from 'path'; import { cwd } from 'process'; +import { getAppLicense } from '../apt/helpers/getAppLicense'; import { installApp } from '../apt/helpers/installApp'; import { ActionHandler } from '../helpers/ActionHandler'; import { AMPS } from '../helpers/amps'; @@ -36,7 +37,15 @@ const Command = () => { throw new InvalidOptionArgumentError('Missing argument "--appKey", required for installing from the Atlassian Marketplace'); } - await installApp(options.baseUrl, options.appKey, undefined, options.username, options.password, true); + await installApp({ + baseUrl: options.baseUrl, + appKey: options.appKey, + license: await getAppLicense(options.license, true), + username: options.username, + password: options.password, + restartAfterInstall: false, + force: true + }); } else { @@ -98,6 +107,7 @@ If there is a running instance, it will try to install the plugin using QuickRel .addOption(new Option('--mpac', 'Install the app from the Atlassian Marketplace')) .addOption(new Option('--baseUrl ', 'URL of the instance (required with --mpac)')) .addOption(new Option('--appKey ', 'The key of the app to be installed (required with --mpac)')) + .addOption(new Option('--license ', 'The app license, either as a path to a file or the license itself')) .addOption(new Option('--cwd ', 'Specify the working directory where to find the AMPS configuration')) .action(options => ActionHandler(program, Command(), { ...options, install: true })); diff --git a/src/types/DCAPT.ts b/src/types/DCAPT.ts index 0652511..232d5ce 100644 --- a/src/types/DCAPT.ts +++ b/src/types/DCAPT.ts @@ -73,12 +73,14 @@ export const APTPerformanceTestArgs = z.object({ license: z.string(), appKey: z.string(), appLicense: z.string(), + restartAfterInstall: z.boolean(), timestamp: z.string(), force: z.boolean() }).partial({ outputDir: true, license: true, timestamp: true, + restartAfterInstall: true, force: true }); @@ -93,6 +95,7 @@ export const APTPerformanceTestOptions = z.object({ license: z.string(), appKey: z.string(), appLicense: z.string(), + restartAfterInstall: z.boolean(), force: z.boolean() }).partial({ baseUrl: true, @@ -100,6 +103,7 @@ export const APTPerformanceTestOptions = z.object({ aws_secret_access_key: true, appKey: true, appLicense: true, + restartAfterInstall: true, force: true }); @@ -132,12 +136,14 @@ export const APTScalabilityTestArgs = z.object({ license: z.string(), appKey: z.string(), appLicense: z.string(), + restartAfterInstall: z.boolean(), timestamp: z.string(), force: z.boolean() }).partial({ outputDir: true, license: true, appLicense: true, + restartAfterInstall: true, timestamp: true, force: true }); @@ -150,10 +156,12 @@ export const APTScalabilityTestOptions = z.object({ license: z.string(), appKey: z.string(), appLicense: z.string(), + restartAfterInstall: z.boolean(), force: z.boolean() }).partial({ appKey: true, appLicense: true, + restartAfterInstall: true, force: true }); diff --git a/src/types/Install.ts b/src/types/Install.ts index f323a94..c562b08 100644 --- a/src/types/Install.ts +++ b/src/types/Install.ts @@ -2,6 +2,8 @@ import { z } from 'zod'; +import { APTRestartOptions } from './DCAPT'; + export const InstallArgs = z.object({ watch: z.boolean(), outputDirectory: z.string(), @@ -12,6 +14,7 @@ export const InstallArgs = z.object({ mpac: z.boolean(), baseUrl: z.string(), appKey: z.string(), + license: z.string(), cwd: z.string() }).partial({ outputDirectory: true, @@ -25,4 +28,27 @@ export const InstallArgs = z.object({ cwd: true }); -export type TInstallArgs = z.infer; \ No newline at end of file +export const InstallOptions = APTRestartOptions.extend({ + baseUrl: z.string(), + appKey: z.string(), + license: z.string(), + username: z.string(), + password: z.string(), + restartAfterInstall: z.boolean(), + force: z.boolean() +}).partial({ + appKey: true, + license: true, + username: true, + password: true, + restartAfterInstall: true, + product: true, + cwd: true, + environment: true, + aws_access_key_id: true, + aws_secret_access_key: true, + force: true +}) + +export type TInstallArgs = z.infer; +export type TInstallOptions = z.infer; \ No newline at end of file