pepr 0.33.0 → 0.34.0

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.
Files changed (140) hide show
  1. package/README.md +2 -1
  2. package/dist/cli/banner.d.ts +2 -0
  3. package/dist/cli/banner.d.ts.map +1 -0
  4. package/dist/cli/build.d.ts +19 -0
  5. package/dist/cli/build.d.ts.map +1 -0
  6. package/dist/cli/deploy.d.ts +3 -0
  7. package/dist/cli/deploy.d.ts.map +1 -0
  8. package/dist/cli/dev.d.ts +3 -0
  9. package/dist/cli/dev.d.ts.map +1 -0
  10. package/dist/cli/format.d.ts +9 -0
  11. package/dist/cli/format.d.ts.map +1 -0
  12. package/dist/cli/init/index.d.ts +3 -0
  13. package/dist/cli/init/index.d.ts.map +1 -0
  14. package/dist/cli/init/templates.d.ts +196 -0
  15. package/dist/cli/init/templates.d.ts.map +1 -0
  16. package/dist/cli/init/utils.d.ts +21 -0
  17. package/dist/cli/init/utils.d.ts.map +1 -0
  18. package/dist/cli/init/utils.test.d.ts +2 -0
  19. package/dist/cli/init/utils.test.d.ts.map +1 -0
  20. package/dist/cli/init/walkthrough.d.ts +8 -0
  21. package/dist/cli/init/walkthrough.d.ts.map +1 -0
  22. package/dist/cli/init/walkthrough.test.d.ts +2 -0
  23. package/dist/cli/init/walkthrough.test.d.ts.map +1 -0
  24. package/dist/cli/kfc.d.ts +3 -0
  25. package/dist/cli/kfc.d.ts.map +1 -0
  26. package/dist/cli/monitor.d.ts +3 -0
  27. package/dist/cli/monitor.d.ts.map +1 -0
  28. package/dist/cli/root.d.ts +5 -0
  29. package/dist/cli/root.d.ts.map +1 -0
  30. package/dist/cli/update.d.ts +3 -0
  31. package/dist/cli/update.d.ts.map +1 -0
  32. package/dist/cli/uuid.d.ts +3 -0
  33. package/dist/cli/uuid.d.ts.map +1 -0
  34. package/dist/cli.js +68 -38
  35. package/dist/controller.js +1 -2
  36. package/dist/fixtures/loader.d.ts +5 -0
  37. package/dist/fixtures/loader.d.ts.map +1 -0
  38. package/dist/lib/assets/helm.d.ts +1 -0
  39. package/dist/lib/assets/helm.d.ts.map +1 -1
  40. package/dist/lib/assets/helm.test.d.ts +2 -0
  41. package/dist/lib/assets/helm.test.d.ts.map +1 -0
  42. package/dist/lib/assets/index.d.ts.map +1 -1
  43. package/dist/lib/assets/pods.d.ts +3 -0
  44. package/dist/lib/assets/pods.d.ts.map +1 -1
  45. package/dist/lib/assets/pods.test.d.ts +2 -0
  46. package/dist/lib/assets/pods.test.d.ts.map +1 -0
  47. package/dist/lib/assets/yaml.d.ts.map +1 -1
  48. package/dist/lib/errors.test.d.ts +2 -0
  49. package/dist/lib/errors.test.d.ts.map +1 -0
  50. package/dist/lib/filter.test.d.ts +2 -0
  51. package/dist/lib/filter.test.d.ts.map +1 -0
  52. package/dist/lib/helpers.d.ts +0 -5
  53. package/dist/lib/helpers.d.ts.map +1 -1
  54. package/dist/lib/helpers.test.d.ts +2 -0
  55. package/dist/lib/helpers.test.d.ts.map +1 -0
  56. package/dist/lib/included-files.test.d.ts +2 -0
  57. package/dist/lib/included-files.test.d.ts.map +1 -0
  58. package/dist/lib/logger.test.d.ts +2 -0
  59. package/dist/lib/logger.test.d.ts.map +1 -0
  60. package/dist/lib/metrics.d.ts +18 -0
  61. package/dist/lib/metrics.d.ts.map +1 -1
  62. package/dist/lib/metrics.test.d.ts +2 -0
  63. package/dist/lib/metrics.test.d.ts.map +1 -0
  64. package/dist/lib/module.test.d.ts +2 -0
  65. package/dist/lib/module.test.d.ts.map +1 -0
  66. package/dist/lib/mutate-request.test.d.ts +2 -0
  67. package/dist/lib/mutate-request.test.d.ts.map +1 -0
  68. package/dist/lib/queue.test.d.ts +2 -0
  69. package/dist/lib/queue.test.d.ts.map +1 -0
  70. package/dist/lib/schedule.test.d.ts +15 -0
  71. package/dist/lib/schedule.test.d.ts.map +1 -0
  72. package/dist/lib/storage.test.d.ts +2 -0
  73. package/dist/lib/storage.test.d.ts.map +1 -0
  74. package/dist/lib/tls.test.d.ts +2 -0
  75. package/dist/lib/tls.test.d.ts.map +1 -0
  76. package/dist/lib/utils.test.d.ts +2 -0
  77. package/dist/lib/utils.test.d.ts.map +1 -0
  78. package/dist/lib/validate-request.test.d.ts +2 -0
  79. package/dist/lib/validate-request.test.d.ts.map +1 -0
  80. package/dist/lib/watch-processor.d.ts.map +1 -1
  81. package/dist/lib/watch-processor.test.d.ts +2 -0
  82. package/dist/lib/watch-processor.test.d.ts.map +1 -0
  83. package/dist/lib.js +76 -20
  84. package/dist/lib.js.map +3 -3
  85. package/dist/sdk/sdk.test.d.ts +2 -0
  86. package/dist/sdk/sdk.test.d.ts.map +1 -0
  87. package/package.json +21 -15
  88. package/src/cli/banner.ts +63 -0
  89. package/src/cli/build.ts +370 -0
  90. package/src/cli/deploy.ts +105 -0
  91. package/src/cli/dev.ts +118 -0
  92. package/src/cli/format.ts +83 -0
  93. package/src/cli/init/index.ts +99 -0
  94. package/src/cli/init/templates.ts +124 -0
  95. package/src/cli/init/utils.test.ts +28 -0
  96. package/src/cli/init/utils.ts +55 -0
  97. package/src/cli/init/walkthrough.test.ts +21 -0
  98. package/src/cli/init/walkthrough.ts +96 -0
  99. package/src/cli/kfc.ts +45 -0
  100. package/src/cli/monitor.ts +101 -0
  101. package/src/cli/root.ts +12 -0
  102. package/src/cli/update.ts +95 -0
  103. package/src/cli/uuid.ts +44 -0
  104. package/src/fixtures/data/create-pod.json +271 -0
  105. package/src/fixtures/data/delete-pod.json +271 -0
  106. package/src/fixtures/loader.ts +18 -0
  107. package/src/lib/.prettierrc +14 -0
  108. package/src/lib/assets/helm.test.ts +64 -0
  109. package/src/lib/assets/helm.ts +35 -0
  110. package/src/lib/assets/index.ts +5 -1
  111. package/src/lib/assets/pods.test.ts +553 -0
  112. package/src/lib/assets/pods.ts +14 -6
  113. package/src/lib/assets/yaml.ts +15 -15
  114. package/src/lib/controller/index.ts +2 -2
  115. package/src/lib/errors.test.ts +85 -0
  116. package/src/lib/filter.test.ts +384 -0
  117. package/src/lib/helpers.test.ts +1192 -0
  118. package/src/lib/helpers.ts +0 -17
  119. package/src/lib/included-files.test.ts +22 -0
  120. package/src/lib/logger.test.ts +18 -0
  121. package/src/lib/metrics.test.ts +132 -0
  122. package/src/lib/metrics.ts +68 -6
  123. package/src/lib/module.test.ts +126 -0
  124. package/src/lib/mutate-request.test.ts +188 -0
  125. package/src/lib/queue.test.ts +58 -0
  126. package/src/lib/schedule.test.ts +217 -0
  127. package/src/lib/storage.test.ts +203 -0
  128. package/src/lib/tls.test.ts +18 -0
  129. package/src/lib/utils.test.ts +69 -0
  130. package/src/lib/validate-request.test.ts +124 -0
  131. package/src/lib/watch-processor.test.ts +322 -0
  132. package/src/lib/watch-processor.ts +20 -4
  133. package/src/sdk/sdk.test.ts +243 -0
  134. package/src/templates/.eslintrc.json +6 -0
  135. package/.prettierignore +0 -1
  136. package/CODE_OF_CONDUCT.md +0 -133
  137. package/SECURITY.md +0 -18
  138. package/SUPPORT.md +0 -16
  139. package/codecov.yaml +0 -19
  140. package/commitlint.config.js +0 -1
