pepr 0.38.0-rc → 0.38.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +13 -13
- package/dist/controller.js +1 -1
- package/dist/fixtures/loader.d.ts +1 -1
- package/dist/fixtures/loader.d.ts.map +1 -1
- package/dist/lib/controller/index.d.ts +2 -1
- package/dist/lib/controller/index.d.ts.map +1 -1
- package/dist/lib/k8s.d.ts +1 -77
- package/dist/lib/k8s.d.ts.map +1 -1
- package/dist/lib.js.map +2 -2
- package/package.json +8 -6
- package/src/fixtures/loader.ts +1 -1
- package/src/lib/assets/pods.ts +6 -6
- package/src/lib/assets/yaml.ts +6 -6
- package/src/lib/controller/index.ts +2 -2
- package/src/lib/k8s.ts +1 -102
- package/dist/cli/init/utils.test.d.ts +0 -2
- package/dist/cli/init/utils.test.d.ts.map +0 -1
- package/dist/cli/init/walkthrough.test.d.ts +0 -2
- package/dist/cli/init/walkthrough.test.d.ts.map +0 -1
- package/dist/lib/adjudicators.test.d.ts +0 -2
- package/dist/lib/adjudicators.test.d.ts.map +0 -1
- package/dist/lib/assets/helm.test.d.ts +0 -2
- package/dist/lib/assets/helm.test.d.ts.map +0 -1
- package/dist/lib/assets/pods.test.d.ts +0 -2
- package/dist/lib/assets/pods.test.d.ts.map +0 -1
- package/dist/lib/capability.test.d.ts +0 -2
- package/dist/lib/capability.test.d.ts.map +0 -1
- package/dist/lib/controller/store.test.d.ts +0 -2
- package/dist/lib/controller/store.test.d.ts.map +0 -1
- package/dist/lib/errors.test.d.ts +0 -2
- package/dist/lib/errors.test.d.ts.map +0 -1
- package/dist/lib/filter.test.d.ts +0 -3
- package/dist/lib/filter.test.d.ts.map +0 -1
- package/dist/lib/finalizer.test.d.ts +0 -2
- package/dist/lib/finalizer.test.d.ts.map +0 -1
- package/dist/lib/helpers.test.d.ts +0 -2
- package/dist/lib/helpers.test.d.ts.map +0 -1
- package/dist/lib/included-files.test.d.ts +0 -2
- package/dist/lib/included-files.test.d.ts.map +0 -1
- package/dist/lib/logger.test.d.ts +0 -2
- package/dist/lib/logger.test.d.ts.map +0 -1
- package/dist/lib/metrics.test.d.ts +0 -2
- package/dist/lib/metrics.test.d.ts.map +0 -1
- package/dist/lib/module.test.d.ts +0 -2
- package/dist/lib/module.test.d.ts.map +0 -1
- package/dist/lib/mutate-request.test.d.ts +0 -2
- package/dist/lib/mutate-request.test.d.ts.map +0 -1
- package/dist/lib/queue.test.d.ts +0 -2
- package/dist/lib/queue.test.d.ts.map +0 -1
- package/dist/lib/schedule.test.d.ts +0 -15
- package/dist/lib/schedule.test.d.ts.map +0 -1
- package/dist/lib/storage.test.d.ts +0 -2
- package/dist/lib/storage.test.d.ts.map +0 -1
- package/dist/lib/tls.test.d.ts +0 -2
- package/dist/lib/tls.test.d.ts.map +0 -1
- package/dist/lib/utils.test.d.ts +0 -2
- package/dist/lib/utils.test.d.ts.map +0 -1
- package/dist/lib/validate-request.test.d.ts +0 -2
- package/dist/lib/validate-request.test.d.ts.map +0 -1
- package/dist/lib/watch-processor.test.d.ts +0 -2
- package/dist/lib/watch-processor.test.d.ts.map +0 -1
- package/dist/sdk/sdk.test.d.ts +0 -2
- package/dist/sdk/sdk.test.d.ts.map +0 -1
- package/src/cli/init/utils.test.ts +0 -19
- package/src/cli/init/walkthrough.test.ts +0 -102
- package/src/lib/adjudicators.test.ts +0 -1236
- package/src/lib/assets/helm.test.ts +0 -64
- package/src/lib/assets/pods.test.ts +0 -553
- package/src/lib/capability.test.ts +0 -655
- package/src/lib/controller/store.test.ts +0 -131
- package/src/lib/errors.test.ts +0 -85
- package/src/lib/filter.test.ts +0 -691
- package/src/lib/finalizer.test.ts +0 -236
- package/src/lib/helpers.test.ts +0 -1486
- package/src/lib/included-files.test.ts +0 -22
- package/src/lib/logger.test.ts +0 -18
- package/src/lib/metrics.test.ts +0 -132
- package/src/lib/module.test.ts +0 -126
- package/src/lib/mutate-request.test.ts +0 -187
- package/src/lib/queue.test.ts +0 -152
- package/src/lib/schedule.test.ts +0 -217
- package/src/lib/storage.test.ts +0 -216
- package/src/lib/tls.test.ts +0 -18
- package/src/lib/utils.test.ts +0 -69
- package/src/lib/validate-request.test.ts +0 -121
- package/src/lib/watch-processor.test.ts +0 -418
- package/src/sdk/sdk.test.ts +0 -276
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
-
|
|
4
|
-
import { createDockerfile } from "./included-files";
|
|
5
|
-
import { expect, describe, test } from "@jest/globals";
|
|
6
|
-
import { promises as fs } from "fs";
|
|
7
|
-
|
|
8
|
-
describe("createDockerfile", () => {
|
|
9
|
-
const version = "0.0.1";
|
|
10
|
-
const description = "Pepr supports WASM modules!";
|
|
11
|
-
const includedFiles = ["main.wasm", "wasm_exec.js"];
|
|
12
|
-
test("should create a Dockerfile.controller with the correct content", async () => {
|
|
13
|
-
await createDockerfile(version, description, includedFiles);
|
|
14
|
-
|
|
15
|
-
const generatedContent = await fs.readFile("Dockerfile.controller", "utf-8");
|
|
16
|
-
expect(generatedContent).toContain(`FROM ghcr.io/defenseunicorns/pepr/controller:v${version}`);
|
|
17
|
-
expect(generatedContent).toContain(`LABEL description="${description}"`);
|
|
18
|
-
includedFiles.forEach(file => {
|
|
19
|
-
expect(generatedContent).toContain(`ADD ${file} ${file}`);
|
|
20
|
-
});
|
|
21
|
-
});
|
|
22
|
-
});
|
package/src/lib/logger.test.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
-
|
|
4
|
-
import { beforeEach, describe, expect, it, jest } from "@jest/globals";
|
|
5
|
-
|
|
6
|
-
describe("Logger", () => {
|
|
7
|
-
beforeEach(() => {
|
|
8
|
-
jest.resetModules(); // Clear the cache for modules
|
|
9
|
-
process.env = {}; // Clear environment variables
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it("should set log level based on LOG_LEVEL environment variable", async () => {
|
|
13
|
-
process.env.LOG_LEVEL = "debug";
|
|
14
|
-
const { default: logger } = await import("./logger");
|
|
15
|
-
|
|
16
|
-
expect(logger.level).toBe("debug");
|
|
17
|
-
});
|
|
18
|
-
});
|
package/src/lib/metrics.test.ts
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
-
|
|
4
|
-
import { expect, test } from "@jest/globals";
|
|
5
|
-
import { performance } from "perf_hooks";
|
|
6
|
-
|
|
7
|
-
import { MetricsCollector } from "./metrics";
|
|
8
|
-
|
|
9
|
-
test("constructor initializes counters correctly", () => {
|
|
10
|
-
const collector = new MetricsCollector("testPrefix");
|
|
11
|
-
|
|
12
|
-
expect(collector).toBeTruthy();
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
test("error method increments error counter", async () => {
|
|
16
|
-
const collector = new MetricsCollector("testPrefix");
|
|
17
|
-
|
|
18
|
-
collector.error();
|
|
19
|
-
|
|
20
|
-
const metrics = await collector.getMetrics();
|
|
21
|
-
expect(metrics).toMatch(/testPrefix_errors 1/);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
test("alert method increments alerts counter", async () => {
|
|
25
|
-
const collector = new MetricsCollector("testPrefix");
|
|
26
|
-
|
|
27
|
-
collector.alert();
|
|
28
|
-
|
|
29
|
-
const metrics = await collector.getMetrics();
|
|
30
|
-
expect(metrics).toMatch(/testPrefix_alerts 1/);
|
|
31
|
-
});
|
|
32
|
-
|
|
33
|
-
test("observeStart returns current timestamp", () => {
|
|
34
|
-
const timeBefore = performance.now();
|
|
35
|
-
const startTime = MetricsCollector.observeStart();
|
|
36
|
-
const timeAfter = performance.now();
|
|
37
|
-
|
|
38
|
-
expect(timeBefore <= startTime).toBe(true);
|
|
39
|
-
expect(timeAfter >= startTime).toBe(true);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
test("observeEnd updates summary", async () => {
|
|
43
|
-
const collector = new MetricsCollector("testPrefix");
|
|
44
|
-
|
|
45
|
-
const startTime = MetricsCollector.observeStart();
|
|
46
|
-
await new Promise(resolve => setTimeout(resolve, 100)); // Delay to simulate operation
|
|
47
|
-
collector.observeEnd(startTime);
|
|
48
|
-
|
|
49
|
-
await new Promise(resolve => setTimeout(resolve, 100)); // Delay to simulate operation
|
|
50
|
-
collector.observeEnd(startTime, "validate");
|
|
51
|
-
collector.observeEnd(startTime, "validate");
|
|
52
|
-
|
|
53
|
-
const metrics = await collector.getMetrics();
|
|
54
|
-
expect(metrics).toMatch(/testPrefix_mutate_count 1/);
|
|
55
|
-
expect(metrics).toMatch(/testPrefix_mutate_sum \d+\.\d+/);
|
|
56
|
-
|
|
57
|
-
expect(metrics).toMatch(/testPrefix_validate_count 2/);
|
|
58
|
-
expect(metrics).toMatch(/testPrefix_validate_sum \d+\.\d+/);
|
|
59
|
-
});
|
|
60
|
-
|
|
61
|
-
test("coverage tests, with duplicate counters, default prefix (pepr) and still works properly", async () => {
|
|
62
|
-
const collector = new MetricsCollector();
|
|
63
|
-
collector.addCounter("testCounter", "testHelp");
|
|
64
|
-
// second one should log, but still work fine TODO: validate log
|
|
65
|
-
collector.addCounter("testCounter", "testHelp");
|
|
66
|
-
let metrics = await collector.getMetrics();
|
|
67
|
-
expect(metrics).toMatch(/pepr_testCounter 0/);
|
|
68
|
-
collector.incCounter("testCounter");
|
|
69
|
-
metrics = await collector.getMetrics();
|
|
70
|
-
expect(metrics).toMatch(/pepr_testCounter 1/);
|
|
71
|
-
collector.addSummary("testSummary", "testHelp");
|
|
72
|
-
// second one should log, but still work fine TODO: validate log
|
|
73
|
-
collector.addSummary("testSummary", "testHelp");
|
|
74
|
-
const startTime = MetricsCollector.observeStart();
|
|
75
|
-
|
|
76
|
-
await new Promise(resolve => setTimeout(resolve, 100)); // Delay to simulate operation
|
|
77
|
-
collector.observeEnd(startTime, "testSummary");
|
|
78
|
-
collector.observeEnd(startTime, "testSummary");
|
|
79
|
-
metrics = await collector.getMetrics();
|
|
80
|
-
expect(metrics).toMatch(/pepr_testSummary_count 2/);
|
|
81
|
-
expect(metrics).toMatch(/pepr_testSummary_sum \d+\.\d+/);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
test("incCacheMiss increments cache miss gauge", async () => {
|
|
85
|
-
const collector = new MetricsCollector("testPrefix");
|
|
86
|
-
|
|
87
|
-
collector.incCacheMiss("window1");
|
|
88
|
-
|
|
89
|
-
const metrics = await collector.getMetrics();
|
|
90
|
-
expect(metrics).toMatch(/testPrefix_cache_miss{window="window1"} 1/);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
test("incRetryCount increments retry count gauge", async () => {
|
|
94
|
-
const collector = new MetricsCollector("testPrefix");
|
|
95
|
-
|
|
96
|
-
collector.incRetryCount("1");
|
|
97
|
-
|
|
98
|
-
const metrics = await collector.getMetrics();
|
|
99
|
-
expect(metrics).toMatch(/testPrefix_resync_failure_count{count="1"} 1/);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
test("initCacheMissWindow initializes cache miss gauge to zero", async () => {
|
|
103
|
-
const collector = new MetricsCollector("testPrefix");
|
|
104
|
-
|
|
105
|
-
collector.initCacheMissWindow("window1");
|
|
106
|
-
|
|
107
|
-
const metrics = await collector.getMetrics();
|
|
108
|
-
expect(metrics).toMatch(/testPrefix_cache_miss{window="window1"} 0/);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
test("should initialize cache miss window and maintain size limit", async () => {
|
|
112
|
-
process.env.PEPR_MAX_CACHE_MISS_WINDOWS = "3";
|
|
113
|
-
const collector = new MetricsCollector("pepr");
|
|
114
|
-
collector.initCacheMissWindow("window1");
|
|
115
|
-
collector.initCacheMissWindow("window2");
|
|
116
|
-
collector.initCacheMissWindow("window3");
|
|
117
|
-
collector.initCacheMissWindow("window4");
|
|
118
|
-
|
|
119
|
-
const metrics = await collector.getMetrics();
|
|
120
|
-
expect(metrics).not.toContain("window1");
|
|
121
|
-
expect(metrics).toContain("window4");
|
|
122
|
-
|
|
123
|
-
collector.initCacheMissWindow("window5");
|
|
124
|
-
collector.initCacheMissWindow("window6");
|
|
125
|
-
collector.initCacheMissWindow("window7");
|
|
126
|
-
|
|
127
|
-
const updatedMetrics = await collector.getMetrics();
|
|
128
|
-
expect(updatedMetrics).not.toContain("window4");
|
|
129
|
-
expect(updatedMetrics).toContain("window5");
|
|
130
|
-
expect(updatedMetrics).toContain("window6");
|
|
131
|
-
expect(updatedMetrics).toContain("window7");
|
|
132
|
-
});
|
package/src/lib/module.test.ts
DELETED
|
@@ -1,126 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
-
|
|
4
|
-
import { beforeEach, expect, jest, test, describe } from "@jest/globals";
|
|
5
|
-
import { clone } from "ramda";
|
|
6
|
-
import { Capability } from "./capability";
|
|
7
|
-
import { Schedule } from "./schedule";
|
|
8
|
-
import { Errors } from "./errors";
|
|
9
|
-
import { PackageJSON, PeprModule } from "./module";
|
|
10
|
-
import { CapabilityExport } from "./types";
|
|
11
|
-
|
|
12
|
-
// Mock Controller
|
|
13
|
-
const startServerMock = jest.fn();
|
|
14
|
-
jest.mock("./controller", () => {
|
|
15
|
-
return {
|
|
16
|
-
Controller: jest.fn().mockImplementation(() => {
|
|
17
|
-
return { startServer: startServerMock };
|
|
18
|
-
}),
|
|
19
|
-
};
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
// Reset the mocks before each test
|
|
23
|
-
beforeEach(() => {
|
|
24
|
-
jest.clearAllMocks();
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
// Mock PackageJSON
|
|
28
|
-
const packageJSON: PackageJSON = {
|
|
29
|
-
description: "Test Description",
|
|
30
|
-
pepr: {
|
|
31
|
-
uuid: "20e17cf6-a2e4-46b2-b626-75d88d96c88b",
|
|
32
|
-
description: "Development module for pepr",
|
|
33
|
-
onError: "ignore",
|
|
34
|
-
alwaysIgnore: {
|
|
35
|
-
namespaces: [],
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
test("should instantiate Controller and start it with the default port", () => {
|
|
41
|
-
new PeprModule(packageJSON);
|
|
42
|
-
expect(startServerMock).toHaveBeenCalledWith(3000);
|
|
43
|
-
});
|
|
44
|
-
|
|
45
|
-
test("should instantiate Controller and start it with the specified port", () => {
|
|
46
|
-
const module = new PeprModule(packageJSON, [], { deferStart: true });
|
|
47
|
-
const port = Math.floor(Math.random() * 10000) + 1000;
|
|
48
|
-
module.start(port);
|
|
49
|
-
expect(startServerMock).toHaveBeenCalledWith(port);
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
test("should not start if deferStart is true", () => {
|
|
53
|
-
new PeprModule(packageJSON, [], { deferStart: true });
|
|
54
|
-
expect(startServerMock).not.toHaveBeenCalled();
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
test("should reject invalid pepr onError conditions", () => {
|
|
58
|
-
const cfg = clone(packageJSON);
|
|
59
|
-
cfg.pepr.onError = "invalidError";
|
|
60
|
-
expect(() => new PeprModule(cfg)).toThrow();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
test("should allow valid pepr onError conditions", () => {
|
|
64
|
-
const cfg = clone(packageJSON);
|
|
65
|
-
cfg.pepr.onError = Errors.audit;
|
|
66
|
-
expect(() => new PeprModule(cfg)).not.toThrow();
|
|
67
|
-
|
|
68
|
-
cfg.pepr.onError = Errors.ignore;
|
|
69
|
-
expect(() => new PeprModule(cfg)).not.toThrow();
|
|
70
|
-
|
|
71
|
-
cfg.pepr.onError = Errors.reject;
|
|
72
|
-
expect(() => new PeprModule(cfg)).not.toThrow();
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
test("should not create a controller if PEPR_MODE is set to build", () => {
|
|
76
|
-
process.env.PEPR_MODE = "build";
|
|
77
|
-
new PeprModule(packageJSON);
|
|
78
|
-
expect(startServerMock).not.toHaveBeenCalled();
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
test("should send the capabilities to the parent process if PEPR_MODE is set to build", () => {
|
|
82
|
-
const sendMock = jest.spyOn(process, "send").mockImplementation(() => true);
|
|
83
|
-
process.env.PEPR_MODE = "build";
|
|
84
|
-
|
|
85
|
-
const capability = new Capability({
|
|
86
|
-
name: "test",
|
|
87
|
-
description: "test",
|
|
88
|
-
});
|
|
89
|
-
|
|
90
|
-
const expected: CapabilityExport = {
|
|
91
|
-
name: capability.name,
|
|
92
|
-
description: capability.description,
|
|
93
|
-
namespaces: capability.namespaces,
|
|
94
|
-
bindings: capability.bindings,
|
|
95
|
-
hasSchedule: capability.hasSchedule,
|
|
96
|
-
};
|
|
97
|
-
|
|
98
|
-
new PeprModule(packageJSON, [capability]);
|
|
99
|
-
expect(sendMock).toHaveBeenCalledWith([expected]);
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
describe("Capability", () => {
|
|
103
|
-
let capability: Capability;
|
|
104
|
-
let schedule: Schedule;
|
|
105
|
-
|
|
106
|
-
beforeEach(() => {
|
|
107
|
-
capability = new Capability({
|
|
108
|
-
name: "test",
|
|
109
|
-
description: "test",
|
|
110
|
-
});
|
|
111
|
-
schedule = {
|
|
112
|
-
name: "test-name",
|
|
113
|
-
every: 1,
|
|
114
|
-
unit: "seconds",
|
|
115
|
-
run: jest.fn(),
|
|
116
|
-
startTime: new Date(),
|
|
117
|
-
completions: 1,
|
|
118
|
-
};
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
test("should handle OnSchedule", () => {
|
|
122
|
-
const { OnSchedule } = capability;
|
|
123
|
-
OnSchedule(schedule);
|
|
124
|
-
expect(capability.hasSchedule).toBe(true);
|
|
125
|
-
});
|
|
126
|
-
});
|
|
@@ -1,187 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
-
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
-
|
|
4
|
-
import { beforeEach, describe, expect, it } from "@jest/globals";
|
|
5
|
-
import { KubernetesObject } from "kubernetes-fluent-client";
|
|
6
|
-
import { Operation, AdmissionRequest } from "./types";
|
|
7
|
-
import { PeprMutateRequest } from "./mutate-request";
|
|
8
|
-
|
|
9
|
-
describe("PeprMutateRequest", () => {
|
|
10
|
-
let mockRequest: AdmissionRequest<KubernetesObject>;
|
|
11
|
-
|
|
12
|
-
beforeEach(() => {
|
|
13
|
-
mockRequest = {
|
|
14
|
-
operation: Operation.CREATE,
|
|
15
|
-
object: {
|
|
16
|
-
apiVersion: "v1",
|
|
17
|
-
kind: "Pod",
|
|
18
|
-
metadata: {
|
|
19
|
-
name: "test-pod",
|
|
20
|
-
labels: {
|
|
21
|
-
"existing-label": "true",
|
|
22
|
-
},
|
|
23
|
-
annotations: {
|
|
24
|
-
"existing-annotation": "true",
|
|
25
|
-
},
|
|
26
|
-
},
|
|
27
|
-
},
|
|
28
|
-
dryRun: false,
|
|
29
|
-
uid: "test-uid",
|
|
30
|
-
name: "test-pod",
|
|
31
|
-
kind: { group: "", version: "v1", kind: "Pod" },
|
|
32
|
-
resource: { group: "", version: "v1", resource: "pods" },
|
|
33
|
-
userInfo: {},
|
|
34
|
-
};
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("should initialize correctly for non-DELETE operations", () => {
|
|
38
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
39
|
-
expect(wrapper.Raw).toEqual(mockRequest.object);
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
it("should initialize correctly for DELETE operations", () => {
|
|
43
|
-
mockRequest = {
|
|
44
|
-
...mockRequest,
|
|
45
|
-
operation: Operation.DELETE,
|
|
46
|
-
oldObject: {
|
|
47
|
-
apiVersion: "v1",
|
|
48
|
-
kind: "Pod",
|
|
49
|
-
metadata: {
|
|
50
|
-
name: "test-pod",
|
|
51
|
-
},
|
|
52
|
-
},
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
56
|
-
expect(wrapper.Raw).toEqual(mockRequest.oldObject);
|
|
57
|
-
});
|
|
58
|
-
|
|
59
|
-
it("should provide correct value for PermitSideEffects", () => {
|
|
60
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
61
|
-
expect(wrapper.PermitSideEffects).toEqual(true);
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("should provide correct value for IsDryRun", () => {
|
|
65
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
66
|
-
expect(wrapper.IsDryRun).toEqual(false);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
it("should provide access to old resource", () => {
|
|
70
|
-
mockRequest = {
|
|
71
|
-
...mockRequest,
|
|
72
|
-
oldObject: {
|
|
73
|
-
apiVersion: "v1",
|
|
74
|
-
kind: "Pod",
|
|
75
|
-
metadata: {
|
|
76
|
-
name: "old-test-pod",
|
|
77
|
-
},
|
|
78
|
-
},
|
|
79
|
-
};
|
|
80
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
81
|
-
expect(wrapper.OldResource).toEqual(mockRequest.oldObject);
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
it("should provide access to the request object", () => {
|
|
85
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
86
|
-
expect(wrapper.Request).toEqual(mockRequest);
|
|
87
|
-
});
|
|
88
|
-
|
|
89
|
-
it("should throw an error if the request object is not available", () => {
|
|
90
|
-
mockRequest = {
|
|
91
|
-
...mockRequest,
|
|
92
|
-
object: undefined as unknown as KubernetesObject,
|
|
93
|
-
};
|
|
94
|
-
|
|
95
|
-
expect(() => new PeprMutateRequest(mockRequest)).toThrow("unable to load the request object into PeprRequest.RawP");
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
it("should merge the provided object with the current resource", () => {
|
|
99
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
100
|
-
wrapper.Merge({
|
|
101
|
-
metadata: {
|
|
102
|
-
labels: {
|
|
103
|
-
"test-label-2": "true",
|
|
104
|
-
},
|
|
105
|
-
},
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
expect(wrapper.Raw.metadata?.labels).toEqual({
|
|
109
|
-
"existing-label": "true",
|
|
110
|
-
"test-label-2": "true",
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
|
|
114
|
-
it("should set a label", () => {
|
|
115
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
116
|
-
wrapper.SetLabel("new-label", "newValue");
|
|
117
|
-
expect(wrapper.Raw.metadata?.labels?.["new-label"]).toEqual("newValue");
|
|
118
|
-
});
|
|
119
|
-
|
|
120
|
-
it("should set an annotation", () => {
|
|
121
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
122
|
-
wrapper.SetAnnotation("new-annotation", "newValue");
|
|
123
|
-
expect(wrapper.Raw.metadata?.annotations?.["new-annotation"]).toEqual("newValue");
|
|
124
|
-
});
|
|
125
|
-
|
|
126
|
-
it("should remove an existing label", () => {
|
|
127
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
128
|
-
wrapper.RemoveLabel("existing-label");
|
|
129
|
-
expect(wrapper.Raw.metadata?.labels?.["existing-label"]).toBeUndefined();
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
it("should remove an existing annotation", () => {
|
|
133
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
134
|
-
wrapper.RemoveAnnotation("existing-annotation");
|
|
135
|
-
expect(wrapper.Raw.metadata?.annotations?.["existing-annotation"]).toBeUndefined();
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
it("should check if a label exists", () => {
|
|
139
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
140
|
-
expect(wrapper.HasLabel("existing-label")).toBeTruthy();
|
|
141
|
-
expect(wrapper.HasLabel("non-existent-label")).toBeFalsy();
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
it("should check if an annotation exists", () => {
|
|
145
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
146
|
-
expect(wrapper.HasAnnotation("existing-annotation")).toBeTruthy();
|
|
147
|
-
expect(wrapper.HasAnnotation("non-existent-annotation")).toBeFalsy();
|
|
148
|
-
});
|
|
149
|
-
|
|
150
|
-
it("should set a label when metadata and labels do not exist", () => {
|
|
151
|
-
delete mockRequest.object.metadata;
|
|
152
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
153
|
-
wrapper.SetLabel("new-label", "newValue");
|
|
154
|
-
expect(wrapper.Raw.metadata?.labels?.["new-label"]).toEqual("newValue");
|
|
155
|
-
});
|
|
156
|
-
|
|
157
|
-
it("should set an annotation when metadata and annotations do not exist", () => {
|
|
158
|
-
delete mockRequest.object.metadata;
|
|
159
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
160
|
-
wrapper.SetAnnotation("new-annotation", "newValue");
|
|
161
|
-
expect(wrapper.Raw.metadata?.annotations?.["new-annotation"]).toEqual("newValue");
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
it("should not throw an error when removing a non-existent label", () => {
|
|
165
|
-
delete mockRequest.object.metadata;
|
|
166
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
167
|
-
expect(() => wrapper.RemoveLabel("non-existent-label")).not.toThrow();
|
|
168
|
-
});
|
|
169
|
-
|
|
170
|
-
it("should not throw an error when removing a non-existent annotation", () => {
|
|
171
|
-
delete mockRequest.object.metadata;
|
|
172
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
173
|
-
expect(() => wrapper.RemoveAnnotation("non-existent-annotation")).not.toThrow();
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
it("should return false for HasLabel when metadata or labels do not exist", () => {
|
|
177
|
-
delete mockRequest.object.metadata;
|
|
178
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
179
|
-
expect(wrapper.HasLabel("any-label")).toBeFalsy();
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
it("should return false for HasAnnotation when metadata or annotations do not exist", () => {
|
|
183
|
-
delete mockRequest.object.metadata;
|
|
184
|
-
const wrapper = new PeprMutateRequest(mockRequest);
|
|
185
|
-
expect(wrapper.HasAnnotation("any-annotation")).toBeFalsy();
|
|
186
|
-
});
|
|
187
|
-
});
|
package/src/lib/queue.test.ts
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
import { afterEach, describe, expect, jest, it } from "@jest/globals";
|
|
2
|
-
import { WatchPhase } from "kubernetes-fluent-client/dist/fluent/types";
|
|
3
|
-
import { Queue } from "./queue";
|
|
4
|
-
|
|
5
|
-
import Log from "./logger";
|
|
6
|
-
jest.mock("./logger");
|
|
7
|
-
|
|
8
|
-
describe("Queue", () => {
|
|
9
|
-
afterEach(() => {
|
|
10
|
-
jest.resetAllMocks();
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it("is uniquely identifiable", () => {
|
|
14
|
-
const name = "kind/namespace";
|
|
15
|
-
const queue = new Queue(name);
|
|
16
|
-
|
|
17
|
-
const label = queue.label();
|
|
18
|
-
|
|
19
|
-
expect(label).toEqual(
|
|
20
|
-
expect.objectContaining({
|
|
21
|
-
// given name of queue
|
|
22
|
-
name,
|
|
23
|
-
|
|
24
|
-
// unique, generated value (to disambiguate similarly-named queues)
|
|
25
|
-
// <epoch timestamp (ms)>-<4 char hex>
|
|
26
|
-
uid: expect.stringMatching(/[0-9]{13}-[0-9a-f]{4}/),
|
|
27
|
-
}),
|
|
28
|
-
);
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
it("exposes runtime stats", async () => {
|
|
32
|
-
const name = "kind/namespace";
|
|
33
|
-
const queue = new Queue(name);
|
|
34
|
-
|
|
35
|
-
expect(queue.stats()).toEqual(
|
|
36
|
-
expect.objectContaining({
|
|
37
|
-
queue: queue.label(),
|
|
38
|
-
stats: { length: 0 },
|
|
39
|
-
}),
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
const kubeObj = { metadata: { name: "test-nm", namespace: "test-ns" } };
|
|
43
|
-
const watchCb = () =>
|
|
44
|
-
new Promise<void>(res => {
|
|
45
|
-
setTimeout(res, 100);
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
await Promise.all([
|
|
49
|
-
queue.enqueue(kubeObj, WatchPhase.Added, watchCb),
|
|
50
|
-
queue.enqueue(kubeObj, WatchPhase.Added, watchCb),
|
|
51
|
-
queue.enqueue(kubeObj, WatchPhase.Added, watchCb),
|
|
52
|
-
queue.enqueue(kubeObj, WatchPhase.Added, watchCb),
|
|
53
|
-
]);
|
|
54
|
-
|
|
55
|
-
const logDebug = Log.debug as jest.Mock;
|
|
56
|
-
const stats = logDebug.mock.calls
|
|
57
|
-
.flat()
|
|
58
|
-
.map(m => JSON.stringify(m))
|
|
59
|
-
.filter(m => m.includes('"stats":'));
|
|
60
|
-
|
|
61
|
-
[
|
|
62
|
-
'"length":1', // 1st entry runs near-immediately, so queue won't fill
|
|
63
|
-
'"length":1', // afterward, queue fills & unfills as callbacks process
|
|
64
|
-
'"length":2',
|
|
65
|
-
'"length":3',
|
|
66
|
-
'"length":3',
|
|
67
|
-
'"length":2',
|
|
68
|
-
'"length":1',
|
|
69
|
-
'"length":0',
|
|
70
|
-
].map((exp, idx) => {
|
|
71
|
-
expect(stats[idx]).toEqual(expect.stringContaining(exp));
|
|
72
|
-
});
|
|
73
|
-
});
|
|
74
|
-
|
|
75
|
-
it("resolves when an enqueued event dequeues without error", async () => {
|
|
76
|
-
const name = "kind/namespace";
|
|
77
|
-
const queue = new Queue(name);
|
|
78
|
-
|
|
79
|
-
const kubeObj = { metadata: { name: "test-nm", namespace: "test-ns" } };
|
|
80
|
-
const watchCb = () =>
|
|
81
|
-
new Promise<void>(res => {
|
|
82
|
-
setTimeout(res, 10);
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
const promise = queue.enqueue(kubeObj, WatchPhase.Added, watchCb);
|
|
86
|
-
expect(promise).toBeInstanceOf(Promise);
|
|
87
|
-
|
|
88
|
-
await expect(promise).resolves.not.toThrow();
|
|
89
|
-
});
|
|
90
|
-
|
|
91
|
-
it("rejects when an enqueued event dequeues with error", async () => {
|
|
92
|
-
const name = "kind/namespace";
|
|
93
|
-
const queue = new Queue(name);
|
|
94
|
-
|
|
95
|
-
const kubeObj = { metadata: { name: "test-nm", namespace: "test-ns" } };
|
|
96
|
-
const watchCb = () =>
|
|
97
|
-
new Promise<void>((_, reject) => {
|
|
98
|
-
setTimeout(() => {
|
|
99
|
-
reject("oof");
|
|
100
|
-
}, 10);
|
|
101
|
-
});
|
|
102
|
-
|
|
103
|
-
const promise = queue.enqueue(kubeObj, WatchPhase.Added, watchCb);
|
|
104
|
-
expect(promise).toBeInstanceOf(Promise);
|
|
105
|
-
|
|
106
|
-
await expect(promise).rejects.toBe("oof");
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
it("processes events in FIFO order", async () => {
|
|
110
|
-
const name = "kind/namespace";
|
|
111
|
-
const queue = new Queue(name);
|
|
112
|
-
|
|
113
|
-
const kubeObj = { metadata: { name: "test-nm", namespace: "test-ns" } };
|
|
114
|
-
const watchA = () =>
|
|
115
|
-
new Promise<void>(resolve => {
|
|
116
|
-
setTimeout(() => {
|
|
117
|
-
Log.info("watchA");
|
|
118
|
-
resolve();
|
|
119
|
-
}, 15);
|
|
120
|
-
});
|
|
121
|
-
const watchB = () =>
|
|
122
|
-
new Promise<void>(resolve => {
|
|
123
|
-
setTimeout(() => {
|
|
124
|
-
Log.info("watchB");
|
|
125
|
-
resolve();
|
|
126
|
-
}, 10);
|
|
127
|
-
});
|
|
128
|
-
const watchC = () =>
|
|
129
|
-
new Promise<void>(resolve => {
|
|
130
|
-
setTimeout(() => {
|
|
131
|
-
Log.info("watchC");
|
|
132
|
-
resolve();
|
|
133
|
-
}, 5);
|
|
134
|
-
});
|
|
135
|
-
|
|
136
|
-
await Promise.all([
|
|
137
|
-
queue.enqueue(kubeObj, WatchPhase.Added, watchA),
|
|
138
|
-
queue.enqueue(kubeObj, WatchPhase.Added, watchB),
|
|
139
|
-
queue.enqueue(kubeObj, WatchPhase.Added, watchC),
|
|
140
|
-
]);
|
|
141
|
-
|
|
142
|
-
const logInfo = Log.info as jest.Mock;
|
|
143
|
-
const calls = logInfo.mock.calls
|
|
144
|
-
.flat()
|
|
145
|
-
.map(m => JSON.stringify(m))
|
|
146
|
-
.filter(m => /"watch[ABC]"/.test(m));
|
|
147
|
-
|
|
148
|
-
['"watchA"', '"watchB"', '"watchC"'].map((exp, idx) => {
|
|
149
|
-
expect(calls[idx]).toEqual(expect.stringContaining(exp));
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
});
|