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.
- package/dist/cli/init/index.d.ts.map +1 -1
- package/dist/cli/init/templates.d.ts +3 -1
- package/dist/cli/init/templates.d.ts.map +1 -1
- package/dist/cli/init/utils.d.ts.map +1 -1
- package/dist/cli/init/walkthrough.d.ts +10 -3
- package/dist/cli/init/walkthrough.d.ts.map +1 -1
- package/dist/cli.js +253 -31
- package/dist/controller.js +138 -1
- package/dist/lib/adjudicators.d.ts +63 -0
- package/dist/lib/adjudicators.d.ts.map +1 -0
- package/dist/lib/adjudicators.test.d.ts +2 -0
- package/dist/lib/adjudicators.test.d.ts.map +1 -0
- package/dist/lib/assets/loader.d.ts.map +1 -1
- package/dist/lib/assets/pods.d.ts +1 -0
- package/dist/lib/assets/pods.d.ts.map +1 -1
- package/dist/lib/capability.d.ts +1 -0
- package/dist/lib/capability.d.ts.map +1 -1
- package/dist/lib/capability.test.d.ts +2 -0
- package/dist/lib/capability.test.d.ts.map +1 -0
- package/dist/lib/controller/index.d.ts.map +1 -1
- package/dist/lib/controller/store.d.ts +4 -0
- package/dist/lib/controller/store.d.ts.map +1 -1
- package/dist/lib/controller/store.test.d.ts +2 -0
- package/dist/lib/controller/store.test.d.ts.map +1 -0
- package/dist/lib/filter.d.ts +2 -3
- package/dist/lib/filter.d.ts.map +1 -1
- package/dist/lib/filter.test.d.ts +2 -1
- package/dist/lib/filter.test.d.ts.map +1 -1
- package/dist/lib/finalizer.d.ts +6 -0
- package/dist/lib/finalizer.d.ts.map +1 -0
- package/dist/lib/finalizer.test.d.ts +2 -0
- package/dist/lib/finalizer.test.d.ts.map +1 -0
- package/dist/lib/helpers.d.ts +2 -2
- package/dist/lib/helpers.d.ts.map +1 -1
- package/dist/lib/helpers.test.d.ts +1 -1
- package/dist/lib/helpers.test.d.ts.map +1 -1
- package/dist/lib/k8s.d.ts.map +1 -1
- package/dist/lib/logger.d.ts +1 -1
- package/dist/lib/logger.d.ts.map +1 -1
- package/dist/lib/module.d.ts +2 -1
- package/dist/lib/module.d.ts.map +1 -1
- package/dist/lib/mutate-processor.d.ts +2 -1
- package/dist/lib/mutate-processor.d.ts.map +1 -1
- package/dist/lib/mutate-request.d.ts +1 -2
- package/dist/lib/mutate-request.d.ts.map +1 -1
- package/dist/lib/queue.d.ts +19 -3
- package/dist/lib/queue.d.ts.map +1 -1
- package/dist/lib/schedule.d.ts +1 -2
- package/dist/lib/schedule.d.ts.map +1 -1
- package/dist/lib/storage.d.ts.map +1 -1
- package/dist/lib/types.d.ts +118 -6
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/validate-processor.d.ts +4 -2
- package/dist/lib/validate-processor.d.ts.map +1 -1
- package/dist/lib/validate-request.d.ts +1 -1
- package/dist/lib/validate-request.d.ts.map +1 -1
- package/dist/lib/watch-processor.d.ts +8 -6
- package/dist/lib/watch-processor.d.ts.map +1 -1
- package/dist/lib.js +467 -233
- package/dist/lib.js.map +4 -4
- package/dist/sdk/sdk.d.ts +5 -3
- package/dist/sdk/sdk.d.ts.map +1 -1
- package/package.json +13 -11
- package/src/cli/build.ts +3 -3
- package/src/cli/init/index.ts +20 -11
- package/src/cli/init/templates.ts +1 -1
- package/src/cli/init/utils.test.ts +11 -20
- package/src/cli/init/utils.ts +5 -0
- package/src/cli/init/walkthrough.test.ts +92 -11
- package/src/cli/init/walkthrough.ts +71 -16
- package/src/cli/monitor.ts +1 -1
- package/src/cli.ts +4 -2
- package/src/fixtures/data/create-pod.json +1 -1
- package/src/fixtures/data/delete-pod.json +1 -1
- package/src/lib/adjudicators.test.ts +1232 -0
- package/src/lib/adjudicators.ts +235 -0
- package/src/lib/assets/index.ts +1 -1
- package/src/lib/assets/loader.ts +1 -0
- package/src/lib/assets/webhooks.ts +1 -1
- package/src/lib/capability.test.ts +655 -0
- package/src/lib/capability.ts +112 -11
- package/src/lib/controller/index.ts +7 -4
- package/src/lib/controller/store.test.ts +131 -0
- package/src/lib/controller/store.ts +43 -5
- package/src/lib/filter.test.ts +279 -9
- package/src/lib/filter.ts +46 -98
- package/src/lib/finalizer.test.ts +236 -0
- package/src/lib/finalizer.ts +63 -0
- package/src/lib/helpers.test.ts +359 -65
- package/src/lib/helpers.ts +141 -95
- package/src/lib/k8s.ts +4 -0
- package/src/lib/module.ts +3 -3
- package/src/lib/mutate-processor.ts +5 -4
- package/src/lib/mutate-request.test.ts +1 -2
- package/src/lib/mutate-request.ts +1 -3
- package/src/lib/queue.test.ts +138 -44
- package/src/lib/queue.ts +48 -13
- package/src/lib/schedule.ts +1 -1
- package/src/lib/storage.ts +5 -6
- package/src/lib/types.ts +154 -5
- package/src/lib/validate-processor.ts +5 -2
- package/src/lib/validate-request.test.ts +1 -4
- package/src/lib/validate-request.ts +1 -1
- package/src/lib/watch-processor.test.ts +89 -124
- package/src/lib/watch-processor.ts +52 -35
- package/src/sdk/sdk.test.ts +46 -13
- package/src/sdk/sdk.ts +15 -6
package/src/lib/filter.test.ts
CHANGED
|
@@ -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 {
|
|
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: "
|
|
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
|
|
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: ["
|
|
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 "./
|
|
5
|
-
import
|
|
6
|
-
|
|
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(
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
}
|