pepr 0.35.0 → 0.37.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 (107) hide show
  1. package/dist/cli/init/index.d.ts.map +1 -1
  2. package/dist/cli/init/templates.d.ts +3 -1
  3. package/dist/cli/init/templates.d.ts.map +1 -1
  4. package/dist/cli/init/utils.d.ts.map +1 -1
  5. package/dist/cli/init/walkthrough.d.ts +10 -3
  6. package/dist/cli/init/walkthrough.d.ts.map +1 -1
  7. package/dist/cli.js +253 -31
  8. package/dist/controller.js +138 -1
  9. package/dist/lib/adjudicators.d.ts +63 -0
  10. package/dist/lib/adjudicators.d.ts.map +1 -0
  11. package/dist/lib/adjudicators.test.d.ts +2 -0
  12. package/dist/lib/adjudicators.test.d.ts.map +1 -0
  13. package/dist/lib/assets/loader.d.ts.map +1 -1
  14. package/dist/lib/assets/pods.d.ts +1 -0
  15. package/dist/lib/assets/pods.d.ts.map +1 -1
  16. package/dist/lib/capability.d.ts +1 -0
  17. package/dist/lib/capability.d.ts.map +1 -1
  18. package/dist/lib/capability.test.d.ts +2 -0
  19. package/dist/lib/capability.test.d.ts.map +1 -0
  20. package/dist/lib/controller/index.d.ts.map +1 -1
  21. package/dist/lib/controller/store.d.ts +4 -0
  22. package/dist/lib/controller/store.d.ts.map +1 -1
  23. package/dist/lib/controller/store.test.d.ts +2 -0
  24. package/dist/lib/controller/store.test.d.ts.map +1 -0
  25. package/dist/lib/filter.d.ts +2 -3
  26. package/dist/lib/filter.d.ts.map +1 -1
  27. package/dist/lib/filter.test.d.ts +2 -1
  28. package/dist/lib/filter.test.d.ts.map +1 -1
  29. package/dist/lib/finalizer.d.ts +6 -0
  30. package/dist/lib/finalizer.d.ts.map +1 -0
  31. package/dist/lib/finalizer.test.d.ts +2 -0
  32. package/dist/lib/finalizer.test.d.ts.map +1 -0
  33. package/dist/lib/helpers.d.ts +2 -2
  34. package/dist/lib/helpers.d.ts.map +1 -1
  35. package/dist/lib/helpers.test.d.ts +1 -1
  36. package/dist/lib/helpers.test.d.ts.map +1 -1
  37. package/dist/lib/k8s.d.ts.map +1 -1
  38. package/dist/lib/logger.d.ts +1 -1
  39. package/dist/lib/logger.d.ts.map +1 -1
  40. package/dist/lib/module.d.ts +2 -1
  41. package/dist/lib/module.d.ts.map +1 -1
  42. package/dist/lib/mutate-processor.d.ts +2 -1
  43. package/dist/lib/mutate-processor.d.ts.map +1 -1
  44. package/dist/lib/mutate-request.d.ts +1 -2
  45. package/dist/lib/mutate-request.d.ts.map +1 -1
  46. package/dist/lib/queue.d.ts +19 -3
  47. package/dist/lib/queue.d.ts.map +1 -1
  48. package/dist/lib/schedule.d.ts +1 -2
  49. package/dist/lib/schedule.d.ts.map +1 -1
  50. package/dist/lib/storage.d.ts.map +1 -1
  51. package/dist/lib/types.d.ts +118 -6
  52. package/dist/lib/types.d.ts.map +1 -1
  53. package/dist/lib/validate-processor.d.ts +4 -2
  54. package/dist/lib/validate-processor.d.ts.map +1 -1
  55. package/dist/lib/validate-request.d.ts +1 -1
  56. package/dist/lib/validate-request.d.ts.map +1 -1
  57. package/dist/lib/watch-processor.d.ts +8 -6
  58. package/dist/lib/watch-processor.d.ts.map +1 -1
  59. package/dist/lib.js +467 -233
  60. package/dist/lib.js.map +4 -4
  61. package/dist/sdk/sdk.d.ts +5 -3
  62. package/dist/sdk/sdk.d.ts.map +1 -1
  63. package/package.json +13 -11
  64. package/src/cli/build.ts +3 -3
  65. package/src/cli/init/index.ts +20 -11
  66. package/src/cli/init/templates.ts +1 -1
  67. package/src/cli/init/utils.test.ts +11 -20
  68. package/src/cli/init/utils.ts +5 -0
  69. package/src/cli/init/walkthrough.test.ts +92 -11
  70. package/src/cli/init/walkthrough.ts +71 -16
  71. package/src/cli/monitor.ts +1 -1
  72. package/src/cli.ts +4 -2
  73. package/src/fixtures/data/create-pod.json +1 -1
  74. package/src/fixtures/data/delete-pod.json +1 -1
  75. package/src/lib/adjudicators.test.ts +1232 -0
  76. package/src/lib/adjudicators.ts +235 -0
  77. package/src/lib/assets/index.ts +1 -1
  78. package/src/lib/assets/loader.ts +1 -0
  79. package/src/lib/assets/webhooks.ts +1 -1
  80. package/src/lib/capability.test.ts +655 -0
  81. package/src/lib/capability.ts +112 -11
  82. package/src/lib/controller/index.ts +7 -4
  83. package/src/lib/controller/store.test.ts +131 -0
  84. package/src/lib/controller/store.ts +43 -5
  85. package/src/lib/filter.test.ts +279 -9
  86. package/src/lib/filter.ts +46 -98
  87. package/src/lib/finalizer.test.ts +236 -0
  88. package/src/lib/finalizer.ts +63 -0
  89. package/src/lib/helpers.test.ts +359 -65
  90. package/src/lib/helpers.ts +141 -95
  91. package/src/lib/k8s.ts +4 -0
  92. package/src/lib/module.ts +3 -3
  93. package/src/lib/mutate-processor.ts +5 -4
  94. package/src/lib/mutate-request.test.ts +1 -2
  95. package/src/lib/mutate-request.ts +1 -3
  96. package/src/lib/queue.test.ts +138 -44
  97. package/src/lib/queue.ts +48 -13
  98. package/src/lib/schedule.ts +1 -1
  99. package/src/lib/storage.ts +5 -6
  100. package/src/lib/types.ts +154 -5
  101. package/src/lib/validate-processor.ts +5 -2
  102. package/src/lib/validate-request.test.ts +1 -4
  103. package/src/lib/validate-request.ts +1 -1
  104. package/src/lib/watch-processor.test.ts +89 -124
  105. package/src/lib/watch-processor.ts +52 -35
  106. package/src/sdk/sdk.test.ts +46 -13
  107. package/src/sdk/sdk.ts +15 -6