@@ -9,21 +9,9 @@ import { apiTokenSecret, service, tlsSecret, watcherService } from "./networking
9
9
  import { deployment, moduleSecret, namespace, watcher } from "./pods";
10
10
  import { clusterRole, clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "./rbac";
11
11
  import { webhookConfig } from "./webhooks";
12
- import { mergePkgJSONEnv, envMapToArray } from "../helpers";
13
-
12
+ import { genEnv } from "./pods";
14
13
  // Helm Chart overrides file (values.yaml) generated from assets
15
14
  export async function overridesFile({ hash, name, image, config, apiToken }: Assets, path: string) {
16
- const pkgJSONAdmissionEnv = {
17
- PEPR_WATCH_MODE: "false",
18
- PEPR_PRETTY_LOG: "false",
19
- LOG_LEVEL: "info",
20
- };
21
- const pkgJSONWatchEnv = {
22
- PEPR_WATCH_MODE: "true",
23
- PEPR_PRETTY_LOG: "false",
24
- LOG_LEVEL: "info",
25
- };
26
-
27
15
  const overrides = {
28
16
  secrets: {
29
17
  apiToken: Buffer.from(apiToken).toString("base64"),
@@ -40,7 +28,8 @@ export async function overridesFile({ hash, name, image, config, apiToken }: Ass
40
28
  terminationGracePeriodSeconds: 5,
41
29
  failurePolicy: config.onError === "reject" ? "Fail" : "Ignore",
42
30
  webhookTimeout: config.webhookTimeout,
43
- env: envMapToArray(mergePkgJSONEnv(pkgJSONAdmissionEnv, config.env)),
31
+ env: genEnv(config, false, true),
32
+ envFrom: [],
44
33
  image,
45
34
  annotations: {
46
35
  "pepr.dev/description": `${config.description}` || "",
@@ -81,10 +70,16 @@ export async function overridesFile({ hash, name, image, config, apiToken }: Ass
81
70
  extraVolumeMounts: [],
82
71
  extraVolumes: [],
83
72
  affinity: {},
73
+ serviceMonitor: {
74
+ enabled: false,
75
+ labels: {},
76
+ annotations: {},
77
+ },
84
78
  },
85
79
  watcher: {
86
80
  terminationGracePeriodSeconds: 5,
87
- env: envMapToArray(mergePkgJSONEnv(pkgJSONWatchEnv, config.env)),
81
+ env: genEnv(config, true, true),
82
+ envFrom: [],
88
83
  image,
89
84
  annotations: {
90
85
  "pepr.dev/description": `${config.description}` || "",
@@ -125,6 +120,11 @@ export async function overridesFile({ hash, name, image, config, apiToken }: Ass
125
120
  extraVolumes: [],
126
121
  affinity: {},
127
122
  podAnnotations: {},
123
+ serviceMonitor: {
124
+ enabled: false,
125
+ labels: {},
126
+ annotations: {},
127
+ },
128
128
  },
129
129
  };
130
130
 
@@ -8,7 +8,7 @@ import https from "https";
8
8
  import { Capability } from "../capability";
9
9
  import { MutateResponse, AdmissionRequest, ValidateResponse } from "../k8s";
10
10
  import Log from "../logger";
11
- import { MetricsCollector } from "../metrics";
11
+ import { metricsCollector, MetricsCollector } from "../metrics";
12
12
  import { ModuleConfig, isWatchMode } from "../module";
13
13
  import { mutateProcessor } from "../mutate-processor";
14
14
  import { validateProcessor } from "../validate-processor";
@@ -20,7 +20,7 @@ export class Controller {
20
20
  #running = false;
21
21
 
22
22
  // Metrics collector
23
- #metricsCollector = new MetricsCollector("pepr");
23
+ #metricsCollector = metricsCollector;
24
24
 
25
25
  // The token used to authenticate requests
26
26
  #token = "";
@@ -0,0 +1,85 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
+
4
+ import { expect, test, describe } from "@jest/globals";
5
+ import * as fc from "fast-check";
6
+ import { Errors, ErrorList, ValidateError } from "./errors";
7
+
8
+ describe("ValidateError Fuzz Testing", () => {
9
+ test("should only accept predefined error values", () => {
10
+ fc.assert(
11
+ fc.property(fc.string(), error => {
12
+ if (ErrorList.includes(error)) {
13
+ expect(() => ValidateError(error)).not.toThrow();
14
+ } else {
15
+ expect(() => ValidateError(error)).toThrow(
16
+ `Invalid error: ${error}. Must be one of: ${ErrorList.join(", ")}`,
17
+ );
18
+ }
19
+ }),
20
+ { verbose: true },
21
+ );
22
+ });
23
+ });
24
+ describe("ValidateError Fake Data Testing", () => {
25
+ test("should correctly handle typical fake error data", () => {
26
+ const fakeErrors = ["error", "failure", "null", "undefined", "exception"];
27
+ fakeErrors.forEach(fakeError => {
28
+ if (ErrorList.includes(fakeError)) {
29
+ expect(() => ValidateError(fakeError)).not.toThrow();
30
+ } else {
31
+ expect(() => ValidateError(fakeError)).toThrow(
32
+ `Invalid error: ${fakeError}. Must be one of: ${ErrorList.join(", ")}`,
33
+ );
34
+ }
35
+ });
36
+ });
37
+ });
38
+ describe("ValidateError Property-Based Testing", () => {
39
+ test("should only validate errors that are part of the ErrorList", () => {
40
+ fc.assert(
41
+ fc.property(fc.constantFrom(...ErrorList), validError => {
42
+ expect(() => ValidateError(validError)).not.toThrow();
43
+ }),
44
+ { verbose: true },
45
+ );
46
+
47
+ fc.assert(
48
+ fc.property(
49
+ fc.string().filter(e => !ErrorList.includes(e)),
50
+ invalidError => {
51
+ expect(() => ValidateError(invalidError)).toThrow(
52
+ `Invalid error: ${invalidError}. Must be one of: ${ErrorList.join(", ")}`,
53
+ );
54
+ },
55
+ ),
56
+ { verbose: true },
57
+ );
58
+ });
59
+ });
60
+
61
+ test("Errors object should have correct properties", () => {
62
+ expect(Errors).toEqual({
63
+ audit: "audit",
64
+ ignore: "ignore",
65
+ reject: "reject",
66
+ });
67
+ });
68
+
69
+ test("ErrorList should contain correct values", () => {
70
+ expect(ErrorList).toEqual(["audit", "ignore", "reject"]);
71
+ });
72
+
73
+ test("ValidateError should not throw an error for valid errors", () => {
74
+ expect(() => {
75
+ ValidateError("audit");
76
+ ValidateError("ignore");
77
+ ValidateError("reject");
78
+ }).not.toThrow();
79
+ });
80
+
81
+ test("ValidateError should throw an error for invalid errors", () => {
82
+ expect(() => ValidateError("invalidError")).toThrowError({
83
+ message: "Invalid error: invalidError. Must be one of: audit, ignore, reject",
84
+ });
85
+ });
@@ -0,0 +1,384 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
+
4
+ import { expect, test, describe } from "@jest/globals";
5
+ import { kind, modelToGroupVersionKind } from "kubernetes-fluent-client";
6
+ import * as fc from "fast-check";
7
+ import { CreatePod, DeletePod } from "../fixtures/loader";
8
+ import { shouldSkipRequest } from "./filter";
9
+ import { Event, Binding } from "./types";
10
+ import { AdmissionRequest } from "./k8s";
11
+
12
+ const callback = () => undefined;
13
+
14
+ const podKind = modelToGroupVersionKind(kind.Pod.name);
15
+
16
+ describe("Fuzzing shouldSkipRequest", () => {
17
+ test("should handle random inputs without crashing", () => {
18
+ fc.assert(
19
+ fc.property(
20
+ fc.record({
21
+ event: fc.constantFrom("CREATE", "UPDATE", "DELETE", "ANY"),
22
+ kind: fc.record({
23
+ group: fc.string(),
24
+ version: fc.string(),
25
+ kind: fc.string(),
26
+ }),
27
+ filters: fc.record({
28
+ name: fc.string(),
29
+ namespaces: fc.array(fc.string()),
30
+ labels: fc.dictionary(fc.string(), fc.string()),
31
+ annotations: fc.dictionary(fc.string(), fc.string()),
32
+ }),
33
+ }),
34
+ fc.record({
35
+ operation: fc.string(),
36
+ uid: fc.string(),
37
+ name: fc.string(),
38
+ namespace: fc.string(),
39
+ kind: fc.record({
40
+ group: fc.string(),
41
+ version: fc.string(),
42
+ kind: fc.string(),
43
+ }),
44
+ }),
45
+ fc.array(fc.string()),
46
+ (binding, req, capabilityNamespaces) => {
47
+ expect(() =>
48
+ shouldSkipRequest(binding as Binding, req as AdmissionRequest, capabilityNamespaces),
49
+ ).not.toThrow();
50
+ },
51
+ ),
52
+ { numRuns: 100 },
53
+ );
54
+ });
55
+ });
56
+ describe("Property-Based Testing shouldSkipRequest", () => {
57
+ test("should only skip requests that do not match the binding criteria", () => {
58
+ fc.assert(
59
+ fc.property(
60
+ fc.record({
61
+ event: fc.constantFrom("CREATE", "UPDATE", "DELETE", "ANY"),
62
+ kind: fc.record({
63
+ group: fc.string(),
64
+ version: fc.string(),
65
+ kind: fc.string(),
66
+ }),
67
+ filters: fc.record({
68
+ name: fc.string(),
69
+ namespaces: fc.array(fc.string()),
70
+ labels: fc.dictionary(fc.string(), fc.string()),
71
+ annotations: fc.dictionary(fc.string(), fc.string()),
72
+ }),
73
+ }),
74
+ fc.record({
75
+ operation: fc.string(),
76
+ uid: fc.string(),
77
+ name: fc.string(),
78
+ namespace: fc.string(),
79
+ kind: fc.record({
80
+ group: fc.string(),
81
+ version: fc.string(),
82
+ kind: fc.string(),
83
+ }),
84
+ }),
85
+ fc.array(fc.string()),
86
+ (binding, req, capabilityNamespaces) => {
87
+ const shouldSkip = shouldSkipRequest(binding as Binding, req as AdmissionRequest, capabilityNamespaces);
88
+ expect(typeof shouldSkip).toBe("boolean");
89
+ },
90
+ ),
91
+ { numRuns: 100 },
92
+ );
93
+ });
94
+ });
95
+
96
+ test("should reject when name does not match", () => {
97
+ const binding = {
98
+ model: kind.Pod,
99
+ event: Event.Any,
100
+ kind: podKind,
101
+ filters: {
102
+ name: "bleh",
103
+ namespaces: [],
104
+ labels: {},
105
+ annotations: {},
106
+ },
107
+ callback,
108
+ };
109
+ const pod = CreatePod();
110
+
111
+ expect(shouldSkipRequest(binding, pod, [])).toBe(true);
112
+ });
113
+
114
+ test("should reject when kind does not match", () => {
115
+ const binding = {
116
+ model: kind.Pod,
117
+ event: Event.Any,
118
+ kind: modelToGroupVersionKind(kind.CronJob.name),
119
+ filters: {
120
+ name: "",
121
+ namespaces: [],
122
+ labels: {},
123
+ annotations: {},
124
+ },
125
+ callback,
126
+ };
127
+ const pod = CreatePod();
128
+
129
+ expect(shouldSkipRequest(binding, pod, [])).toBe(true);
130
+ });
131
+
132
+ test("should reject when group does not match", () => {
133
+ const binding = {
134
+ model: kind.Pod,
135
+ event: Event.Any,
136
+ kind: modelToGroupVersionKind(kind.CronJob.name),
137
+ filters: {
138
+ name: "",
139
+ namespaces: [],
140
+ labels: {},
141
+ annotations: {},
142
+ },
143
+ callback,
144
+ };
145
+ const pod = CreatePod();
146
+
147
+ expect(shouldSkipRequest(binding, pod, [])).toBe(true);
148
+ });
149
+
150
+ test("should reject when version does not match", () => {
151
+ const binding = {
152
+ model: kind.Pod,
153
+ event: Event.Any,
154
+ kind: {
155
+ group: "",
156
+ version: "v2",
157
+ kind: "Pod",
158
+ },
159
+ filters: {
160
+ name: "",
161
+ namespaces: [],
162
+ labels: {},
163
+ annotations: {},
164
+ },
165
+ callback,
166
+ };
167
+ const pod = CreatePod();
168
+
169
+ expect(shouldSkipRequest(binding, pod, [])).toBe(true);
170
+ });
171
+
172
+ test("should allow when group, version, and kind match", () => {
173
+ const binding = {
174
+ model: kind.Pod,
175
+ event: Event.Any,
176
+ kind: podKind,
177
+ filters: {
178
+ name: "",
179
+ namespaces: [],
180
+ labels: {},
181
+ annotations: {},
182
+ },
183
+ callback,
184
+ };
185
+ const pod = CreatePod();
186
+
187
+ expect(shouldSkipRequest(binding, pod, [])).toBe(false);
188
+ });
189
+
190
+ test("should allow when kind match and others are empty", () => {
191
+ const binding = {
192
+ model: kind.Pod,
193
+ event: Event.Any,
194
+ kind: {
195
+ group: "",
196
+ version: "",
197
+ kind: "Pod",
198
+ },
199
+ filters: {
200
+ name: "",
201
+ namespaces: [],
202
+ labels: {},
203
+ annotations: {},
204
+ },
205
+ callback,
206
+ };
207
+ const pod = CreatePod();
208
+
209
+ expect(shouldSkipRequest(binding, pod, [])).toBe(false);
210
+ });
211
+
212
+ test("should reject when teh capability namespace does not match", () => {
213
+ const binding = {
214
+ model: kind.Pod,
215
+ event: Event.Any,
216
+ kind: podKind,
217
+ filters: {
218
+ name: "",
219
+ namespaces: [],
220
+ labels: {},
221
+ annotations: {},
222
+ },
223
+ callback,
224
+ };
225
+ const pod = CreatePod();
226
+
227
+ expect(shouldSkipRequest(binding, pod, ["bleh", "bleh2"])).toBe(true);
228
+ });
229
+
230
+ test("should reject when namespace does not match", () => {
231
+ const binding = {
232
+ model: kind.Pod,
233
+ event: Event.Any,
234
+ kind: podKind,
235
+ filters: {
236
+ name: "",
237
+ namespaces: ["bleh"],
238
+ labels: {},
239
+ annotations: {},
240
+ },
241
+ callback,
242
+ };
243
+ const pod = CreatePod();
244
+
245
+ expect(shouldSkipRequest(binding, pod, [])).toBe(true);
246
+ });
247
+
248
+ test("should allow when namespace is match", () => {
249
+ const binding = {
250
+ model: kind.Pod,
251
+ event: Event.Any,
252
+ kind: podKind,
253
+ filters: {
254
+ name: "",
255
+ namespaces: ["default", "unicorn", "things"],
256
+ labels: {},
257
+ annotations: {},
258
+ },
259
+ callback,
260
+ };
261
+ const pod = CreatePod();
262
+
263
+ expect(shouldSkipRequest(binding, pod, [])).toBe(false);
264
+ });
265
+
266
+ test("should reject when label does not match", () => {
267
+ const binding = {
268
+ model: kind.Pod,
269
+ event: Event.Any,
270
+ kind: podKind,
271
+ filters: {
272
+ name: "",
273
+ namespaces: [],
274
+ labels: {
275
+ foo: "bar",
276
+ },
277
+ annotations: {},
278
+ },
279
+ callback,
280
+ };
281
+ const pod = CreatePod();
282
+
283
+ expect(shouldSkipRequest(binding, pod, [])).toBe(true);
284
+ });
285
+
286
+ test("should allow when label is match", () => {
287
+ const binding = {
288
+ model: kind.Pod,
289
+ event: Event.Any,
290
+ kind: podKind,
291
+ filters: {
292
+ name: "",
293
+
294
+ namespaces: [],
295
+ labels: {
296
+ foo: "bar",
297
+ test: "test1",
298
+ },
299
+ annotations: {},
300
+ },
301
+ callback,
302
+ };
303
+
304
+ const pod = CreatePod();
305
+ pod.object.metadata = pod.object.metadata || {};
306
+ pod.object.metadata.labels = {
307
+ foo: "bar",
308
+ test: "test1",
309
+ test2: "test2",
310
+ };
311
+
312
+ expect(shouldSkipRequest(binding, pod, [])).toBe(false);
313
+ });
314
+
315
+ test("should reject when annotation does not match", () => {
316
+ const binding = {
317
+ model: kind.Pod,
318
+ event: Event.Any,
319
+ kind: podKind,
320
+ filters: {
321
+ name: "",
322
+ namespaces: [],
323
+ labels: {},
324
+ annotations: {
325
+ foo: "bar",
326
+ },
327
+ },
328
+ callback,
329
+ };
330
+ const pod = CreatePod();
331
+
332
+ expect(shouldSkipRequest(binding, pod, [])).toBe(true);
333
+ });
334
+
335
+ test("should allow when annotation is match", () => {
336
+ const binding = {
337
+ model: kind.Pod,
338
+ event: Event.Any,
339
+ kind: podKind,
340
+ filters: {
341
+ name: "",
342
+ namespaces: [],
343
+ labels: {},
344
+ annotations: {
345
+ foo: "bar",
346
+ test: "test1",
347
+ },
348
+ },
349
+ callback,
350
+ };
351
+
352
+ const pod = CreatePod();
353
+ pod.object.metadata = pod.object.metadata || {};
354
+ pod.object.metadata.annotations = {
355
+ foo: "bar",
356
+ test: "test1",
357
+ test2: "test2",
358
+ };
359
+
360
+ expect(shouldSkipRequest(binding, pod, [])).toBe(false);
361
+ });
362
+
363
+ test("should use `oldObject` when the operation is `DELETE`", () => {
364
+ const binding = {
365
+ model: kind.Pod,
366
+ event: Event.Delete,
367
+ kind: podKind,
368
+ filters: {
369
+ name: "",
370
+ namespaces: [],
371
+ labels: {
372
+ "app.kubernetes.io/name": "cool-name-podinfo",
373
+ },
374
+ annotations: {
375
+ "prometheus.io/scrape": "true",
376
+ },
377
+ },
378
+ callback,
379
+ };
380
+
381
+ const pod = DeletePod();
382
+
383
+ expect(shouldSkipRequest(binding, pod, [])).toBe(false);
384
+ });