From 34e2649a987e809e0820d22f97878c9705074247 Mon Sep 17 00:00:00 2001 From: Shmaraiev Oleksandr Date: Tue, 24 Dec 2024 17:26:54 +0200 Subject: [PATCH] Add 'DotnetDevFileAPI' E2E test (#23298) * Add 'DotnetDevFileAPI' test * Update to overload 'deleteDevWorkspace' method --- tests/e2e/specs/api/DotnetDevFileAPI.spec.ts | 99 +++++++++++++++++++ tests/e2e/specs/api/GoDevFileAPI.spec.ts | 6 +- tests/e2e/specs/api/PhpDevFileAPI.spec.ts | 6 +- tests/e2e/specs/api/PythonDevFileAPI.spec.ts | 6 +- .../KubernetesCommandLineToolsExecutor.ts | 27 ++++- 5 files changed, 133 insertions(+), 11 deletions(-) create mode 100644 tests/e2e/specs/api/DotnetDevFileAPI.spec.ts diff --git a/tests/e2e/specs/api/DotnetDevFileAPI.spec.ts b/tests/e2e/specs/api/DotnetDevFileAPI.spec.ts new file mode 100644 index 00000000000..31e70d17490 --- /dev/null +++ b/tests/e2e/specs/api/DotnetDevFileAPI.spec.ts @@ -0,0 +1,99 @@ +/** ******************************************************************* + * copyright (c) 2024 Red Hat, Inc. + * + * This program and the accompanying materials are made + * available under the terms of the Eclipse Public License 2.0 + * which is available at https://www.eclipse.org/legal/epl-2.0/ + * + * SPDX-License-Identifier: EPL-2.0 + **********************************************************************/ +import { BASE_TEST_CONSTANTS } from '../../constants/BASE_TEST_CONSTANTS'; +import { e2eContainer } from '../../configs/inversify.config'; +import { CLASSES } from '../../configs/inversify.types'; +import { DevfilesHelper } from '../../utils/DevfilesHelper'; +import { ContainerTerminal, KubernetesCommandLineToolsExecutor } from '../../utils/KubernetesCommandLineToolsExecutor'; +import { DevWorkspaceConfigurationHelper } from '../../utils/DevWorkspaceConfigurationHelper'; +import { DevfileContext } from '@eclipse-che/che-devworkspace-generator/lib/api/devfile-context'; +import { ShellString } from 'shelljs'; +import { expect } from 'chai'; +import { API_TEST_CONSTANTS } from '../../constants/API_TEST_CONSTANTS'; +import YAML from 'yaml'; +import { Logger } from '../../utils/Logger'; +import crypto from 'crypto'; + +suite('Dotnet devfile API test', function (): void { + const devfilesRegistryHelper: DevfilesHelper = e2eContainer.get(CLASSES.DevfilesRegistryHelper); + const kubernetesCommandLineToolsExecutor: KubernetesCommandLineToolsExecutor = e2eContainer.get( + CLASSES.KubernetesCommandLineToolsExecutor + ); + const devfileID: string = 'dotnet'; + const containerTerminal: ContainerTerminal = e2eContainer.get(CLASSES.ContainerTerminal); + let devWorkspaceConfigurationHelper: DevWorkspaceConfigurationHelper; + let devfileContext: DevfileContext; + let devfileContent: string = ''; + let dwtName: string = ''; + + suiteSetup(`Prepare login ${BASE_TEST_CONSTANTS.TEST_ENVIRONMENT}`, function (): void { + kubernetesCommandLineToolsExecutor.loginToOcp(); + }); + + test(`Create ${devfileID} workspace`, async function (): Promise { + const randomPref: string = crypto.randomBytes(4).toString('hex'); + kubernetesCommandLineToolsExecutor.namespace = API_TEST_CONSTANTS.TS_API_TEST_NAMESPACE || 'admin-devspaces'; + devfileContent = devfilesRegistryHelper.getDevfileContent(devfileID); + const editorDevfileContent: string = devfilesRegistryHelper.obtainCheDevFileEditorFromCheConfigMap('editors-definitions'); + dwtName = YAML.parse(devfileContent).metadata.name; + const uniqName: string = YAML.parse(devfileContent).metadata.name + randomPref; + kubernetesCommandLineToolsExecutor.workspaceName = uniqName; + + devWorkspaceConfigurationHelper = new DevWorkspaceConfigurationHelper({ + editorContent: editorDevfileContent, + devfileContent: devfileContent + }); + devfileContext = await devWorkspaceConfigurationHelper.generateDevfileContext(); + if (devfileContext.devWorkspace.metadata) { + devfileContext.devWorkspace.metadata.name = uniqName; + } + const devWorkspaceConfigurationYamlString: string = + devWorkspaceConfigurationHelper.getDevWorkspaceConfigurationYamlAsString(devfileContext); + const output: ShellString = kubernetesCommandLineToolsExecutor.applyAndWaitDevWorkspace(devWorkspaceConfigurationYamlString); + expect(output.stdout).contains('condition met'); + }); + + test('Check devfile commands', function (): void { + const workdir: string = YAML.parse(devfileContent).commands[0].exec.workingDir; + const containerName: string = YAML.parse(devfileContent).commands[0].exec.component; + const updateCommandLine: string = YAML.parse(devfileContent).commands[0].exec.commandLine; + Logger.info(`workdir from exec section of DevFile: ${workdir}`); + Logger.info(`containerName from exec section of DevFile: ${containerName}`); + + Logger.info('"Test \'update-dependencies\' command execution"'); + Logger.info(`commandLine from exec section of DevFile file: ${updateCommandLine}`); + const runCommandInBash: string = `cd ${workdir} && ${updateCommandLine}`; + const output: ShellString = containerTerminal.execInContainerCommand(runCommandInBash, containerName); + expect(output.code).eqls(0); + expect(output.stdout.trim()).contains('Restored /projects/dotnet-web-simple/web.csproj'); + + Logger.info('"Test \'build\' command execution"'); + const buildCommandLine: string = YAML.parse(devfileContent).commands[1].exec.commandLine; + Logger.info(`commandLine from exec section of DevFile: ${buildCommandLine}`); + const runCommandInBash2: string = `cd ${workdir} && ${buildCommandLine}`; + const output2: ShellString = containerTerminal.execInContainerCommand(runCommandInBash2, containerName); + expect(output2.code).eqls(0); + expect(output2.stdout.trim()).contains('Build succeeded'); + + Logger.info('"Test \'run\' command execution"'); + const runCommandLine: string = YAML.parse(devfileContent).commands[2].exec.commandLine; + Logger.info(`commandLine from exec section of DevFile: ${runCommandLine}`); + const runCommandInBash3: string = `cd ${workdir} && sh -c "(${runCommandLine} > server.log 2>&1 &) && sleep 20s && exit"`; + const output3: ShellString = containerTerminal.execInContainerCommand(runCommandInBash3, containerName); + expect(output3.code).eqls(0); + const logOutput: ShellString = containerTerminal.execInContainerCommand(`cat ${workdir}/server.log`, containerName); + Logger.info(`Log output: ${logOutput.stdout}`); + expect(logOutput.stdout.trim()).contains('Content root path: /projects/dotnet-web-simple'); + }); + + suiteTeardown('Delete DevWorkspace', function (): void { + kubernetesCommandLineToolsExecutor.deleteDevWorkspace(dwtName); + }); +}); diff --git a/tests/e2e/specs/api/GoDevFileAPI.spec.ts b/tests/e2e/specs/api/GoDevFileAPI.spec.ts index 8683ea10875..3e9d8c7a8c8 100644 --- a/tests/e2e/specs/api/GoDevFileAPI.spec.ts +++ b/tests/e2e/specs/api/GoDevFileAPI.spec.ts @@ -32,6 +32,7 @@ suite('Go devfile API test', function (): void { let devWorkspaceConfigurationHelper: DevWorkspaceConfigurationHelper; let devfileContext: DevfileContext; let devfileContent: string = ''; + let dwtName: string = ''; suiteSetup(`Prepare login ${BASE_TEST_CONSTANTS.TEST_ENVIRONMENT}`, function (): void { kubernetesCommandLineToolsExecutor.loginToOcp(); @@ -42,6 +43,7 @@ suite('Go devfile API test', function (): void { kubernetesCommandLineToolsExecutor.namespace = API_TEST_CONSTANTS.TS_API_TEST_NAMESPACE || 'admin-devspaces'; devfileContent = devfilesRegistryHelper.getDevfileContent(devfileID); const editorDevfileContent: string = devfilesRegistryHelper.obtainCheDevFileEditorFromCheConfigMap('editors-definitions'); + dwtName = YAML.parse(devfileContent).metadata.name; const uniqName: string = YAML.parse(devfileContent).metadata.name + randomPref; kubernetesCommandLineToolsExecutor.workspaceName = uniqName; @@ -84,7 +86,7 @@ suite('Go devfile API test', function (): void { expect(logOutput.stdout.trim()).contains('Web server running on port 8080'); }); - suiteTeardown('Delete workspace', function (): void { - kubernetesCommandLineToolsExecutor.deleteDevWorkspace(); + suiteTeardown('Delete DevWorkspace', function (): void { + kubernetesCommandLineToolsExecutor.deleteDevWorkspace(dwtName); }); }); diff --git a/tests/e2e/specs/api/PhpDevFileAPI.spec.ts b/tests/e2e/specs/api/PhpDevFileAPI.spec.ts index 86d3b5b5e05..c5208db22c3 100644 --- a/tests/e2e/specs/api/PhpDevFileAPI.spec.ts +++ b/tests/e2e/specs/api/PhpDevFileAPI.spec.ts @@ -31,6 +31,7 @@ suite('PHP devfile API test', function (): void { let devWorkspaceConfigurationHelper: DevWorkspaceConfigurationHelper; let devfileContext: DevfileContext; let devfileContent: string = ''; + let dwtName: string = ''; suiteSetup(`Prepare login ${BASE_TEST_CONSTANTS.TEST_ENVIRONMENT}`, function (): void { kubernetesCommandLineToolsExecutor.loginToOcp(); @@ -41,6 +42,7 @@ suite('PHP devfile API test', function (): void { kubernetesCommandLineToolsExecutor.namespace = API_TEST_CONSTANTS.TS_API_TEST_NAMESPACE || 'admin-devspaces'; devfileContent = devfilesRegistryHelper.getDevfileContent(devfileID); const editorDevfileContent: string = devfilesRegistryHelper.obtainCheDevFileEditorFromCheConfigMap('editors-definitions'); + dwtName = YAML.parse(devfileContent).metadata.name; const uniqName: string = YAML.parse(devfileContent).metadata.name + randomPref; kubernetesCommandLineToolsExecutor.workspaceName = uniqName; @@ -70,7 +72,7 @@ suite('PHP devfile API test', function (): void { expect(output.stdout.trim()).contains('Hello, world!'); }); - suiteTeardown('Delete workspace', function (): void { - kubernetesCommandLineToolsExecutor.deleteDevWorkspace(); + suiteTeardown('Delete DevWorkspace', function (): void { + kubernetesCommandLineToolsExecutor.deleteDevWorkspace(dwtName); }); }); diff --git a/tests/e2e/specs/api/PythonDevFileAPI.spec.ts b/tests/e2e/specs/api/PythonDevFileAPI.spec.ts index 7d15c1c1be9..30adf871d83 100644 --- a/tests/e2e/specs/api/PythonDevFileAPI.spec.ts +++ b/tests/e2e/specs/api/PythonDevFileAPI.spec.ts @@ -32,6 +32,7 @@ suite('Python devfile API test', function (): void { let devWorkspaceConfigurationHelper: DevWorkspaceConfigurationHelper; let devfileContext: DevfileContext; let devfileContent: string = ''; + let dwtName: string = ''; suiteSetup(`Prepare login ${BASE_TEST_CONSTANTS.TEST_ENVIRONMENT}`, function (): void { kubernetesCommandLineToolsExecutor.loginToOcp(); @@ -42,6 +43,7 @@ suite('Python devfile API test', function (): void { kubernetesCommandLineToolsExecutor.namespace = API_TEST_CONSTANTS.TS_API_TEST_NAMESPACE || 'admin-devspaces'; devfileContent = devfilesRegistryHelper.getDevfileContent(devfileID); const editorDevfileContent: string = devfilesRegistryHelper.obtainCheDevFileEditorFromCheConfigMap('editors-definitions'); + dwtName = YAML.parse(devfileContent).metadata.name; const uniqName: string = YAML.parse(devfileContent).metadata.name + randomPref; kubernetesCommandLineToolsExecutor.workspaceName = uniqName; @@ -71,7 +73,7 @@ suite('Python devfile API test', function (): void { expect(output.stdout.trim()).contains('Hello, world!'); }); - suiteTeardown('Delete workspace', function (): void { - kubernetesCommandLineToolsExecutor.deleteDevWorkspace(); + suiteTeardown('Delete DevWorkspace', function (): void { + kubernetesCommandLineToolsExecutor.deleteDevWorkspace(dwtName); }); }); diff --git a/tests/e2e/utils/KubernetesCommandLineToolsExecutor.ts b/tests/e2e/utils/KubernetesCommandLineToolsExecutor.ts index ae55ebddb75..5e1fbec0c59 100644 --- a/tests/e2e/utils/KubernetesCommandLineToolsExecutor.ts +++ b/tests/e2e/utils/KubernetesCommandLineToolsExecutor.ts @@ -94,16 +94,33 @@ export class KubernetesCommandLineToolsExecutor implements IKubernetesCommandLin return output.stderr ? output.stderr : output.stdout.replace('\n', ''); } - deleteDevWorkspace(): void { - Logger.debug(`${this.kubernetesCommandLineTool} - delete '${this.workspaceName}' workspace`); + // used to delete when devWorkspace and devWorkspaceTemplate have the same names + deleteDevWorkspace(): void; + + // used to delete when devWorkspace and devWorkspaceTemplate have different names + deleteDevWorkspace(dwTemplateName: string): void; + + deleteDevWorkspace(dwTemplateName?: string): void { + Logger.debug(`${this.kubernetesCommandLineTool} - delete '${this.workspaceName}' devWorkspace`); this.shellExecutor.executeCommand( `${this.kubernetesCommandLineTool} patch dw ${this.workspaceName} -n ${this.namespace} -p '{ "metadata": { "finalizers": null }}' --type merge || true` ); this.shellExecutor.executeCommand(`${this.kubernetesCommandLineTool} delete dw ${this.workspaceName} -n ${this.namespace} || true`); - this.shellExecutor.executeCommand( - `${this.kubernetesCommandLineTool} delete dwt ${BASE_TEST_CONSTANTS.TS_SELENIUM_EDITOR}-${this.workspaceName} -n ${this.namespace} || true` - ); + + if (dwTemplateName === undefined) { + Logger.debug(`${this.kubernetesCommandLineTool} - delete '${this.workspaceName}' devWorkspaceTemplate`); + + this.shellExecutor.executeCommand( + `${this.kubernetesCommandLineTool} delete dwt ${BASE_TEST_CONSTANTS.TS_SELENIUM_EDITOR}-${this.workspaceName} -n ${this.namespace} || true` + ); + } else { + Logger.debug(`${this.kubernetesCommandLineTool} - delete '${dwTemplateName}' devWorkspaceTemplate`); + + this.shellExecutor.executeCommand( + `${this.kubernetesCommandLineTool} delete dwt ${BASE_TEST_CONSTANTS.TS_SELENIUM_EDITOR}-${dwTemplateName} -n ${this.namespace} || true` + ); + } } applyAndWaitDevWorkspace(yamlConfiguration: string): ShellString {