diff --git a/src/commands/config.command.ts b/src/commands/config.command.ts index 8902497..ecf8efc 100644 --- a/src/commands/config.command.ts +++ b/src/commands/config.command.ts @@ -1,4 +1,5 @@ import {batchImportExportService} from "../services/package-manager/batch-import-export-service"; +import {variableService} from "../services/package-manager/variable-service"; export class ConfigCommand { @@ -10,6 +11,14 @@ export class ConfigCommand { } } + public async listVariables(jsonResponse: boolean, keysByVersion: string[], keysByVersionFile: string): Promise { + if (jsonResponse) { + await variableService.exportVariables(keysByVersion, keysByVersionFile); + } else { + await variableService.listVariables(keysByVersion, keysByVersionFile); + } + } + public batchExportPackages(packageKeys: string[], withDependencies: boolean = false): Promise { return batchImportExportService.batchExportPackages(packageKeys, withDependencies); } diff --git a/src/content-cli-config.ts b/src/content-cli-config.ts index 679ca47..9314243 100644 --- a/src/content-cli-config.ts +++ b/src/content-cli-config.ts @@ -23,6 +23,22 @@ export class Config { return program; } + public static listVariables(program: CommanderStatic): CommanderStatic { + program + .command("listVariables") + .description("Command to list versioned variables of packages") + .option("-p, --profile ", "Profile which you want to use to list packages") + .option("--json", "Return response as json type", "") + .option("--keysByVersion ", "Mapping of package keys and versions", "") + .option("--keysByVersionFile ", "Package keys by version mappings file path.", "") + .action(async cmd => { + await new ConfigCommand().listVariables(cmd.json, cmd.keysByVersion, cmd.keysByVersionFile); + process.exit(); + }) + + return program; + } + public static export(program: CommanderStatic): CommanderStatic { program .command("export") @@ -45,6 +61,7 @@ process.on("unhandledRejection", (e, promise) => { const loadAllCommands = () => { Config.list(commander); + Config.listVariables(commander); Config.export(commander); commander.parse(process.argv); }; diff --git a/src/services/package-manager/variable-service.ts b/src/services/package-manager/variable-service.ts index 71ed1c0..02807e7 100644 --- a/src/services/package-manager/variable-service.ts +++ b/src/services/package-manager/variable-service.ts @@ -9,6 +9,9 @@ import { v4 as uuidv4 } from "uuid"; import {FatalError, logger} from "../../util/logger"; import {FileService, fileService} from "../file-service"; import {URLSearchParams} from "url"; +import {studioService} from "../studio/studio.service"; +import {batchImportExportApi} from "../../api/batch-import-export-api"; +import {PackageKeyAndVersionPair, VariableManifestTransport} from "../../interfaces/package-export-transport"; class VariableService { @@ -33,9 +36,21 @@ class VariableService { const parsedParams = this.parseParams(params); const assignments = await variablesApi.getCandidateAssignments(type, parsedParams); - const filename = uuidv4() + ".json"; - fileService.writeToFileWithGivenName(JSON.stringify(assignments), filename); - logger.info(FileService.fileDownloadedMessage + filename); + this.exportToJson(assignments) + } + + public async listVariables(keysByVersion: string[], keysByVersionFile: string): Promise { + const variableManifests = await this.getVersionedVariablesByKeyVersionPairs(keysByVersion, keysByVersionFile); + + variableManifests.forEach(variableManifest => { + logger.info(JSON.stringify(variableManifest)); + }); + } + + public async exportVariables(keysByVersion: string[], keysByVersionFile: string): Promise { + const variableManifests = await this.getVersionedVariablesByKeyVersionPairs(keysByVersion, keysByVersionFile); + + this.exportToJson(variableManifests); } private parseParams(params?: string): URLSearchParams { @@ -54,6 +69,43 @@ class VariableService { return queryParams; } + + private async getVersionedVariablesByKeyVersionPairs(keysByVersion: string[], keysByVersionFile: string): Promise { + const variablesExportRequest: PackageKeyAndVersionPair[] = await this.buildKeyVersionPairs(keysByVersion, keysByVersionFile); + + const variableManifests = await batchImportExportApi.findVariablesWithValuesByPackageKeysAndVersion(variablesExportRequest); + return studioService.fixConnectionVariables(variableManifests); + } + + private async buildKeyVersionPairs(keysByVersion: string[], keysByVersionFile: string): Promise { + let variablesExportRequest: PackageKeyAndVersionPair[] = []; + + if (keysByVersion.length) { + variablesExportRequest = this.buildKeyAndVersionPairsFromArrayInput(keysByVersion); + } else if (!keysByVersion.length && keysByVersionFile.length) { + variablesExportRequest = await fileService.readFileToJson(keysByVersionFile); + } else { + throw new FatalError("Please provide keysByVersion mappings or file path!"); + } + + return variablesExportRequest; + } + + private buildKeyAndVersionPairsFromArrayInput(keysByVersion: string[]): PackageKeyAndVersionPair[] { + return keysByVersion.map(keyAndVersion => { + const keyAndVersionSplit = keyAndVersion.split(":"); + return { + packageKey: keyAndVersionSplit[0], + version: keyAndVersionSplit[1] + }; + }); + } + + private exportToJson(data: any): void { + const filename = uuidv4() + ".json"; + fileService.writeToFileWithGivenName(JSON.stringify(data), filename); + logger.info(FileService.fileDownloadedMessage + filename); + } } export const variableService = new VariableService(); diff --git a/tests/config/config-list-variables.spec.ts b/tests/config/config-list-variables.spec.ts new file mode 100644 index 0000000..e4eb154 --- /dev/null +++ b/tests/config/config-list-variables.spec.ts @@ -0,0 +1,149 @@ +import {ConfigCommand} from "../../src/commands/config.command"; +import {mockWriteFileSync, testTransport} from "../jest.setup"; +import {FileService} from "../../src/services/file-service"; +import * as path from "path"; +import {PackageKeyAndVersionPair, VariableManifestTransport} from "../../src/interfaces/package-export-transport"; +import {PackageManagerVariableType} from "../../src/interfaces/package-manager.interfaces"; +import {mockAxiosPost, mockedPostRequestBodyByUrl} from "../utls/http-requests-mock"; +import {parse} from "../../src/util/yaml"; +import * as fs from "fs"; + +describe("Config listVariables", () => { + + const firstManifest: VariableManifestTransport = { + packageKey: "key-1", + version: "1.0.0", + variables: [ + { + key: "key1-var", + type: PackageManagerVariableType.DATA_MODEL, + value: "dm-id" as unknown as object, + metadata: {} + }, + { + key: "key-1-connection", + type: PackageManagerVariableType.CONNECTION, + value: { + appName: "celonis", + connectionId: "connection-id" + } as unknown as object, + metadata: null + } + ] + }; + + const secondManifest: VariableManifestTransport = { + packageKey: "key-2", + version: "1.0.0", + variables: [ + { + key: "key2-var", + type: PackageManagerVariableType.CONNECTION, + value: { + appName: "celonis", + connectionId: "connection-id" + } as unknown as object, + metadata: { + appName: "celonis" + } + } + ] + }; + + const fixedVariableManifests: VariableManifestTransport[] = [ + { + ...firstManifest, + variables: [ + { + ...firstManifest.variables[0] + }, + { + ...firstManifest.variables[1], + metadata: { + appName: "celonis" + } + } + ] + }, + { + ...secondManifest + } + ]; + + const packageKeyAndVersionPairs: PackageKeyAndVersionPair[] = [ + { + packageKey: "key-1", + version: "1.0.0" + }, + { + packageKey: "key-2", + version: "1.0.0" + } + ]; + + beforeEach(() => { + mockAxiosPost("https://myTeam.celonis.cloud/package-manager/api/core/packages/export/batch/variables-with-assignments", [{...firstManifest}, {...secondManifest}]); + }) + + it("Should list fixed variables for non-json response", async () => { + await new ConfigCommand().listVariables(false, ["key-1:1.0.0", "key-2:1.0.0"], null); + + expect(testTransport.logMessages.length).toBe(2); + expect(testTransport.logMessages[0].message).toContain(JSON.stringify(fixedVariableManifests[0])); + expect(testTransport.logMessages[1].message).toContain(JSON.stringify(fixedVariableManifests[1])); + + const variableExportRequest = parse(mockedPostRequestBodyByUrl.get("https://myTeam.celonis.cloud/package-manager/api/core/packages/export/batch/variables-with-assignments")); + expect(variableExportRequest).toEqual(packageKeyAndVersionPairs); + }) + + it("Should export fixed variables for json response", async () => { + await new ConfigCommand().listVariables(true, ["key-1:1.0.0", "key-2:1.0.0"], null); + + expect(testTransport.logMessages.length).toBe(1); + expect(testTransport.logMessages[0].message).toContain(FileService.fileDownloadedMessage); + + const expectedFileName = testTransport.logMessages[0].message.split(FileService.fileDownloadedMessage)[1]; + expect(mockWriteFileSync).toHaveBeenCalledWith(path.resolve(process.cwd(), expectedFileName), JSON.stringify(fixedVariableManifests), {encoding: "utf-8"}); + + const variableExportRequest = parse(mockedPostRequestBodyByUrl.get("https://myTeam.celonis.cloud/package-manager/api/core/packages/export/batch/variables-with-assignments")); + expect(variableExportRequest).toEqual(packageKeyAndVersionPairs); + }) + + it("Should list fixed variables for non-json response and keysByVersion file mapping", async () => { + (fs.existsSync as jest.Mock).mockReturnValue(true); + (fs.readFileSync as jest.Mock).mockReturnValue(JSON.stringify(packageKeyAndVersionPairs)); + + await new ConfigCommand().listVariables(false, [], "key_version_mapping.json"); + + expect(testTransport.logMessages.length).toBe(2); + expect(testTransport.logMessages[0].message).toContain(JSON.stringify(fixedVariableManifests[0])); + expect(testTransport.logMessages[1].message).toContain(JSON.stringify(fixedVariableManifests[1])); + + const variableExportRequest = parse(mockedPostRequestBodyByUrl.get("https://myTeam.celonis.cloud/package-manager/api/core/packages/export/batch/variables-with-assignments")); + expect(variableExportRequest).toEqual(packageKeyAndVersionPairs); + }) + + it("Should export fixed variables for json response and keysByVersion file mapping", async () => { + (fs.existsSync as jest.Mock).mockReturnValue(true); + (fs.readFileSync as jest.Mock).mockReturnValue(JSON.stringify(packageKeyAndVersionPairs)); + + await new ConfigCommand().listVariables(true, [], "key_version_mapping.json"); + + expect(testTransport.logMessages.length).toBe(1); + expect(testTransport.logMessages[0].message).toContain(FileService.fileDownloadedMessage); + + const expectedFileName = testTransport.logMessages[0].message.split(FileService.fileDownloadedMessage)[1]; + expect(mockWriteFileSync).toHaveBeenCalledWith(path.resolve(process.cwd(), expectedFileName), JSON.stringify(fixedVariableManifests), {encoding: "utf-8"}); + + const variableExportRequest = parse(mockedPostRequestBodyByUrl.get("https://myTeam.celonis.cloud/package-manager/api/core/packages/export/batch/variables-with-assignments")); + expect(variableExportRequest).toEqual(packageKeyAndVersionPairs); + }) + + it("Should throw error if no mapping or file path is provided", async () => { + try { + await new ConfigCommand().listVariables(true, [], ""); + } catch (e) { + expect(e.message).toEqual("Please provide keysByVersion mappings or file path!"); + } + }) +}) \ No newline at end of file