@@ -6,12 +6,11 @@ import { kind, modelToGroupVersionKind } from "kubernetes-fluent-client";
6
6
  import * as fc from "fast-check";
7
7
  import { CreatePod, DeletePod } from "../fixtures/loader";
8
8
  import { shouldSkipRequest } from "./filter";
9
- import { Event, Binding } from "./types";
10
- import { AdmissionRequest } from "./k8s";
9
+ import { AdmissionRequest, Binding, Event } from "./types";
11
10
 
12
- const callback = () => undefined;
11
+ export const callback = () => undefined;
13
12
 
14
- const podKind = modelToGroupVersionKind(kind.Pod.name);
13
+ export const podKind = modelToGroupVersionKind(kind.Pod.name);
15
14
 
16
15
  describe("Fuzzing shouldSkipRequest", () => {
17
16
  test("should handle random inputs without crashing", () => {
@@ -29,6 +28,7 @@ describe("Fuzzing shouldSkipRequest", () => {
29
28
  namespaces: fc.array(fc.string()),
30
29
  labels: fc.dictionary(fc.string(), fc.string()),
31
30
  annotations: fc.dictionary(fc.string(), fc.string()),
31
+ deletionTimestamp: fc.boolean(),
32
32
  }),
33
33
  }),
34
34
  fc.record({
@@ -41,6 +41,11 @@ describe("Fuzzing shouldSkipRequest", () => {
41
41
  version: fc.string(),
42
42
  kind: fc.string(),
43
43
  }),
44
+ object: fc.record({
45
+ metadata: fc.record({
46
+ deletionTimestamp: fc.option(fc.date()),
47
+ }),
48
+ }),
44
49
  }),
45
50
  fc.array(fc.string()),
46
51
  (binding, req, capabilityNamespaces) => {
@@ -69,6 +74,7 @@ describe("Property-Based Testing shouldSkipRequest", () => {
69
74
  namespaces: fc.array(fc.string()),
70
75
  labels: fc.dictionary(fc.string(), fc.string()),
71
76
  annotations: fc.dictionary(fc.string(), fc.string()),
77
+ deletionTimestamp: fc.boolean(),
72
78
  }),
73
79
  }),
74
80
  fc.record({
@@ -81,6 +87,11 @@ describe("Property-Based Testing shouldSkipRequest", () => {
81
87
  version: fc.string(),
82
88
  kind: fc.string(),
83
89
  }),
90
+ object: fc.record({
91
+ metadata: fc.record({
92
+ deletionTimestamp: fc.option(fc.date()),
93
+ }),
94
+ }),
84
95
  }),
85
96
  fc.array(fc.string()),
86
97
  (binding, req, capabilityNamespaces) => {
@@ -93,24 +104,182 @@ describe("Property-Based Testing shouldSkipRequest", () => {
93
104
  });
94
105
  });
