diff --git a/src/cli/build.ts b/src/cli/build.ts index 27160977e..5ec58740e 100644 --- a/src/cli/build.ts +++ b/src/cli/build.ts @@ -11,9 +11,10 @@ import { dependencies, version } from "./init/templates"; import { RootCmd } from "./root"; import { peprFormat } from "./format"; import { Option } from "commander"; -import { createDirectoryIfNotExists, validateCapabilityNames, parseTimeout } from "../lib/helpers"; +import { validateCapabilityNames, parseTimeout } from "../lib/helpers"; import { sanitizeResourceName } from "../sdk/sdk"; import { determineRbacMode } from "./build.helpers"; +import { createDirectoryIfNotExists } from "../lib/filesystemService"; const peprTS = "pepr.ts"; let outputDir: string = "dist"; export type Reloader = (opts: BuildResult) => void | Promise; diff --git a/src/lib/assets/index.ts b/src/lib/assets/index.ts index 3cb42fcef..c699d6070 100644 --- a/src/lib/assets/index.ts +++ b/src/lib/assets/index.ts @@ -11,7 +11,7 @@ import { deploy } from "./deploy"; import { loadCapabilities } from "./loader"; import { allYaml, zarfYaml, overridesFile, zarfYamlChart } from "./yaml"; import { namespaceComplianceValidator, replaceString } from "../helpers"; -import { createDirectoryIfNotExists, dedent } from "../helpers"; +import { dedent } from "../helpers"; import { resolve } from "path"; import { chartYaml, @@ -27,6 +27,7 @@ import { apiTokenSecret, service, tlsSecret, watcherService } from "./networking import { watcher, moduleSecret } from "./pods"; import { clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "./rbac"; +import { createDirectoryIfNotExists } from "../filesystemService"; export class Assets { readonly name: string; readonly tls: TLSOut; diff --git a/src/lib/filesystemService.test.ts b/src/lib/filesystemService.test.ts new file mode 100644 index 000000000..da00e4840 --- /dev/null +++ b/src/lib/filesystemService.test.ts @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023-Present The Pepr Authors + +import { describe, jest, expect, it } from "@jest/globals"; +import { createDirectoryIfNotExists } from "./filesystemService"; +import { promises as fs } from "fs"; + +jest.mock("fs", () => { + return { + promises: { + access: jest.fn(), + mkdir: jest.fn(), + }, + }; +}); + +describe("createDirectoryIfNotExists function", () => { + it("should create a directory if it doesn't exist", async () => { + (fs.access as jest.Mock).mockRejectedValue({ code: "ENOENT" } as never); + (fs.mkdir as jest.Mock).mockResolvedValue(undefined as never); + + const directoryPath = "/pepr/pepr-test-module/asdf"; + + await createDirectoryIfNotExists(directoryPath); + + expect(fs.access).toHaveBeenCalledWith(directoryPath); + expect(fs.mkdir).toHaveBeenCalledWith(directoryPath, { recursive: true }); + }); + + it("should not create a directory if it already exists", async () => { + jest.resetAllMocks(); + (fs.access as jest.Mock).mockResolvedValue(undefined as never); + + const directoryPath = "/pepr/pepr-test-module/asdf"; + + await createDirectoryIfNotExists(directoryPath); + + expect(fs.access).toHaveBeenCalledWith(directoryPath); + expect(fs.mkdir).not.toHaveBeenCalled(); + }); + + it("should throw an error for other fs.access errors", async () => { + jest.resetAllMocks(); + (fs.access as jest.Mock).mockRejectedValue({ code: "ERROR" } as never); + + const directoryPath = "/pepr/pepr-test-module/asdf"; + + try { + await createDirectoryIfNotExists(directoryPath); + } catch (error) { + expect(error.code).toEqual("ERROR"); + } + }); +}); diff --git a/src/lib/filesystemService.ts b/src/lib/filesystemService.ts new file mode 100644 index 000000000..3a581d61f --- /dev/null +++ b/src/lib/filesystemService.ts @@ -0,0 +1,16 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023-Present The Pepr Authors + +import { promises } from "fs"; + +export async function createDirectoryIfNotExists(path: string) { + try { + await promises.access(path); + } catch (error) { + if (error.code === "ENOENT") { + await promises.mkdir(path, { recursive: true }); + } else { + throw error; + } + } +} diff --git a/src/lib/helpers.test.ts b/src/lib/helpers.test.ts index e093c24c4..e162ababa 100644 --- a/src/lib/helpers.test.ts +++ b/src/lib/helpers.test.ts @@ -6,7 +6,6 @@ import { Event } from "./enums"; import { addVerbIfNotExists, bindingAndCapabilityNSConflict, - createDirectoryIfNotExists, createRBACMap, filterNoMatchReason, dedent, @@ -26,7 +25,6 @@ import { import { sanitizeResourceName } from "../sdk/sdk"; import * as fc from "fast-check"; import { expect, describe, test, jest, beforeEach, afterEach } from "@jest/globals"; -import { promises as fs } from "fs"; import { SpiedFunction } from "jest-mock"; import { KubernetesObject, kind } from "kubernetes-fluent-client"; @@ -39,15 +37,6 @@ jest.mock("kubernetes-fluent-client", () => { }; }); -jest.mock("fs", () => { - return { - promises: { - access: jest.fn(), - mkdir: jest.fn(), - }, - }; -}); - const mockCapabilities: CapabilityExport[] = JSON.parse(`[ { "name": "hello-pepr", @@ -371,45 +360,6 @@ describe("addVerbIfNotExists", () => { }); }); -describe("createDirectoryIfNotExists function", () => { - test("should create a directory if it doesn't exist", async () => { - (fs.access as jest.Mock).mockRejectedValue({ code: "ENOENT" } as never); - (fs.mkdir as jest.Mock).mockResolvedValue(undefined as never); - - const directoryPath = "/pepr/pepr-test-module/asdf"; - - await createDirectoryIfNotExists(directoryPath); - - expect(fs.access).toHaveBeenCalledWith(directoryPath); - expect(fs.mkdir).toHaveBeenCalledWith(directoryPath, { recursive: true }); - }); - - test("should not create a directory if it already exists", async () => { - jest.resetAllMocks(); - (fs.access as jest.Mock).mockResolvedValue(undefined as never); - - const directoryPath = "/pepr/pepr-test-module/asdf"; - - await createDirectoryIfNotExists(directoryPath); - - expect(fs.access).toHaveBeenCalledWith(directoryPath); - expect(fs.mkdir).not.toHaveBeenCalled(); - }); - - test("should throw an error for other fs.access errors", async () => { - jest.resetAllMocks(); - (fs.access as jest.Mock).mockRejectedValue({ code: "ERROR" } as never); - - const directoryPath = "/pepr/pepr-test-module/asdf"; - - try { - await createDirectoryIfNotExists(directoryPath); - } catch (error) { - expect(error.code).toEqual("ERROR"); - } - }); -}); - describe("hasAnyOverlap", () => { test("returns true for overlapping arrays", () => { expect(hasAnyOverlap([1, 2, 3], [3, 4, 5])).toBe(true); diff --git a/src/lib/helpers.ts b/src/lib/helpers.ts index 1709909f9..356abc0b4 100644 --- a/src/lib/helpers.ts +++ b/src/lib/helpers.ts @@ -1,7 +1,6 @@ // SPDX-License-Identifier: Apache-2.0 // SPDX-FileCopyrightText: 2023-Present The Pepr Authors -import { promises as fs } from "fs"; import { KubernetesObject } from "kubernetes-fluent-client"; import Log from "./logger"; import { Binding, CapabilityExport } from "./types"; @@ -191,18 +190,6 @@ export function createRBACMap(capabilities: CapabilityExport[]): RBACMap { }, {}); } -export async function createDirectoryIfNotExists(path: string) { - try { - await fs.access(path); - } catch (error) { - if (error.code === "ENOENT") { - await fs.mkdir(path, { recursive: true }); - } else { - throw error; - } - } -} - export function hasEveryOverlap(array1: T[], array2: T[]): boolean { if (!Array.isArray(array1) || !Array.isArray(array2)) { return false;