pepr 0.34.1 → 0.36.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/templates.d.ts +1 -0
- package/dist/cli/init/templates.d.ts.map +1 -1
- package/dist/cli.js +48 -23
- package/dist/controller.js +1 -1
- package/dist/lib/assets/helm.d.ts.map +1 -1
- package/dist/lib/assets/pods.d.ts.map +1 -1
- package/dist/lib/assets/yaml.d.ts.map +1 -1
- package/dist/lib/capability.d.ts.map +1 -1
- package/dist/lib/filter.d.ts.map +1 -1
- package/dist/lib/helpers.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/queue.d.ts +19 -3
- package/dist/lib/queue.d.ts.map +1 -1
- package/dist/lib/types.d.ts +3 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib/watch-processor.d.ts +10 -1
- package/dist/lib/watch-processor.d.ts.map +1 -1
- package/dist/lib.js +104 -32
- package/dist/lib.js.map +3 -3
- package/dist/sdk/sdk.d.ts +5 -3
- package/dist/sdk/sdk.d.ts.map +1 -1
- package/package.json +10 -10
- package/src/cli/init/templates.ts +1 -0
- package/src/lib/assets/helm.ts +4 -16
- package/src/lib/assets/pods.ts +4 -0
- package/src/lib/assets/yaml.ts +32 -0
- package/src/lib/capability.ts +9 -1
- package/src/lib/filter.test.ts +85 -1
- package/src/lib/filter.ts +9 -0
- package/src/lib/helpers.test.ts +34 -0
- package/src/lib/helpers.ts +5 -0
- package/src/lib/queue.test.ts +138 -44
- package/src/lib/queue.ts +48 -13
- package/src/lib/types.ts +3 -0
- package/src/lib/watch-processor.test.ts +101 -5
- package/src/lib/watch-processor.ts +49 -16
- package/src/sdk/sdk.test.ts +46 -13
- package/src/sdk/sdk.ts +15 -6
- package/src/templates/capabilities/hello-pepr.ts +9 -0
package/dist/sdk/sdk.d.ts
CHANGED
|
@@ -24,10 +24,12 @@ export declare function containers(request: PeprValidateRequest<a.Pod> | PeprMut
|
|
|
24
24
|
export declare function writeEvent(cr: GenericKind, event: Partial<kind.CoreEvent>, eventType: string, eventReason: string, reportingComponent: string, reportingInstance: string): Promise<void>;
|
|
25
25
|
/**
|
|
26
26
|
* Get the owner reference for a custom resource
|
|
27
|
-
* @param
|
|
28
|
-
* @
|
|
27
|
+
* @param customResource the custom resource to get the owner reference for
|
|
28
|
+
* @param blockOwnerDeletion if true, AND if the owner has the "foregroundDeletion" finalizer, then the owner cannot be deleted from the key-value store until this reference is removed.
|
|
29
|
+
* @param controller if true, this reference points to the managing controller.
|
|
30
|
+
* @returns the owner reference array for the custom resource
|
|
29
31
|
*/
|
|
30
|
-
export declare function getOwnerRefFrom(
|
|
32
|
+
export declare function getOwnerRefFrom(customResource: GenericKind, blockOwnerDeletion?: boolean, controller?: boolean): V1OwnerReference[];
|
|
31
33
|
/**
|
|
32
34
|
* Sanitize a resource name to make it a valid Kubernetes resource name.
|
|
33
35
|
*
|
package/dist/sdk/sdk.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/sdk/sdk.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAO,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAGrD;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,EAC9D,aAAa,CAAC,EAAE,YAAY,GAAG,gBAAgB,GAAG,qBAAqB,mDAgBxE;AAED;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,WAAW,EACf,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAC9B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,kBAAkB,EAAE,MAAM,EAC1B,iBAAiB,EAAE,MAAM,iBAwB1B;AAED
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/sdk/sdk.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAC3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAO,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAGrD;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,mBAAmB,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,EAC9D,aAAa,CAAC,EAAE,YAAY,GAAG,gBAAgB,GAAG,qBAAqB,mDAgBxE;AAED;;;;;;;;;GASG;AACH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,WAAW,EACf,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAC9B,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,EACnB,kBAAkB,EAAE,MAAM,EAC1B,iBAAiB,EAAE,MAAM,iBAwB1B;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,cAAc,EAAE,WAAW,EAC3B,kBAAkB,CAAC,EAAE,OAAO,EAC5B,UAAU,CAAC,EAAE,OAAO,GACnB,gBAAgB,EAAE,CAcpB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,UAYhD"}
|
package/package.json
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
"/dist",
|
|
14
14
|
"/src"
|
|
15
15
|
],
|
|
16
|
-
"version": "0.
|
|
16
|
+
"version": "0.36.0",
|
|
17
17
|
"main": "dist/lib.js",
|
|
18
18
|
"types": "dist/lib.d.ts",
|
|
19
19
|
"scripts": {
|
|
@@ -38,22 +38,22 @@
|
|
|
38
38
|
"format:fix": "eslint src --fix && prettier src --write"
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"@types/ramda": "0.30.
|
|
42
|
-
"express": "4.
|
|
41
|
+
"@types/ramda": "0.30.2",
|
|
42
|
+
"express": "4.21.0",
|
|
43
43
|
"fast-json-patch": "3.1.1",
|
|
44
44
|
"json-pointer": "^0.6.2",
|
|
45
|
-
"kubernetes-fluent-client": "3.0.
|
|
46
|
-
"pino": "9.
|
|
45
|
+
"kubernetes-fluent-client": "3.0.3",
|
|
46
|
+
"pino": "9.4.0",
|
|
47
47
|
"pino-pretty": "11.2.2",
|
|
48
48
|
"prom-client": "15.1.3",
|
|
49
49
|
"ramda": "0.30.1"
|
|
50
50
|
},
|
|
51
51
|
"devDependencies": {
|
|
52
|
-
"@commitlint/cli": "19.
|
|
53
|
-
"@commitlint/config-conventional": "19.
|
|
52
|
+
"@commitlint/cli": "19.5.0",
|
|
53
|
+
"@commitlint/config-conventional": "19.5.0",
|
|
54
54
|
"@fast-check/jest": "^2.0.1",
|
|
55
55
|
"@jest/globals": "29.7.0",
|
|
56
|
-
"@types/eslint": "9.6.
|
|
56
|
+
"@types/eslint": "9.6.1",
|
|
57
57
|
"@types/express": "4.17.21",
|
|
58
58
|
"@types/json-pointer": "^1.0.34",
|
|
59
59
|
"@types/node": "22.x.x",
|
|
@@ -63,8 +63,8 @@
|
|
|
63
63
|
"fast-check": "^3.19.0",
|
|
64
64
|
"jest": "29.7.0",
|
|
65
65
|
"js-yaml": "^4.1.0",
|
|
66
|
-
"nock": "13.5.4",
|
|
67
|
-
"ts-jest": "29.2.
|
|
66
|
+
"nock": "^13.5.4",
|
|
67
|
+
"ts-jest": "29.2.5"
|
|
68
68
|
},
|
|
69
69
|
"peerDependencies": {
|
|
70
70
|
"@typescript-eslint/eslint-plugin": "7.18.0",
|
package/src/lib/assets/helm.ts
CHANGED
|
@@ -90,15 +90,9 @@ export function watcherDeployTemplate(buildTimestamp: string) {
|
|
|
90
90
|
- /app/node_modules/pepr/dist/controller.js
|
|
91
91
|
- {{ .Values.hash }}
|
|
92
92
|
readinessProbe:
|
|
93
|
-
|
|
94
|
-
path: /healthz
|
|
95
|
-
port: 3000
|
|
96
|
-
scheme: HTTPS
|
|
93
|
+
{{- toYaml .Values.watcher.readinessProbe | nindent 12 }}
|
|
97
94
|
livenessProbe:
|
|
98
|
-
|
|
99
|
-
path: /healthz
|
|
100
|
-
port: 3000
|
|
101
|
-
scheme: HTTPS
|
|
95
|
+
{{- toYaml .Values.watcher.livenessProbe | nindent 12 }}
|
|
102
96
|
ports:
|
|
103
97
|
- containerPort: 3000
|
|
104
98
|
resources:
|
|
@@ -176,15 +170,9 @@ export function admissionDeployTemplate(buildTimestamp: string) {
|
|
|
176
170
|
- /app/node_modules/pepr/dist/controller.js
|
|
177
171
|
- {{ .Values.hash }}
|
|
178
172
|
readinessProbe:
|
|
179
|
-
|
|
180
|
-
path: /healthz
|
|
181
|
-
port: 3000
|
|
182
|
-
scheme: HTTPS
|
|
173
|
+
{{- toYaml .Values.admission.readinessProbe | nindent 12 }}
|
|
183
174
|
livenessProbe:
|
|
184
|
-
|
|
185
|
-
path: /healthz
|
|
186
|
-
port: 3000
|
|
187
|
-
scheme: HTTPS
|
|
175
|
+
{{- toYaml .Values.admission.livenessProbe | nindent 12 }}
|
|
188
176
|
ports:
|
|
189
177
|
- containerPort: 3000
|
|
190
178
|
resources:
|
package/src/lib/assets/pods.ts
CHANGED
|
@@ -111,6 +111,7 @@ export function watcher(assets: Assets, hash: string, buildTimestamp: string, im
|
|
|
111
111
|
port: 3000,
|
|
112
112
|
scheme: "HTTPS",
|
|
113
113
|
},
|
|
114
|
+
initialDelaySeconds: 10,
|
|
114
115
|
},
|
|
115
116
|
livenessProbe: {
|
|
116
117
|
httpGet: {
|
|
@@ -118,6 +119,7 @@ export function watcher(assets: Assets, hash: string, buildTimestamp: string, im
|
|
|
118
119
|
port: 3000,
|
|
119
120
|
scheme: "HTTPS",
|
|
120
121
|
},
|
|
122
|
+
initialDelaySeconds: 10,
|
|
121
123
|
},
|
|
122
124
|
ports: [
|
|
123
125
|
{
|
|
@@ -248,6 +250,7 @@ export function deployment(
|
|
|
248
250
|
port: 3000,
|
|
249
251
|
scheme: "HTTPS",
|
|
250
252
|
},
|
|
253
|
+
initialDelaySeconds: 10,
|
|
251
254
|
},
|
|
252
255
|
livenessProbe: {
|
|
253
256
|
httpGet: {
|
|
@@ -255,6 +258,7 @@ export function deployment(
|
|
|
255
258
|
port: 3000,
|
|
256
259
|
scheme: "HTTPS",
|
|
257
260
|
},
|
|
261
|
+
initialDelaySeconds: 10,
|
|
258
262
|
},
|
|
259
263
|
ports: [
|
|
260
264
|
{
|
package/src/lib/assets/yaml.ts
CHANGED
|
@@ -45,6 +45,22 @@ export async function overridesFile({ hash, name, image, config, apiToken }: Ass
|
|
|
45
45
|
runAsNonRoot: true,
|
|
46
46
|
fsGroup: 65532,
|
|
47
47
|
},
|
|
48
|
+
readinessProbe: {
|
|
49
|
+
httpGet: {
|
|
50
|
+
path: "/healthz",
|
|
51
|
+
port: 3000,
|
|
52
|
+
scheme: "HTTPS",
|
|
53
|
+
},
|
|
54
|
+
initialDelaySeconds: 10,
|
|
55
|
+
},
|
|
56
|
+
livenessProbe: {
|
|
57
|
+
httpGet: {
|
|
58
|
+
path: "/healthz",
|
|
59
|
+
port: 3000,
|
|
60
|
+
scheme: "HTTPS",
|
|
61
|
+
},
|
|
62
|
+
initialDelaySeconds: 10,
|
|
63
|
+
},
|
|
48
64
|
resources: {
|
|
49
65
|
requests: {
|
|
50
66
|
memory: "64Mi",
|
|
@@ -95,6 +111,22 @@ export async function overridesFile({ hash, name, image, config, apiToken }: Ass
|
|
|
95
111
|
runAsNonRoot: true,
|
|
96
112
|
fsGroup: 65532,
|
|
97
113
|
},
|
|
114
|
+
readinessProbe: {
|
|
115
|
+
httpGet: {
|
|
116
|
+
path: "/healthz",
|
|
117
|
+
port: 3000,
|
|
118
|
+
scheme: "HTTPS",
|
|
119
|
+
},
|
|
120
|
+
initialDelaySeconds: 10,
|
|
121
|
+
},
|
|
122
|
+
livenessProbe: {
|
|
123
|
+
httpGet: {
|
|
124
|
+
path: "/healthz",
|
|
125
|
+
port: 3000,
|
|
126
|
+
scheme: "HTTPS",
|
|
127
|
+
},
|
|
128
|
+
initialDelaySeconds: 10,
|
|
129
|
+
},
|
|
98
130
|
resources: {
|
|
99
131
|
requests: {
|
|
100
132
|
memory: "64Mi",
|
package/src/lib/capability.ts
CHANGED
|
@@ -198,12 +198,13 @@ export class Capability implements CapabilityExport {
|
|
|
198
198
|
namespaces: [],
|
|
199
199
|
labels: {},
|
|
200
200
|
annotations: {},
|
|
201
|
+
deletionTimestamp: false,
|
|
201
202
|
},
|
|
202
203
|
};
|
|
203
204
|
|
|
204
205
|
const bindings = this.#bindings;
|
|
205
206
|
const prefix = `${this.#name}: ${model.name}`;
|
|
206
|
-
const commonChain = { WithLabel, WithAnnotation, Mutate, Validate, Watch, Reconcile };
|
|
207
|
+
const commonChain = { WithLabel, WithAnnotation, WithDeletionTimestamp, Mutate, Validate, Watch, Reconcile };
|
|
207
208
|
const isNotEmpty = (value: object) => Object.keys(value).length > 0;
|
|
208
209
|
const log = (message: string, cbString: string) => {
|
|
209
210
|
const filteredObj = pickBy(isNotEmpty, binding.filters);
|
|
@@ -277,6 +278,12 @@ export class Capability implements CapabilityExport {
|
|
|
277
278
|
return { ...commonChain, WithName };
|
|
278
279
|
}
|
|
279
280
|
|
|
281
|
+
function WithDeletionTimestamp(): BindingFilter<T> {
|
|
282
|
+
Log.debug("Add deletionTimestamp filter");
|
|
283
|
+
binding.filters.deletionTimestamp = true;
|
|
284
|
+
return commonChain;
|
|
285
|
+
}
|
|
286
|
+
|
|
280
287
|
function WithName(name: string): BindingFilter<T> {
|
|
281
288
|
Log.debug(`Add name filter ${name}`, prefix);
|
|
282
289
|
binding.filters.name = name;
|
|
@@ -301,6 +308,7 @@ export class Capability implements CapabilityExport {
|
|
|
301
308
|
...commonChain,
|
|
302
309
|
InNamespace,
|
|
303
310
|
WithName,
|
|
311
|
+
WithDeletionTimestamp,
|
|
304
312
|
};
|
|
305
313
|
}
|
|
306
314
|
|
package/src/lib/filter.test.ts
CHANGED
|
@@ -29,6 +29,7 @@ describe("Fuzzing shouldSkipRequest", () => {
|
|
|
29
29
|
namespaces: fc.array(fc.string()),
|
|
30
30
|
labels: fc.dictionary(fc.string(), fc.string()),
|
|
31
31
|
annotations: fc.dictionary(fc.string(), fc.string()),
|
|
32
|
+
deletionTimestamp: fc.boolean(),
|
|
32
33
|
}),
|
|
33
34
|
}),
|
|
34
35
|
fc.record({
|
|
@@ -41,6 +42,11 @@ describe("Fuzzing shouldSkipRequest", () => {
|
|
|
41
42
|
version: fc.string(),
|
|
42
43
|
kind: fc.string(),
|
|
43
44
|
}),
|
|
45
|
+
object: fc.record({
|
|
46
|
+
metadata: fc.record({
|
|
47
|
+
deletionTimestamp: fc.option(fc.date()),
|
|
48
|
+
}),
|
|
49
|
+
}),
|
|
44
50
|
}),
|
|
45
51
|
fc.array(fc.string()),
|
|
46
52
|
(binding, req, capabilityNamespaces) => {
|
|
@@ -69,6 +75,7 @@ describe("Property-Based Testing shouldSkipRequest", () => {
|
|
|
69
75
|
namespaces: fc.array(fc.string()),
|
|
70
76
|
labels: fc.dictionary(fc.string(), fc.string()),
|
|
71
77
|
annotations: fc.dictionary(fc.string(), fc.string()),
|
|
78
|
+
deletionTimestamp: fc.boolean(),
|
|
72
79
|
}),
|
|
73
80
|
}),
|
|
74
81
|
fc.record({
|
|
@@ -81,6 +88,11 @@ describe("Property-Based Testing shouldSkipRequest", () => {
|
|
|
81
88
|
version: fc.string(),
|
|
82
89
|
kind: fc.string(),
|
|
83
90
|
}),
|
|
91
|
+
object: fc.record({
|
|
92
|
+
metadata: fc.record({
|
|
93
|
+
deletionTimestamp: fc.option(fc.date()),
|
|
94
|
+
}),
|
|
95
|
+
}),
|
|
84
96
|
}),
|
|
85
97
|
fc.array(fc.string()),
|
|
86
98
|
(binding, req, capabilityNamespaces) => {
|
|
@@ -103,6 +115,7 @@ test("should reject when name does not match", () => {
|
|
|
103
115
|
namespaces: [],
|
|
104
116
|
labels: {},
|
|
105
117
|
annotations: {},
|
|
118
|
+
deletionTimestamp: false,
|
|
106
119
|
},
|
|
107
120
|
callback,
|
|
108
121
|
};
|
|
@@ -121,6 +134,7 @@ test("should reject when kind does not match", () => {
|
|
|
121
134
|
namespaces: [],
|
|
122
135
|
labels: {},
|
|
123
136
|
annotations: {},
|
|
137
|
+
deletionTimestamp: false,
|
|
124
138
|
},
|
|
125
139
|
callback,
|
|
126
140
|
};
|
|
@@ -139,6 +153,7 @@ test("should reject when group does not match", () => {
|
|
|
139
153
|
namespaces: [],
|
|
140
154
|
labels: {},
|
|
141
155
|
annotations: {},
|
|
156
|
+
deletionTimestamp: false,
|
|
142
157
|
},
|
|
143
158
|
callback,
|
|
144
159
|
};
|
|
@@ -161,6 +176,7 @@ test("should reject when version does not match", () => {
|
|
|
161
176
|
namespaces: [],
|
|
162
177
|
labels: {},
|
|
163
178
|
annotations: {},
|
|
179
|
+
deletionTimestamp: false,
|
|
164
180
|
},
|
|
165
181
|
callback,
|
|
166
182
|
};
|
|
@@ -179,6 +195,7 @@ test("should allow when group, version, and kind match", () => {
|
|
|
179
195
|
namespaces: [],
|
|
180
196
|
labels: {},
|
|
181
197
|
annotations: {},
|
|
198
|
+
deletionTimestamp: false,
|
|
182
199
|
},
|
|
183
200
|
callback,
|
|
184
201
|
};
|
|
@@ -201,6 +218,7 @@ test("should allow when kind match and others are empty", () => {
|
|
|
201
218
|
namespaces: [],
|
|
202
219
|
labels: {},
|
|
203
220
|
annotations: {},
|
|
221
|
+
deletionTimestamp: false,
|
|
204
222
|
},
|
|
205
223
|
callback,
|
|
206
224
|
};
|
|
@@ -219,6 +237,7 @@ test("should reject when teh capability namespace does not match", () => {
|
|
|
219
237
|
namespaces: [],
|
|
220
238
|
labels: {},
|
|
221
239
|
annotations: {},
|
|
240
|
+
deletionTimestamp: false,
|
|
222
241
|
},
|
|
223
242
|
callback,
|
|
224
243
|
};
|
|
@@ -237,6 +256,7 @@ test("should reject when namespace does not match", () => {
|
|
|
237
256
|
namespaces: ["bleh"],
|
|
238
257
|
labels: {},
|
|
239
258
|
annotations: {},
|
|
259
|
+
deletionTimestamp: false,
|
|
240
260
|
},
|
|
241
261
|
callback,
|
|
242
262
|
};
|
|
@@ -255,6 +275,7 @@ test("should allow when namespace is match", () => {
|
|
|
255
275
|
namespaces: ["default", "unicorn", "things"],
|
|
256
276
|
labels: {},
|
|
257
277
|
annotations: {},
|
|
278
|
+
deletionTimestamp: false,
|
|
258
279
|
},
|
|
259
280
|
callback,
|
|
260
281
|
};
|
|
@@ -275,6 +296,7 @@ test("should reject when label does not match", () => {
|
|
|
275
296
|
foo: "bar",
|
|
276
297
|
},
|
|
277
298
|
annotations: {},
|
|
299
|
+
deletionTimestamp: false,
|
|
278
300
|
},
|
|
279
301
|
callback,
|
|
280
302
|
};
|
|
@@ -290,7 +312,7 @@ test("should allow when label is match", () => {
|
|
|
290
312
|
kind: podKind,
|
|
291
313
|
filters: {
|
|
292
314
|
name: "",
|
|
293
|
-
|
|
315
|
+
deletionTimestamp: false,
|
|
294
316
|
namespaces: [],
|
|
295
317
|
labels: {
|
|
296
318
|
foo: "bar",
|
|
@@ -324,6 +346,7 @@ test("should reject when annotation does not match", () => {
|
|
|
324
346
|
annotations: {
|
|
325
347
|
foo: "bar",
|
|
326
348
|
},
|
|
349
|
+
deletionTimestamp: false,
|
|
327
350
|
},
|
|
328
351
|
callback,
|
|
329
352
|
};
|
|
@@ -345,6 +368,7 @@ test("should allow when annotation is match", () => {
|
|
|
345
368
|
foo: "bar",
|
|
346
369
|
test: "test1",
|
|
347
370
|
},
|
|
371
|
+
deletionTimestamp: false,
|
|
348
372
|
},
|
|
349
373
|
callback,
|
|
350
374
|
};
|
|
@@ -368,6 +392,7 @@ test("should use `oldObject` when the operation is `DELETE`", () => {
|
|
|
368
392
|
filters: {
|
|
369
393
|
name: "",
|
|
370
394
|
namespaces: [],
|
|
395
|
+
deletionTimestamp: false,
|
|
371
396
|
labels: {
|
|
372
397
|
"app.kubernetes.io/name": "cool-name-podinfo",
|
|
373
398
|
},
|
|
@@ -382,3 +407,62 @@ test("should use `oldObject` when the operation is `DELETE`", () => {
|
|
|
382
407
|
|
|
383
408
|
expect(shouldSkipRequest(binding, pod, [])).toBe(false);
|
|
384
409
|
});
|
|
410
|
+
|
|
411
|
+
test("should skip processing when deletionTimestamp is not present on pod", () => {
|
|
412
|
+
const binding = {
|
|
413
|
+
model: kind.Pod,
|
|
414
|
+
event: Event.Any,
|
|
415
|
+
kind: podKind,
|
|
416
|
+
filters: {
|
|
417
|
+
name: "",
|
|
418
|
+
namespaces: [],
|
|
419
|
+
labels: {},
|
|
420
|
+
annotations: {
|
|
421
|
+
foo: "bar",
|
|
422
|
+
test: "test1",
|
|
423
|
+
},
|
|
424
|
+
deletionTimestamp: true,
|
|
425
|
+
},
|
|
426
|
+
callback,
|
|
427
|
+
};
|
|
428
|
+
|
|
429
|
+
const pod = CreatePod();
|
|
430
|
+
pod.object.metadata = pod.object.metadata || {};
|
|
431
|
+
pod.object.metadata.annotations = {
|
|
432
|
+
foo: "bar",
|
|
433
|
+
test: "test1",
|
|
434
|
+
test2: "test2",
|
|
435
|
+
};
|
|
436
|
+
|
|
437
|
+
expect(shouldSkipRequest(binding, pod, [])).toBe(true);
|
|
438
|
+
});
|
|
439
|
+
|
|
440
|
+
test("should processing when deletionTimestamp is not present on pod", () => {
|
|
441
|
+
const binding = {
|
|
442
|
+
model: kind.Pod,
|
|
443
|
+
event: Event.Any,
|
|
444
|
+
kind: podKind,
|
|
445
|
+
filters: {
|
|
446
|
+
name: "",
|
|
447
|
+
namespaces: [],
|
|
448
|
+
labels: {},
|
|
449
|
+
annotations: {
|
|
450
|
+
foo: "bar",
|
|
451
|
+
test: "test1",
|
|
452
|
+
},
|
|
453
|
+
deletionTimestamp: true,
|
|
454
|
+
},
|
|
455
|
+
callback,
|
|
456
|
+
};
|
|
457
|
+
|
|
458
|
+
const pod = CreatePod();
|
|
459
|
+
pod.object.metadata = pod.object.metadata || {};
|
|
460
|
+
pod.object.metadata!.deletionTimestamp = new Date("2021-09-01T00:00:00Z");
|
|
461
|
+
pod.object.metadata.annotations = {
|
|
462
|
+
foo: "bar",
|
|
463
|
+
test: "test1",
|
|
464
|
+
test2: "test2",
|
|
465
|
+
};
|
|
466
|
+
|
|
467
|
+
expect(shouldSkipRequest(binding, pod, [])).toBe(false);
|
|
468
|
+
});
|
package/src/lib/filter.ts
CHANGED
|
@@ -22,6 +22,15 @@ export function shouldSkipRequest(binding: Binding, req: AdmissionRequest, capab
|
|
|
22
22
|
const { metadata } = srcObject || {};
|
|
23
23
|
const combinedNamespaces = [...namespaces, ...capabilityNamespaces];
|
|
24
24
|
|
|
25
|
+
// Delete bindings do not work through admission with DeletionTimestamp
|
|
26
|
+
if (binding.event.includes(Event.Delete) && binding.filters?.deletionTimestamp) {
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Test for deletionTimestamp
|
|
31
|
+
if (binding.filters?.deletionTimestamp && !req.object.metadata?.deletionTimestamp) {
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
25
34
|
// Test for matching operation
|
|
26
35
|
if (!binding.event.includes(operation) && !binding.event.includes(Event.Any)) {
|
|
27
36
|
return true;
|
package/src/lib/helpers.test.ts
CHANGED
|
@@ -1056,6 +1056,40 @@ describe("filterMatcher", () => {
|
|
|
1056
1056
|
expect(result).toEqual("Ignoring Watch Callback: Cannot use a namespace filter in a namespace object.");
|
|
1057
1057
|
});
|
|
1058
1058
|
|
|
1059
|
+
test("return deletionTimestamp error when there is no deletionTimestamp in the object", () => {
|
|
1060
|
+
const binding = {
|
|
1061
|
+
filters: { deletionTimestamp: true },
|
|
1062
|
+
};
|
|
1063
|
+
const obj = {
|
|
1064
|
+
metadata: {},
|
|
1065
|
+
};
|
|
1066
|
+
const capabilityNamespaces: string[] = [];
|
|
1067
|
+
const result = filterNoMatchReason(
|
|
1068
|
+
binding as unknown as Partial<Binding>,
|
|
1069
|
+
obj as unknown as Partial<KubernetesObject>,
|
|
1070
|
+
capabilityNamespaces,
|
|
1071
|
+
);
|
|
1072
|
+
expect(result).toEqual("Ignoring Watch Callback: Object does not have a deletion timestamp.");
|
|
1073
|
+
});
|
|
1074
|
+
|
|
1075
|
+
test("return no deletionTimestamp error when there is a deletionTimestamp in the object", () => {
|
|
1076
|
+
const binding = {
|
|
1077
|
+
filters: { deletionTimestamp: true },
|
|
1078
|
+
};
|
|
1079
|
+
const obj = {
|
|
1080
|
+
metadata: {
|
|
1081
|
+
deletionTimestamp: "2021-01-01T00:00:00Z",
|
|
1082
|
+
},
|
|
1083
|
+
};
|
|
1084
|
+
const capabilityNamespaces: string[] = [];
|
|
1085
|
+
const result = filterNoMatchReason(
|
|
1086
|
+
binding as unknown as Partial<Binding>,
|
|
1087
|
+
obj as unknown as Partial<KubernetesObject>,
|
|
1088
|
+
capabilityNamespaces,
|
|
1089
|
+
);
|
|
1090
|
+
expect(result).not.toEqual("Ignoring Watch Callback: Object does not have a deletion timestamp.");
|
|
1091
|
+
});
|
|
1092
|
+
|
|
1059
1093
|
test("returns label overlap error when there is no overlap between binding and object labels", () => {
|
|
1060
1094
|
const binding = {
|
|
1061
1095
|
filters: { labels: { key: "value" } },
|
package/src/lib/helpers.ts
CHANGED
|
@@ -73,6 +73,11 @@ export function filterNoMatchReason(
|
|
|
73
73
|
obj: Partial<KubernetesObject>,
|
|
74
74
|
capabilityNamespaces: string[],
|
|
75
75
|
): string {
|
|
76
|
+
// binding deletionTimestamp filter and object deletionTimestamp dont match
|
|
77
|
+
if (binding.filters?.deletionTimestamp && !obj.metadata?.deletionTimestamp) {
|
|
78
|
+
return `Ignoring Watch Callback: Object does not have a deletion timestamp.`;
|
|
79
|
+
}
|
|
80
|
+
|
|
76
81
|
// binding kind is namespace with a InNamespace filter
|
|
77
82
|
if (binding.kind && binding.kind.kind === "Namespace" && binding.filters && binding.filters.namespaces.length !== 0) {
|
|
78
83
|
return `Ignoring Watch Callback: Cannot use a namespace filter in a namespace object.`;
|