95
106
 
96
- test("should reject when name does not match", () => {
107
+ test("create: should reject when regex name does not match", () => {
97
108
  const binding = {
98
109
  model: kind.Pod,
99
110
  event: Event.Any,
100
111
  kind: podKind,
101
112
  filters: {
102
- name: "bleh",
113
+ name: "",
103
114
  namespaces: [],
115
+ regexNamespaces: [],
116
+ regexName: new RegExp(/^default$/).source,
104
117
  labels: {},
105
118
  annotations: {},
119
+ deletionTimestamp: false,
106
120
  },
107
121
  callback,
108
122
  };
109
123
  const pod = CreatePod();
124
+ expect(shouldSkipRequest(binding, pod, [])).toBe(true);
125
+ });
126
+ test("create: should not reject when regex name does match", () => {
127
+ const binding = {
128
+ model: kind.Pod,
129
+ event: Event.Any,
130
+ kind: podKind,
131
+ filters: {
132
+ name: "",
133
+ namespaces: [],
134
+ regexNamespaces: [],
135
+ regexName: new RegExp(/^cool/).source,
136
+ labels: {},
137
+ annotations: {},
138
+ deletionTimestamp: false,
139
+ },
140
+ callback,
141
+ };
142
+ const pod = CreatePod();
143
+ expect(shouldSkipRequest(binding, pod, [])).toBe(false);
144
+ });
145
+ test("delete: should reject when regex name does not match", () => {
146
+ const binding = {
147
+ model: kind.Pod,
148
+ event: Event.Any,
149
+ kind: podKind,
150
+ filters: {
151
+ name: "",
152
+ namespaces: [],
153
+ regexNamespaces: [],
154
+ regexName: new RegExp(/^default$/).source,
155
+ labels: {},
156
+ annotations: {},
157
+ deletionTimestamp: false,
158
+ },
159
+ callback,
160
+ };
161
+ const pod = DeletePod();
162
+ expect(shouldSkipRequest(binding, pod, [])).toBe(true);
163
+ });
164
+ test("delete: should not reject when regex name does match", () => {
165
+ const binding = {
166
+ model: kind.Pod,
167
+ event: Event.Any,
168
+ kind: podKind,
169
+ filters: {
170
+ name: "",
171
+ namespaces: [],
172
+ regexNamespaces: [],
173
+ regexName: new RegExp(/^cool/).source,
174
+ labels: {},
175
+ annotations: {},
176
+ deletionTimestamp: false,
177
+ },
178
+ callback,
179
+ };
180
+ const pod = DeletePod();
181
+ expect(shouldSkipRequest(binding, pod, [])).toBe(false);
182
+ });
110
183
 
184
+ test("create: should not reject when regex namespace does match", () => {
185
+ const binding = {
186
+ model: kind.Pod,
187
+ event: Event.Any,
188
+ kind: podKind,
189
+ filters: {
190
+ name: "",
191
+ namespaces: [],
192
+ regexNamespaces: [new RegExp(/^helm/).source],
193
+ regexName: "",
194
+ labels: {},
195
+ annotations: {},
196
+ deletionTimestamp: false,
197
+ },
198
+ callback,
199
+ };
200
+ const pod = CreatePod();
201
+ expect(shouldSkipRequest(binding, pod, [])).toBe(false);
202
+ });
203
+
204
+ test("create: should reject when regex namespace does not match", () => {
205
+ const binding = {
206
+ model: kind.Pod,
207
+ event: Event.Any,
208
+ kind: podKind,
209
+ filters: {
210
+ name: "",
211
+ namespaces: [],
212
+ regexNamespaces: [new RegExp(/^argo/).source],
213
+ regexName: "",
214
+ labels: {},
215
+ annotations: {},
216
+ deletionTimestamp: false,
217
+ },
218
+ callback,
219
+ };
220
+ const pod = CreatePod();
221
+ expect(shouldSkipRequest(binding, pod, [])).toBe(true);
222
+ });
223
+
224
+ test("delete: should reject when regex namespace does not match", () => {
225
+ const binding = {
226
+ model: kind.Pod,
227
+ event: Event.Any,
228
+ kind: podKind,
229
+ filters: {
230
+ name: "bleh",
231
+ namespaces: [],
232
+ regexNamespaces: [new RegExp(/^argo/).source],
233
+ regexName: "",
234
+ labels: {},
235
+ annotations: {},
236
+ deletionTimestamp: false,
237
+ },
238
+ callback,
239
+ };
240
+ const pod = DeletePod();
111
241
  expect(shouldSkipRequest(binding, pod, [])).toBe(true);
112
242
  });
113
243
 
244
+ test("delete: should not reject when regex namespace does match", () => {
245
+ const binding = {
246
+ model: kind.Pod,
247
+ event: Event.Any,
248
+ kind: podKind,
249
+ filters: {
250
+ name: "",
251
+ namespaces: [],
252
+ regexNamespaces: [new RegExp(/^helm/).source],
253
+ regexName: "",
254
+ labels: {},
255
+ annotations: {},
256
+ deletionTimestamp: false,
257
+ },
258
+ callback,
259
+ };
260
+ const pod = DeletePod();
261
+ expect(shouldSkipRequest(binding, pod, [])).toBe(false);
262
+ });
263
+
264
+ test("delete: should reject when name does not match", () => {
265
+ const binding = {
266
+ model: kind.Pod,
267
+ event: Event.Any,
268
+ kind: podKind,
269
+ filters: {
270
+ name: "bleh",
271
+ namespaces: [],
272
+ regexNamespaces: [],
273
+ regexName: new RegExp(/^not-cool/).source,
274
+ labels: {},
275
+ annotations: {},
276
+ deletionTimestamp: false,
277
+ },
278
+ callback,
279
+ };
280
+ const pod = DeletePod();
281
+ expect(shouldSkipRequest(binding, pod, [])).toBe(true);
282
+ });
114
283
  test("should reject when kind does not match", () => {
115
284
  const binding = {
116
285
  model: kind.Pod,
@@ -119,8 +288,11 @@ test("should reject when kind does not match", () => {
119
288
  filters: {
120
289
  name: "",
121
290
  namespaces: [],
291
+ regexNamespaces: [],
292
+ regexName: "",
122
293
  labels: {},
123
294
  annotations: {},
295
+ deletionTimestamp: false,
124
296
  },
125
297
  callback,
126
298
  };
@@ -139,6 +311,9 @@ test("should reject when group does not match", () => {
139
311
  namespaces: [],
140
312
  labels: {},
141
313
  annotations: {},
314
+ deletionTimestamp: false,
315
+ regexNamespaces: [],
316
+ regexName: "",
142
317
  },
143
318
  callback,
144
319
  };
@@ -161,6 +336,9 @@ test("should reject when version does not match", () => {
161
336
  namespaces: [],
162
337
  labels: {},
163
338
  annotations: {},
339
+ deletionTimestamp: false,
340
+ regexNamespaces: [],
341
+ regexName: "",
164
342
  },
165
343
  callback,
166
344
  };
@@ -179,6 +357,9 @@ test("should allow when group, version, and kind match", () => {
179
357
  namespaces: [],
180
358
  labels: {},
181
359
  annotations: {},
360
+ deletionTimestamp: false,
361
+ regexNamespaces: [],
362
+ regexName: "",
182
363
  },
183
364
  callback,
184
365
  };
@@ -201,6 +382,9 @@ test("should allow when kind match and others are empty", () => {
201
382
  namespaces: [],
202
383
  labels: {},
203
384
  annotations: {},
385
+ deletionTimestamp: false,
386
+ regexNamespaces: [],
387
+ regexName: "",
204
388
  },
205
389
  callback,
206
390
  };
@@ -209,7 +393,7 @@ test("should allow when kind match and others are empty", () => {
209
393
  expect(shouldSkipRequest(binding, pod, [])).toBe(false);
210
394
  });
211
395
 
212
- test("should reject when teh capability namespace does not match", () => {
396
+ test("should reject when the capability namespace does not match", () => {
213
397
  const binding = {
214
398
  model: kind.Pod,
215
399
  event: Event.Any,
@@ -219,6 +403,9 @@ test("should reject when teh capability namespace does not match", () => {
219
403
  namespaces: [],
220
404
  labels: {},
221
405
  annotations: {},
406
+ deletionTimestamp: false,
407
+ regexNamespaces: [],
408
+ regexName: "",
222
409
  },
223
410
  callback,
224
411
  };
@@ -237,6 +424,9 @@ test("should reject when namespace does not match", () => {
237
424
  namespaces: ["bleh"],
238
425
  labels: {},
239
426
  annotations: {},
427
+ deletionTimestamp: false,
428
+ regexNamespaces: [],
429
+ regexName: "",
240
430
  },
241
431
  callback,
242
432
  };
@@ -252,9 +442,12 @@ test("should allow when namespace is match", () => {
252
442
  kind: podKind,
253
443
  filters: {
254
444
  name: "",
255
- namespaces: ["default", "unicorn", "things"],
445
+ namespaces: ["helm-releasename", "unicorn", "things"],
256
446
  labels: {},
257
447
  annotations: {},
448
+ deletionTimestamp: false,
449
+ regexNamespaces: [],
450
+ regexName: "",
258
451
  },
259
452
  callback,
260
453
  };
@@ -275,6 +468,9 @@ test("should reject when label does not match", () => {
275
468
  foo: "bar",
276
469
  },
277
470
  annotations: {},
471
+ deletionTimestamp: false,
472
+ regexNamespaces: [],
473
+ regexName: "",
278
474
  },
279
475
  callback,
280
476
  };
@@ -290,8 +486,10 @@ test("should allow when label is match", () => {
290
486
  kind: podKind,
291
487
  filters: {
292
488
  name: "",
293
-
489
+ deletionTimestamp: false,
294
490
  namespaces: [],
491
+ regexNamespaces: [],
492
+ regexName: "",
295
493
  labels: {
296
494
  foo: "bar",
297
495
  test: "test1",
@@ -324,6 +522,9 @@ test("should reject when annotation does not match", () => {
324
522
  annotations: {
325
523
  foo: "bar",
326
524
  },
525
+ deletionTimestamp: false,
526
+ regexNamespaces: [],
527
+ regexName: "",
327
528
  },
328
529
  callback,
329
530
  };
@@ -345,6 +546,9 @@ test("should allow when annotation is match", () => {
345
546
  foo: "bar",
346
547
  test: "test1",
347
548
  },
549
+ deletionTimestamp: false,
550
+ regexNamespaces: [],
551
+ regexName: "",
348
552
  },
349
553
  callback,
350
554
  };
@@ -368,6 +572,9 @@ test("should use `oldObject` when the operation is `DELETE`", () => {
368
572
  filters: {
369
573
  name: "",
370
574
  namespaces: [],
575
+ regexNamespaces: [],
576
+ regexName: "",
577
+ deletionTimestamp: false,
371
578
  labels: {
372
579
  "app.kubernetes.io/name": "cool-name-podinfo",
373
580
  },
@@ -382,3 +589,66 @@ test("should use `oldObject` when the operation is `DELETE`", () => {
382
589
 
383
590
  expect(shouldSkipRequest(binding, pod, [])).toBe(false);
384
591
  });
592
+
593
+ test("should skip processing when deletionTimestamp is not present on pod", () => {
594
+ const binding = {
595
+ model: kind.Pod,
596
+ event: Event.Any,
597
+ kind: podKind,
598
+ filters: {
599
+ name: "",
600
+ namespaces: [],
601
+ labels: {},
602
+ regexNamespaces: [],
603
+ regexName: "",
604
+ annotations: {
605
+ foo: "bar",
606
+ test: "test1",
607
+ },
608
+ deletionTimestamp: true,
609
+ },
610
+ callback,
611
+ };
612
+
613
+ const pod = CreatePod();
614
+ pod.object.metadata = pod.object.metadata || {};
615
+ pod.object.metadata.annotations = {
616
+ foo: "bar",
617
+ test: "test1",
618
+ test2: "test2",
619
+ };
620
+
621
+ expect(shouldSkipRequest(binding, pod, [])).toBe(true);
622
+ });
623
+
624
+ test("should processing when deletionTimestamp is not present on pod", () => {
625
+ const binding = {
626
+ model: kind.Pod,
627
+ event: Event.Any,
628
+ kind: podKind,
629
+ filters: {
630
+ name: "",
631
+ namespaces: [],
632
+ labels: {},
633
+ regexNamespaces: [],
634
+ regexName: "",
635
+ annotations: {
636
+ foo: "bar",
637
+ test: "test1",
638
+ },
639
+ deletionTimestamp: true,
640
+ },
641
+ callback,
642
+ };
643
+
644
+ const pod = CreatePod();
645
+ pod.object.metadata = pod.object.metadata || {};
646
+ pod.object.metadata!.deletionTimestamp = new Date("2021-09-01T00:00:00Z");
647
+ pod.object.metadata.annotations = {
648
+ foo: "bar",
649
+ test: "test1",
650
+ test2: "test2",
651
+ };
652
+
653
+ expect(shouldSkipRequest(binding, pod, [])).toBe(false);
654
+ });
package/src/lib/filter.ts CHANGED
@@ -1,9 +1,24 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
3
 
4
- import { AdmissionRequest, Operation } from "./k8s";
5
- import logger from "./logger";
6
- import { Binding, Event } from "./types";
4
+ import { AdmissionRequest, Binding, Operation } from "./types";
5
+ import {
6
+ carriesIgnoredNamespace,
7
+ misboundDeleteWithDeletionTimestamp,
8
+ mismatchedDeletionTimestamp,
9
+ mismatchedAnnotations,
10
+ mismatchedLabels,
11
+ mismatchedName,
12
+ mismatchedNameRegex,
13
+ mismatchedNamespace,
14
+ mismatchedNamespaceRegex,
15
+ mismatchedEvent,
16
+ mismatchedGroup,
17
+ mismatchedVersion,
18
+ mismatchedKind,
19
+ unbindableNamespaces,
20
+ uncarryableNamespace,
21
+ } from "./adjudicators";
7
22
 
8
23
  /**
9
24
  * shouldSkipRequest determines if a request should be skipped based on the binding filters.
@@ -12,99 +27,32 @@ import { Binding, Event } from "./types";
12
27
  * @param req the incoming request
13
28
  * @returns
14
29
  */
15
- export function shouldSkipRequest(binding: Binding, req: AdmissionRequest, capabilityNamespaces: string[]) {
16
- const { group, kind, version } = binding.kind || {};
17
- const { namespaces, labels, annotations, name } = binding.filters || {};
18
- const operation = req.operation.toUpperCase();
19
- const uid = req.uid;
20
- // Use the old object if the request is a DELETE operation
21
- const srcObject = operation === Operation.DELETE ? req.oldObject : req.object;
22
- const { metadata } = srcObject || {};
23
- const combinedNamespaces = [...namespaces, ...capabilityNamespaces];
24
-
25
- // Test for matching operation
26
- if (!binding.event.includes(operation) && !binding.event.includes(Event.Any)) {
27
- return true;
28
- }
29
-
30
- // Test name first, since it's the most specific
31
- if (name && name !== req.name) {
32
- return true;
33
- }
34
-
35
- // Test for matching kinds
36
- if (kind !== req.kind.kind) {
37
- return true;
38
- }
39
-
40
- // Test for matching groups
41
- if (group && group !== req.kind.group) {
42
- return true;
43
- }
44
-
45
- // Test for matching versions
46
- if (version && version !== req.kind.version) {
47
- return true;
48
- }
49
-
50
- // Test for matching namespaces
51
- if (
52
- (combinedNamespaces.length && !combinedNamespaces.includes(req.namespace || "")) ||
53
- (!namespaces.includes(req.namespace || "") && capabilityNamespaces.length !== 0 && namespaces.length !== 0)
54
- ) {
55
- let type = "";
56
- let label = "";
57
-
58
- if (binding.isMutate) {
59
- type = "Mutate";
60
- label = binding.mutateCallback!.name;
61
- } else if (binding.isValidate) {
62
- type = "Validate";
63
- label = binding.validateCallback!.name;
64
- } else if (binding.isWatch) {
65
- type = "Watch";
66
- label = binding.watchCallback!.name;
67
- }
68
-
69
- logger.debug({ uid }, `${type} binding (${label}) does not match request namespace "${req.namespace}"`);
70
-
71
- return true;
72
- }
73
-
74
- // Test for matching labels
75
- for (const [key, value] of Object.entries(labels)) {
76
- const testKey = metadata?.labels?.[key];
77
-
78
- // First check if the label exists
79
- if (!testKey) {
80
- logger.debug({ uid }, `Label ${key} does not exist`);
81
- return true;
82
- }
83
-
84
- // Then check if the value matches, if specified
85
- if (value && testKey !== value) {
86
- logger.debug({ uid }, `${testKey} does not match ${value}`);
87
- return true;
88
- }
89
- }
90
-
91
- // Test for matching annotations
92
- for (const [key, value] of Object.entries(annotations)) {
93
- const testKey = metadata?.annotations?.[key];
94
-
95
- // First check if the annotation exists
96
- if (!testKey) {
97
- logger.debug({ uid }, `Annotation ${key} does not exist`);
98
- return true;
99
- }
100
-
101
- // Then check if the value matches, if specified
102
- if (value && testKey !== value) {
103
- logger.debug({ uid }, `${testKey} does not match ${value}`);
104
- return true;
105
- }
106
- }
107
-
108
- // No failed filters, so we should not skip this request
109
- return false;
30
+ export function shouldSkipRequest(
31
+ binding: Binding,
32
+ req: AdmissionRequest,
33
+ capabilityNamespaces: string[],
34
+ ignoredNamespaces?: string[],
35
+ ): boolean {
36
+ const obj = req.operation === Operation.DELETE ? req.oldObject : req.object;
37
+
38
+ // prettier-ignore
39
+ return (
40
+ misboundDeleteWithDeletionTimestamp(binding) ? true :
41
+ mismatchedDeletionTimestamp(binding, obj) ? true :
42
+ mismatchedEvent(binding, req) ? true :
43
+ mismatchedName(binding, obj) ? true :
44
+ mismatchedGroup(binding, req) ? true :
45
+ mismatchedVersion(binding, req) ? true :
46
+ mismatchedKind(binding, req) ? true :
47
+ unbindableNamespaces(capabilityNamespaces, binding) ? true :
48
+ uncarryableNamespace(capabilityNamespaces, obj) ? true :
49
+ mismatchedNamespace(binding, obj) ? true :
50
+ mismatchedLabels(binding, obj) ? true :
51
+ mismatchedAnnotations(binding, obj) ? true :
52
+ mismatchedNamespaceRegex(binding, obj) ? true :
53
+ mismatchedNameRegex(binding, obj) ? true :
54
+ carriesIgnoredNamespace(ignoredNamespaces, obj) ? true :
55
+
56
+ false
57
+ );
110
58
  }