diff --git a/src/behaviours/helm-charts/add-helm-repository-from-list-in-preferences.test.ts b/src/behaviours/helm-charts/add-helm-repository-from-list-in-preferences.test.ts index 0f43805b78..4d83567b21 100644 --- a/src/behaviours/helm-charts/add-helm-repository-from-list-in-preferences.test.ts +++ b/src/behaviours/helm-charts/add-helm-repository-from-list-in-preferences.test.ts @@ -14,6 +14,7 @@ import callForPublicHelmRepositoriesInjectable from "../../renderer/components/+ import showSuccessNotificationInjectable from "../../renderer/components/notifications/show-success-notification.injectable"; import showErrorNotificationInjectable from "../../renderer/components/notifications/show-error-notification.injectable"; import type { AsyncResult } from "../../common/utils/async-result"; +import type { ExecFile } from "../../main/child-process/exec-file.injectable"; import execFileInjectable from "../../main/child-process/exec-file.injectable"; // TODO: Make tooltips free of side effects by making it deterministic @@ -26,10 +27,8 @@ describe("add helm repository from list in preferences", () => { let showSuccessNotificationMock: jest.Mock; let showErrorNotificationMock: jest.Mock; let rendered: RenderResult; - let execFileMock: AsyncFnMock< - ReturnType - >; - let getActiveHelmRepositoriesMock: AsyncFnMock<() => AsyncResult>; + let execFileMock: AsyncFnMock; + let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; let callForPublicHelmRepositoriesMock: AsyncFnMock<() => Promise>; beforeEach(async () => { diff --git a/src/behaviours/helm-charts/listing-active-helm-repositories-in-preferences.test.ts b/src/behaviours/helm-charts/listing-active-helm-repositories-in-preferences.test.ts index 3528a871fc..c08e7c3084 100644 --- a/src/behaviours/helm-charts/listing-active-helm-repositories-in-preferences.test.ts +++ b/src/behaviours/helm-charts/listing-active-helm-repositories-in-preferences.test.ts @@ -15,6 +15,7 @@ import loggerInjectable from "../../common/logger.injectable"; import type { Logger } from "../../common/logger"; import callForPublicHelmRepositoriesInjectable from "../../renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/public-helm-repositories/call-for-public-helm-repositories.injectable"; import showErrorNotificationInjectable from "../../renderer/components/notifications/show-error-notification.injectable"; +import type { ExecFile } from "../../main/child-process/exec-file.injectable"; import execFileInjectable from "../../main/child-process/exec-file.injectable"; // TODO: Make tooltips free of side effects by making it deterministic @@ -26,7 +27,7 @@ describe("listing active helm repositories in preferences", () => { let applicationBuilder: ApplicationBuilder; let rendered: RenderResult; let readYamlFileMock: AsyncFnMock; - let execFileMock: AsyncFnMock>; + let execFileMock: AsyncFnMock; let loggerStub: Logger; let showErrorNotificationMock: jest.Mock; diff --git a/src/behaviours/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts b/src/behaviours/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts index bfa8f91dd2..0feb7a6afb 100644 --- a/src/behaviours/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts +++ b/src/behaviours/helm-charts/remove-helm-repository-from-list-of-active-repository-in-preferences.test.ts @@ -13,6 +13,7 @@ import getActiveHelmRepositoriesInjectable from "../../main/helm/repositories/ge import type { HelmRepo } from "../../common/helm/helm-repo"; import callForPublicHelmRepositoriesInjectable from "../../renderer/components/+preferences/kubernetes/helm-charts/adding-of-public-helm-repository/public-helm-repositories/call-for-public-helm-repositories.injectable"; import type { AsyncResult } from "../../common/utils/async-result"; +import type { ExecFile } from "../../main/child-process/exec-file.injectable"; import execFileInjectable from "../../main/child-process/exec-file.injectable"; // TODO: Make tooltips free of side effects by making it deterministic @@ -23,10 +24,8 @@ jest.mock("../../renderer/components/tooltip/withTooltip", () => ({ describe("remove helm repository from list of active repositories in preferences", () => { let applicationBuilder: ApplicationBuilder; let rendered: RenderResult; - let getActiveHelmRepositoriesMock: AsyncFnMock<() => AsyncResult>; - let execFileMock: AsyncFnMock< - ReturnType - >; + let getActiveHelmRepositoriesMock: AsyncFnMock<() => Promise>>; + let execFileMock: AsyncFnMock; beforeEach(async () => { applicationBuilder = getApplicationBuilder(); diff --git a/src/main/child-process/exec-file.injectable.ts b/src/main/child-process/exec-file.injectable.ts index 6db35b0e27..493994e9af 100644 --- a/src/main/child-process/exec-file.injectable.ts +++ b/src/main/child-process/exec-file.injectable.ts @@ -3,14 +3,25 @@ * Licensed under MIT License. See LICENSE in root directory for more information. */ import { getInjectable } from "@ogre-tools/injectable"; +import type { ExecFileOptions, ExecFileOptionsWithStringEncoding } from "child_process"; import { execFile } from "child_process"; import { promisify } from "util"; -export type ExecFile = typeof execFile["__promisify__"]; +export interface ExecFile { + (file: string, args?: readonly string[], opts?: ExecFileOptionsWithStringEncoding | ExecFileOptions): Promise; +} const execFileInjectable = getInjectable({ id: "exec-file", - instantiate: (): ExecFile => promisify(execFile), + instantiate: (): ExecFile => { + const asyncExecFile = promisify(execFile); + + return async (file) => { + const { stdout } = await asyncExecFile(file); + + return stdout; + }; + }, }); export default execFileInjectable; diff --git a/src/main/helm/exec-helm/exec-helm.injectable.ts b/src/main/helm/exec-helm/exec-helm.injectable.ts index fbbf8e35e8..0830cd0fa6 100644 --- a/src/main/helm/exec-helm/exec-helm.injectable.ts +++ b/src/main/helm/exec-helm/exec-helm.injectable.ts @@ -17,9 +17,9 @@ const execHelmInjectable = getInjectable({ return async (...args: string[]): Promise> => { try { - const { stdout } = await execFile(helmBinaryPath, args); + const response = await execFile(helmBinaryPath, args); - return { callWasSuccessful: true, response: stdout }; + return { callWasSuccessful: true, response }; } catch (error) { return { callWasSuccessful: false, error: getErrorMessage(error) }; } diff --git a/src/main/k8s/resource-applier/__tests__/applier.test.ts b/src/main/k8s/resource-applier/__tests__/applier.test.ts index 564dd71c96..9c2065baef 100644 --- a/src/main/k8s/resource-applier/__tests__/applier.test.ts +++ b/src/main/k8s/resource-applier/__tests__/applier.test.ts @@ -4,7 +4,6 @@ */ import type { DiContainer } from "@ogre-tools/injectable"; -import type { ChildProcess } from "child_process"; import path from "path"; import directoryForKubeConfigsInjectable from "../../../../common/app-paths/directory-for-kube-configs/directory-for-kube-configs.injectable"; import createAuthorizationReviewInjectable from "../../../../common/cluster/authorization-review.injectable"; @@ -91,36 +90,20 @@ describe("ResourceApplier", () => { }); it("should call unlink, if everything passes", async () => { - execFile.mockImplementation(() => Object.assign( - Promise.resolve({ - stdout: "I am some output", - stderr: "", - }), - { - child: {} as ChildProcess, - }, - )); + execFile.mockImplementation(async () => "I am some output"); await expect(resourceApplier.apply({})).resolves.toBeTruthy(); expect(unlink).toBeCalledWith("some/temp/file"); }); it("should return the stdout of execFile", async () => { - execFile.mockImplementation(() => Object.assign( - Promise.resolve({ - stdout: "I am some output", - stderr: "", - }), - { - child: {} as ChildProcess, - }, - )); + execFile.mockImplementation(async () => "I am some output"); expect(await resourceApplier.apply({})).toBe("I am some output"); }); it("should build up a correct set of arguments", async () => { - execFile.mockImplementation((path, args) => { + execFile.mockImplementation(async (path, args) => { expect(args).toEqual([ "apply", "--kubeconfig", @@ -131,15 +114,7 @@ describe("ResourceApplier", () => { "some/temp/file", ]); - return Object.assign( - Promise.resolve({ - stdout: "I am some output", - stderr: "", - }), - { - child: {} as ChildProcess, - }, - ); + return "I am some output"; }); await resourceApplier.apply({}); @@ -184,17 +159,7 @@ describe("ResourceApplier", () => { onlyOnce(contents); }); - execFile.mockImplementation(() => { - return Object.assign( - Promise.resolve({ - stdout: "I am some output", - stderr: "", - }), - { - child: {} as ChildProcess, - }, - ); - }); + execFile.mockImplementation(async () => "I am some output"); await expect(resourceApplier.kubectlApplyAll([...resources])).resolves.toBeTruthy(); expect(removeDir).toBeCalledWith("some/temp/dir"); @@ -202,7 +167,7 @@ describe("ResourceApplier", () => { }); it("should use resonable arguments", async () => { - execFile.mockImplementation((path, args) => { + execFile.mockImplementation(async (path, args) => { expect(args).toEqual([ "apply", "--kubeconfig", @@ -213,15 +178,7 @@ describe("ResourceApplier", () => { "some/temp/dir", ]); - return Object.assign( - Promise.resolve({ - stdout: "I am some output", - stderr: "", - }), - { - child: {} as ChildProcess, - }, - ); + return "I am some output"; }); await expect(resourceApplier.kubectlApplyAll(["foo", "bar"])).resolves.toBeTruthy(); diff --git a/src/main/k8s/resource-applier/applier.ts b/src/main/k8s/resource-applier/applier.ts index 32c39e225d..d04d06f22d 100644 --- a/src/main/k8s/resource-applier/applier.ts +++ b/src/main/k8s/resource-applier/applier.ts @@ -75,9 +75,7 @@ export class ResourceApplier implements K8sResourceApplier { ); try { - const { stdout } = await this.dependencies.execFile(kubectlPath, args); - - return stdout; + return await this.dependencies.execFile(kubectlPath, args); } catch (error) { if (isObject(error) && hasTypedProperty(error, "stderr", isString)) { throw error.stderr; @@ -114,9 +112,8 @@ export class ResourceApplier implements K8sResourceApplier { try { await this.dependencies.writeFile(fileName, content); - const { stdout } = await this.dependencies.execFile(kubectlPath, args, { env: execEnv }); - return stdout; + return await this.dependencies.execFile(kubectlPath, args, { env: execEnv }); } catch (error) { if (isObject(error) && hasTypedProperty(error, "stderr", isString)) { throw error.stderr; @@ -155,9 +152,7 @@ export class ResourceApplier implements K8sResourceApplier { this.dependencies.logger.info(`[RESOURCE-APPLIER] Executing ${kubectlPath}`, { args }); - const { stdout } = await this.dependencies.execFile(kubectlPath, args); - - return stdout; + return await this.dependencies.execFile(kubectlPath, args); } catch (error) { this.dependencies.logger.error(`[RESOURCE-APPLIER] cmd errored: ${error}`);