pepr 0.38.3 → 0.39.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 (95) hide show
  1. package/dist/cli/build.d.ts +1 -1
  2. package/dist/cli/build.d.ts.map +1 -1
  3. package/dist/cli/build.helpers.d.ts +19 -0
  4. package/dist/cli/build.helpers.d.ts.map +1 -0
  5. package/dist/cli/deploy.d.ts.map +1 -1
  6. package/dist/cli/format.d.ts.map +1 -1
  7. package/dist/cli/init/index.d.ts.map +1 -1
  8. package/dist/cli/init/templates.d.ts +6 -2
  9. package/dist/cli/init/templates.d.ts.map +1 -1
  10. package/dist/cli/monitor.d.ts.map +1 -1
  11. package/dist/cli.js +278 -225
  12. package/dist/controller.js +37 -27
  13. package/dist/lib/assets/deploy.d.ts.map +1 -1
  14. package/dist/lib/assets/helm.d.ts +1 -0
  15. package/dist/lib/assets/helm.d.ts.map +1 -1
  16. package/dist/lib/assets/index.d.ts +1 -1
  17. package/dist/lib/assets/index.d.ts.map +1 -1
  18. package/dist/lib/assets/rbac.d.ts +31 -4
  19. package/dist/lib/assets/rbac.d.ts.map +1 -1
  20. package/dist/lib/assets/yaml.d.ts +2 -2
  21. package/dist/lib/assets/yaml.d.ts.map +1 -1
  22. package/dist/lib/capability.d.ts +2 -8
  23. package/dist/lib/capability.d.ts.map +1 -1
  24. package/dist/lib/controller/store.d.ts +1 -5
  25. package/dist/lib/controller/store.d.ts.map +1 -1
  26. package/dist/lib/controller/storeCache.d.ts +11 -0
  27. package/dist/lib/controller/storeCache.d.ts.map +1 -0
  28. package/dist/lib/enums.d.ts +17 -0
  29. package/dist/lib/enums.d.ts.map +1 -0
  30. package/dist/lib/{adjudicators.d.ts → filter/adjudicators.d.ts} +15 -13
  31. package/dist/lib/filter/adjudicators.d.ts.map +1 -0
  32. package/dist/lib/{filter.d.ts → filter/filter.d.ts} +1 -1
  33. package/dist/lib/filter/filter.d.ts.map +1 -0
  34. package/dist/lib/helpers.d.ts +1 -2
  35. package/dist/lib/helpers.d.ts.map +1 -1
  36. package/dist/lib/k8s.d.ts +1 -1
  37. package/dist/lib/k8s.d.ts.map +1 -1
  38. package/dist/lib/logger.d.ts +4 -0
  39. package/dist/lib/logger.d.ts.map +1 -1
  40. package/dist/lib/metrics.d.ts.map +1 -1
  41. package/dist/lib/module.d.ts +5 -0
  42. package/dist/lib/module.d.ts.map +1 -1
  43. package/dist/lib/mutate-processor.d.ts.map +1 -1
  44. package/dist/lib/mutate-request.d.ts +1 -60
  45. package/dist/lib/mutate-request.d.ts.map +1 -1
  46. package/dist/lib/types.d.ts +8 -24
  47. package/dist/lib/types.d.ts.map +1 -1
  48. package/dist/lib/validate-request.d.ts.map +1 -1
  49. package/dist/lib/watch-processor.d.ts.map +1 -1
  50. package/dist/lib.js +220 -295
  51. package/dist/lib.js.map +4 -4
  52. package/dist/sdk/cosign.d.ts +18 -0
  53. package/dist/sdk/cosign.d.ts.map +1 -0
  54. package/dist/sdk/heredoc.d.ts +2 -0
  55. package/dist/sdk/heredoc.d.ts.map +1 -0
  56. package/dist/sdk/sdk.d.ts +1 -2
  57. package/dist/sdk/sdk.d.ts.map +1 -1
  58. package/package.json +11 -7
  59. package/src/cli/build.helpers.ts +28 -0
  60. package/src/cli/build.ts +124 -121
  61. package/src/cli/deploy.ts +27 -24
  62. package/src/cli/dev.ts +3 -3
  63. package/src/cli/format.ts +3 -6
  64. package/src/cli/init/index.ts +23 -19
  65. package/src/cli/monitor.ts +34 -36
  66. package/src/lib/assets/deploy.ts +12 -3
  67. package/src/lib/assets/helm.ts +14 -0
  68. package/src/lib/assets/index.ts +12 -8
  69. package/src/lib/assets/rbac.ts +69 -17
  70. package/src/lib/assets/webhooks.ts +1 -1
  71. package/src/lib/assets/yaml.ts +8 -4
  72. package/src/lib/capability.ts +7 -12
  73. package/src/lib/controller/index.ts +3 -3
  74. package/src/lib/controller/store.ts +42 -202
  75. package/src/lib/controller/storeCache.ts +63 -0
  76. package/src/lib/enums.ts +21 -0
  77. package/src/lib/{adjudicators.ts → filter/adjudicators.ts} +39 -28
  78. package/src/lib/{filter.ts → filter/filter.ts} +3 -2
  79. package/src/lib/finalizer.ts +1 -1
  80. package/src/lib/helpers.ts +19 -15
  81. package/src/lib/k8s.ts +2 -2
  82. package/src/lib/logger.ts +41 -0
  83. package/src/lib/metrics.ts +3 -1
  84. package/src/lib/module.ts +5 -0
  85. package/src/lib/mutate-processor.ts +14 -12
  86. package/src/lib/mutate-request.ts +4 -69
  87. package/src/lib/types.ts +9 -28
  88. package/src/lib/validate-processor.ts +1 -1
  89. package/src/lib/validate-request.ts +2 -1
  90. package/src/lib/watch-processor.ts +34 -20
  91. package/src/sdk/cosign.ts +327 -0
  92. package/src/sdk/heredoc.ts +36 -0
  93. package/src/sdk/sdk.ts +1 -2
  94. package/dist/lib/adjudicators.d.ts.map +0 -1
  95. package/dist/lib/filter.d.ts.map +0 -1
@@ -6,15 +6,15 @@ import { K8s } from "kubernetes-fluent-client";
6
6
  import { startsWith } from "ramda";
7
7
 
8
8
  import { Capability } from "../capability";
9
- import { PeprStore } from "../k8s";
10
- import Log from "../logger";
9
+ import { Store } from "../k8s";
10
+ import Log, { redactedPatch, redactedStore } from "../logger";
11
11
  import { DataOp, DataSender, DataStore, Storage } from "../storage";
12
+ import { fillStoreCache, sendUpdatesAndFlushCache } from "./storeCache";
12
13
 
13
- const redactedValue = "**redacted**";
14
14
  const namespace = "pepr-system";
15
15
  export const debounceBackoff = 5000;
16
16
 
17
- export class PeprControllerStore {
17
+ export class StoreController {
18
18
  #name: string;
19
19
  #stores: Record<string, Storage> = {};
20
20
  #sendDebounce: NodeJS.Timeout | undefined;
@@ -23,124 +23,53 @@ export class PeprControllerStore {
23
23
  constructor(capabilities: Capability[], name: string, onReady?: () => void) {
24
24
  this.#onReady = onReady;
25
25
 
26
- // Setup Pepr State bindings
27
26
  this.#name = name;
28
27
 
28
+ const setStorageInstance = (registrationFunction: () => Storage, name: string) => {
29
+ const scheduleStore = registrationFunction();
30
+
31
+ // Bind the store sender to the capability
32
+ scheduleStore.registerSender(this.#send(name));
33
+
34
+ // Store the storage instance
35
+ this.#stores[name] = scheduleStore;
36
+ };
37
+
29
38
  if (name.includes("schedule")) {
30
39
  // Establish the store for each capability
31
40
  for (const { name, registerScheduleStore, hasSchedule } of capabilities) {
32
- // Guard Clause to exit early
33
- if (hasSchedule !== true) {
34
- continue;
41
+ if (hasSchedule === true) {
42
+ // Register the scheduleStore with the capability
43
+ setStorageInstance(registerScheduleStore, name);
35
44
  }
36
- // Register the scheduleStore with the capability
37
- const { scheduleStore } = registerScheduleStore();
38
-
39
- // Bind the store sender to the capability
40
- scheduleStore.registerSender(this.#send(name));
41
-
42
- // Store the storage instance
43
- this.#stores[name] = scheduleStore;
44
45
  }
45
46
  } else {
46
47
  // Establish the store for each capability
47
48
  for (const { name, registerStore } of capabilities) {
48
- // Register the store with the capability
49
- const { store } = registerStore();
50
-
51
- // Bind the store sender to the capability
52
- store.registerSender(this.#send(name));
53
-
54
- // Store the storage instance
55
- this.#stores[name] = store;
49
+ setStorageInstance(registerStore, name);
56
50
  }
57
51
  }
58
52
 
59
- // Add a jitter to the Store creation to avoid collisions
60
53
  setTimeout(
61
54
  () =>
62
- K8s(PeprStore)
55
+ K8s(Store)
63
56
  .InNamespace(namespace)
64
57
  .Get(this.#name)
65
- // If the get succeeds, migrate and setup the watch
66
- .then(async (store: PeprStore) => await this.#migrateAndSetupWatch(store))
67
- // Otherwise, create the resource
58
+ .then(async (store: Store) => await this.#migrateAndSetupWatch(store))
68
59
  .catch(this.#createStoreResource),
69
- Math.random() * 3000,
60
+ Math.random() * 3000, // Add a jitter to the Store creation to avoid collisions
70
61
  );
71
62
  }
72
63
 
73
64
  #setupWatch = () => {
74
- const watcher = K8s(PeprStore, { name: this.#name, namespace }).Watch(this.#receive);
65
+ const watcher = K8s(Store, { name: this.#name, namespace }).Watch(this.#receive);
75
66
  watcher.start().catch(e => Log.error(e, "Error starting Pepr store watch"));
76
67
  };
77
68
 
78
- #migrateAndSetupWatch = async (store: PeprStore) => {
69
+ #migrateAndSetupWatch = async (store: Store) => {
79
70
  Log.debug(redactedStore(store), "Pepr Store migration");
80
71
  const data: DataStore = store.data || {};
81
- const migrateCache: Record<string, Operation> = {};
82
-
83
- // Send the cached updates to the cluster
84
- const flushCache = async () => {
85
- const indexes = Object.keys(migrateCache);
86
- const payload = Object.values(migrateCache);
87
-
88
- // Loop over each key in the cache and delete it to avoid collisions with other sender calls
89
- for (const idx of indexes) {
90
- delete migrateCache[idx];
91
- }
92
-
93
- try {
94
- // Send the patch to the cluster
95
- if (payload.length > 0) {
96
- await K8s(PeprStore, { namespace, name: this.#name }).Patch(payload);
97
- }
98
- } catch (err) {
99
- Log.error(err, "Pepr store update failure");
100
-
101
- if (err.status === 422) {
102
- Object.keys(migrateCache).forEach(key => delete migrateCache[key]);
103
- } else {
104
- // On failure to update, re-add the operations to the cache to be retried
105
- for (const idx of indexes) {
106
- migrateCache[idx] = payload[Number(idx)];
107
- }
108
- }
109
- }
110
- };
111
-
112
- const fillCache = (name: string, op: DataOp, key: string[], val?: string) => {
113
- if (op === "add") {
114
- // adjust the path for the capability
115
- const path = `/data/${name}-v2-${key}`;
116
- const value = val || "";
117
- const cacheIdx = [op, path, value].join(":");
118
-
119
- // Add the operation to the cache
120
- migrateCache[cacheIdx] = { op, path, value };
121
-
122
- return;
123
- }
124
-
125
- if (op === "remove") {
126
- if (key.length < 1) {
127
- throw new Error(`Key is required for REMOVE operation`);
128
- }
129
-
130
- for (const k of key) {
131
- const path = `/data/${name}-${k}`;
132
- const cacheIdx = [op, path].join(":");
133
-
134
- // Add the operation to the cache
135
- migrateCache[cacheIdx] = { op, path };
136
- }
137
-
138
- return;
139
- }
140
-
141
- // If we get here, the operation is not supported
142
- throw new Error(`Unsupported operation: ${op}`);
143
- };
72
+ let storeCache: Record<string, Operation> = {};
144
73
 
145
74
  for (const name of Object.keys(this.#stores)) {
146
75
  // Get the prefix offset for the keys
@@ -151,16 +80,23 @@ export class PeprControllerStore {
151
80
  // Match on the capability name as a prefix for non v2 keys
152
81
  if (startsWith(name, key) && !startsWith(`${name}-v2`, key)) {
153
82
  // populate migrate cache
154
- fillCache(name, "remove", [key.slice(offset)], data[key]);
155
- fillCache(name, "add", [key.slice(offset)], data[key]);
83
+ storeCache = fillStoreCache(storeCache, name, "remove", {
84
+ key: [key.slice(offset)],
85
+ value: data[key],
86
+ });
87
+ storeCache = fillStoreCache(storeCache, name, "add", {
88
+ key: [key.slice(offset)],
89
+ value: data[key],
90
+ version: "v2",
91
+ });
156
92
  }
157
93
  }
158
94
  }
159
- await flushCache();
95
+ storeCache = await sendUpdatesAndFlushCache(storeCache, namespace, this.#name);
160
96
  this.#setupWatch();
161
97
  };
162
98
 
163
- #receive = (store: PeprStore) => {
99
+ #receive = (store: Store) => {
164
100
  Log.debug(redactedStore(store), "Pepr Store update");
165
101
 
166
102
  // Wrap the update in a debounced function
@@ -202,81 +138,18 @@ export class PeprControllerStore {
202
138
  };
203
139
 
204
140
  #send = (capabilityName: string) => {
205
- const sendCache: Record<string, Operation> = {};
206
-
207
- // Load the sendCache with patch operations
208
- const fillCache = (op: DataOp, key: string[], val?: string) => {
209
- if (op === "add") {
210
- // adjust the path for the capability
211
- const path = `/data/${capabilityName}-${key}`;
212
- const value = val || "";
213
- const cacheIdx = [op, path, value].join(":");
214
-
215
- // Add the operation to the cache
216
- sendCache[cacheIdx] = { op, path, value };
217
-
218
- return;
219
- }
220
-
221
- if (op === "remove") {
222
- if (key.length < 1) {
223
- throw new Error(`Key is required for REMOVE operation`);
224
- }
225
-
226
- for (const k of key) {
227
- const path = `/data/${capabilityName}-${k}`;
228
- const cacheIdx = [op, path].join(":");
229
-
230
- // Add the operation to the cache
231
- sendCache[cacheIdx] = { op, path };
232
- }
233
-
234
- return;
235
- }
236
-
237
- // If we get here, the operation is not supported
238
- throw new Error(`Unsupported operation: ${op}`);
239
- };
240
-
241
- // Send the cached updates to the cluster
242
- const flushCache = async () => {
243
- const indexes = Object.keys(sendCache);
244
- const payload = Object.values(sendCache);
245
-
246
- // Loop over each key in the cache and delete it to avoid collisions with other sender calls
247
- for (const idx of indexes) {
248
- delete sendCache[idx];
249
- }
250
-
251
- try {
252
- // Send the patch to the cluster
253
- if (payload.length > 0) {
254
- await K8s(PeprStore, { namespace, name: this.#name }).Patch(payload);
255
- }
256
- } catch (err) {
257
- Log.error(err, "Pepr store update failure");
258
-
259
- if (err.status === 422) {
260
- Object.keys(sendCache).forEach(key => delete sendCache[key]);
261
- } else {
262
- // On failure to update, re-add the operations to the cache to be retried
263
- for (const idx of indexes) {
264
- sendCache[idx] = payload[Number(idx)];
265
- }
266
- }
267
- }
268
- };
141
+ let storeCache: Record<string, Operation> = {};
269
142
 
270
143
  // Create a sender function for the capability to add/remove data from the store
271
- const sender: DataSender = async (op: DataOp, key: string[], val?: string) => {
272
- fillCache(op, key, val);
144
+ const sender: DataSender = async (op: DataOp, key: string[], value?: string) => {
145
+ storeCache = fillStoreCache(storeCache, capabilityName, op, { key, value });
273
146
  };
274
147
 
275
148
  // Send any cached updates every debounceBackoff milliseconds
276
149
  setInterval(() => {
277
- if (Object.keys(sendCache).length > 0) {
278
- Log.debug(redactedPatch(sendCache), "Sending updates to Pepr store");
279
- void flushCache();
150
+ if (Object.keys(storeCache).length > 0) {
151
+ Log.debug(redactedPatch(storeCache), "Sending updates to Pepr store");
152
+ void sendUpdatesAndFlushCache(storeCache, namespace, this.#name);
280
153
  }
281
154
  }, debounceBackoff);
282
155
 
@@ -288,7 +161,7 @@ export class PeprControllerStore {
288
161
  Log.debug(e);
289
162
 
290
163
  try {
291
- await K8s(PeprStore).Apply({
164
+ await K8s(Store).Apply({
292
165
  metadata: {
293
166
  name: this.#name,
294
167
  namespace,
@@ -306,36 +179,3 @@ export class PeprControllerStore {
306
179
  }
307
180
  };
308
181
  }
309
-
310
- export function redactedStore(store: PeprStore): PeprStore {
311
- const redacted = process.env.PEPR_STORE_REDACT_VALUES === "true";
312
- return {
313
- ...store,
314
- data: Object.keys(store.data).reduce((acc: Record<string, string>, key: string) => {
315
- acc[key] = redacted ? redactedValue : store.data[key];
316
- return acc;
317
- }, {}),
318
- };
319
- }
320
-
321
- export function redactedPatch(patch: Record<string, Operation> = {}): Record<string, Operation> {
322
- const redacted = process.env.PEPR_STORE_REDACT_VALUES === "true";
323
-
324
- if (!redacted) {
325
- return patch;
326
- }
327
-
328
- const redactedCache: Record<string, Operation> = {};
329
-
330
- Object.keys(patch).forEach(key => {
331
- const operation = patch[key];
332
- const redactedKey = key.includes(":") ? key.substring(0, key.lastIndexOf(":")) + ":**redacted**" : key;
333
- const redactedOperation: Operation = {
334
- ...operation,
335
- ...("value" in operation ? { value: "**redacted**" } : {}),
336
- };
337
- redactedCache[redactedKey] = redactedOperation;
338
- });
339
-
340
- return redactedCache;
341
- }
@@ -0,0 +1,63 @@
1
+ import { DataOp } from "../storage";
2
+ import Log from "../logger";
3
+ import { K8s } from "kubernetes-fluent-client";
4
+ import { Store } from "../k8s";
5
+ import { StatusCodes } from "http-status-codes";
6
+ import { Operation } from "fast-json-patch";
7
+
8
+ export const sendUpdatesAndFlushCache = async (cache: Record<string, Operation>, namespace: string, name: string) => {
9
+ const indexes = Object.keys(cache);
10
+ const payload = Object.values(cache);
11
+
12
+ try {
13
+ if (payload.length > 0) {
14
+ await K8s(Store, { namespace, name }).Patch(payload); // Send patch to cluster
15
+ Object.keys(cache).forEach(key => delete cache[key]);
16
+ }
17
+ } catch (err) {
18
+ Log.error(err, "Pepr store update failure");
19
+
20
+ if (err.status === StatusCodes.UNPROCESSABLE_ENTITY) {
21
+ Object.keys(cache).forEach(key => delete cache[key]);
22
+ } else {
23
+ indexes.forEach(index => {
24
+ cache[index] = payload[Number(index)]; // On failure to update, re-add the operations to the cache to be retried
25
+ });
26
+ }
27
+ }
28
+ return cache;
29
+ };
30
+
31
+ type CacheItem = {
32
+ key: string[];
33
+ value?: string;
34
+ version?: string;
35
+ };
36
+
37
+ export const fillStoreCache = (
38
+ cache: Record<string, Operation>,
39
+ capabilityName: string,
40
+ op: DataOp,
41
+ cacheItem: CacheItem,
42
+ ): Record<string, Operation> => {
43
+ const path = [`/data/${capabilityName}`, cacheItem.version, cacheItem.key] // adjust the path, see ADR-0008
44
+ .filter(str => str !== "" && str !== undefined)
45
+ .join("-");
46
+ if (op === "add") {
47
+ const value = cacheItem.value || "";
48
+ const cacheIdx = [op, path, value].join(":");
49
+
50
+ // Add the operation to the cache
51
+ cache[cacheIdx] = { op, path, value };
52
+ } else if (op === "remove") {
53
+ if (cacheItem.key.length < 1) {
54
+ throw new Error(`Key is required for REMOVE operation`);
55
+ }
56
+ const cacheIndex = [op, path].join(":");
57
+ // Add the operation to the cache
58
+ cache[cacheIndex] = { op, path };
59
+ } else {
60
+ throw new Error(`Unsupported operation: ${op}`);
61
+ }
62
+ return cache;
63
+ };
@@ -0,0 +1,21 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+ // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
+
4
+ // Operation type for mutation operations
5
+ export enum Operation {
6
+ CREATE = "CREATE",
7
+ UPDATE = "UPDATE",
8
+ DELETE = "DELETE",
9
+ CONNECT = "CONNECT",
10
+ }
11
+
12
+ /**
13
+ * The type of Kubernetes mutating webhook event that the action is registered for.
14
+ */
15
+ export enum Event {
16
+ Create = "CREATE",
17
+ Update = "UPDATE",
18
+ Delete = "DELETE",
19
+ CreateOrUpdate = "CREATEORUPDATE",
20
+ Any = "*",
21
+ }
@@ -1,7 +1,7 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
3
 
4
- import { Event, Operation } from "./types";
4
+ import { Event, Operation } from "../enums";
5
5
  import {
6
6
  __,
7
7
  allPass,
@@ -22,7 +22,7 @@ import {
22
22
  /*
23
23
  Naming scheme:
24
24
  - AdmissionRequest - "declares" / "neglects"
25
- - KubernetesObject - "carries" / "missing"
25
+ - KuberneteskubernetesObjectect - "carries" / "missing"
26
26
  - Binding - "defines" / "ignores"
27
27
  */
28
28
 
@@ -36,27 +36,33 @@ export const declaredKind = pipe(request => request?.kind?.kind, defaultTo(""));
36
36
  export const declaredUid = pipe(request => request?.uid, defaultTo(""));
37
37
 
38
38
  /*
39
- KubernetesObject collectors
39
+ KuberneteskubernetesObjectect collectors
40
40
  */
41
- export const carriesDeletionTimestamp = pipe(obj => !!obj.metadata?.deletionTimestamp, defaultTo(false));
41
+ export const carriesDeletionTimestamp = pipe(
42
+ kubernetesObject => !!kubernetesObject.metadata?.deletionTimestamp,
43
+ defaultTo(false),
44
+ );
42
45
  export const missingDeletionTimestamp = complement(carriesDeletionTimestamp);
43
46
 
44
- export const carriedName = pipe(obj => obj?.metadata?.name, defaultTo(""));
47
+ export const carriedKind = pipe(kubernetesObject => kubernetesObject?.metadata?.kind, defaultTo("not set"));
48
+ export const carriedVersion = pipe(kubernetesObject => kubernetesObject?.metadata?.version, defaultTo("not set"));
49
+ export const carriedName = pipe(kubernetesObject => kubernetesObject?.metadata?.name, defaultTo(""));
45
50
  export const carriesName = pipe(carriedName, equals(""), not);
46
51
  export const missingName = complement(carriesName);
47
52
 
48
- export const carriedNamespace = pipe(obj => obj?.metadata?.namespace, defaultTo(""));
53
+ export const carriedNamespace = pipe(kubernetesObject => kubernetesObject?.metadata?.namespace, defaultTo(""));
49
54
  export const carriesNamespace = pipe(carriedNamespace, equals(""), not);
50
55
 
51
- export const carriedAnnotations = pipe(obj => obj?.metadata?.annotations, defaultTo({}));
56
+ export const carriedAnnotations = pipe(kubernetesObject => kubernetesObject?.metadata?.annotations, defaultTo({}));
52
57
  export const carriesAnnotations = pipe(carriedAnnotations, equals({}), not);
53
58
 
54
- export const carriedLabels = pipe(obj => obj?.metadata?.labels, defaultTo({}));
59
+ export const carriedLabels = pipe(kubernetesObject => kubernetesObject?.metadata?.labels, defaultTo({}));
55
60
  export const carriesLabels = pipe(carriedLabels, equals({}), not);
56
61
 
57
62
  /*
58
63
  Binding collectors
59
64
  */
65
+
60
66
  export const definesDeletionTimestamp = pipe(binding => binding?.filters?.deletionTimestamp, defaultTo(false));
61
67
  export const ignoresDeletionTimestamp = complement(definesDeletionTimestamp);
62
68
 
@@ -112,7 +118,7 @@ export const definedCallback = pipe(binding => {
112
118
  null
113
119
  );
114
120
  });
115
- export const definedCallbackName = pipe(definedCallback, defaultTo({ name: "" }), cb => cb.name);
121
+ export const definedCallbackName = pipe(definedCallback, defaultTo({ name: "" }), callback => callback.name);
116
122
 
117
123
  /*
118
124
  post-collection comparitors
@@ -124,32 +130,32 @@ export const mismatchedDeletionTimestamp = allPass([
124
130
 
125
131
  export const mismatchedName = allPass([
126
132
  pipe(nthArg(0), definesName),
127
- pipe((bnd, obj) => definedName(bnd) !== carriedName(obj)),
133
+ pipe((binding, kubernetesObject) => definedName(binding) !== carriedName(kubernetesObject)),
128
134
  ]);
129
135
 
130
136
  export const mismatchedNameRegex = allPass([
131
137
  pipe(nthArg(0), definesNameRegex),
132
- pipe((bnd, obj) => new RegExp(definedNameRegex(bnd)).test(carriedName(obj)), not),
138
+ pipe((binding, kubernetesObject) => new RegExp(definedNameRegex(binding)).test(carriedName(kubernetesObject)), not),
133
139
  ]);
134
140
 
135
141
  export const bindsToKind = curry(
136
- allPass([pipe(nthArg(0), definedKind, equals(""), not), pipe((bnd, knd) => definedKind(bnd) === knd)]),
142
+ allPass([pipe(nthArg(0), definedKind, equals(""), not), pipe((binding, kind) => definedKind(binding) === kind)]),
137
143
  );
138
144
  export const bindsToNamespace = curry(pipe(bindsToKind(__, "Namespace")));
139
145
  export const misboundNamespace = allPass([bindsToNamespace, definesNamespaces]);
140
146
 
141
147
  export const mismatchedNamespace = allPass([
142
148
  pipe(nthArg(0), definesNamespaces),
143
- pipe((bnd, obj) => definedNamespaces(bnd).includes(carriedNamespace(obj)), not),
149
+ pipe((binding, kubernetesObject) => definedNamespaces(binding).includes(carriedNamespace(kubernetesObject)), not),
144
150
  ]);
145
151
 
146
152
  export const mismatchedNamespaceRegex = allPass([
147
153
  pipe(nthArg(0), definesNamespaceRegexes),
148
- pipe((bnd, obj) =>
154
+ pipe((binding, kubernetesObject) =>
149
155
  pipe(
150
- any((rex: string) => new RegExp(rex).test(carriedNamespace(obj))),
156
+ any((regEx: string) => new RegExp(regEx).test(carriedNamespace(kubernetesObject))),
151
157
  not,
152
- )(definedNamespaceRegexes(bnd)),
158
+ )(definedNamespaceRegexes(binding)),
153
159
  ),
154
160
  ]);
155
161
 
@@ -158,18 +164,18 @@ export const metasMismatch = pipe(
158
164
  const result = { defined, carried, unalike: {} };
159
165
 
160
166
  result.unalike = Object.entries(result.defined)
161
- .map(([key, val]) => {
167
+ .map(([key, value]) => {
162
168
  const keyMissing = !Object.hasOwn(result.carried, key);
163
- const noValue = !val;
169
+ const noValue = !value;
164
170
  const valMissing = !result.carried[key];
165
171
  const valDiffers = result.carried[key] !== result.defined[key];
166
172
 
167
173
  // prettier-ignore
168
174
  return (
169
- keyMissing ? { [key]: val } :
175
+ keyMissing ? { [key]: value } :
170
176
  noValue ? {} :
171
- valMissing ? { [key]: val } :
172
- valDiffers ? { [key]: val } :
177
+ valMissing ? { [key]: value } :
178
+ valDiffers ? { [key]: value } :
173
179
  {}
174
180
  )
175
181
  })
@@ -182,38 +188,43 @@ export const metasMismatch = pipe(
182
188
 
183
189
  export const mismatchedAnnotations = allPass([
184
190
  pipe(nthArg(0), definesAnnotations),
185
- pipe((bnd, obj) => metasMismatch(definedAnnotations(bnd), carriedAnnotations(obj))),
191
+ pipe((binding, kubernetesObject) => metasMismatch(definedAnnotations(binding), carriedAnnotations(kubernetesObject))),
186
192
  ]);
187
193
 
188
194
  export const mismatchedLabels = allPass([
189
195
  pipe(nthArg(0), definesLabels),
190
- pipe((bnd, obj) => metasMismatch(definedLabels(bnd), carriedLabels(obj))),
196
+ pipe((binding, kubernetesObject) => metasMismatch(definedLabels(binding), carriedLabels(kubernetesObject))),
191
197
  ]);
192
198
 
193
199
  export const uncarryableNamespace = allPass([
194
200
  pipe(nthArg(0), length, gt(__, 0)),
195
201
  pipe(nthArg(1), carriesNamespace),
196
- pipe((nss, obj) => nss.includes(carriedNamespace(obj)), not),
202
+ pipe((namespaceSelector, kubernetesObject) => namespaceSelector.includes(carriedNamespace(kubernetesObject)), not),
197
203
  ]);
198
204
 
199
205
  export const carriesIgnoredNamespace = allPass([
200
206
  pipe(nthArg(0), length, gt(__, 0)),
201
207
  pipe(nthArg(1), carriesNamespace),
202
- pipe((nss, obj) => nss.includes(carriedNamespace(obj))),
208
+ pipe((namespaceSelector, kubernetesObject) => namespaceSelector.includes(carriedNamespace(kubernetesObject))),
203
209
  ]);
204
210
 
205
211
  export const unbindableNamespaces = allPass([
206
212
  pipe(nthArg(0), length, gt(__, 0)),
207
213
  pipe(nthArg(1), definesNamespaces),
208
- pipe((nss, bnd) => difference(definedNamespaces(bnd), nss), length, equals(0), not),
214
+ pipe(
215
+ (namespaceSelector, binding) => difference(definedNamespaces(binding), namespaceSelector),
216
+ length,
217
+ equals(0),
218
+ not,
219
+ ),
209
220
  ]);
210
221
 
211
222
  export const misboundDeleteWithDeletionTimestamp = allPass([definesDelete, definesDeletionTimestamp]);
212
223
 
213
224
  export const operationMatchesEvent = anyPass([
214
225
  pipe(nthArg(1), equals(Event.Any)),
215
- pipe((op, evt) => op === evt),
216
- pipe((op, evt) => (op ? evt.includes(op) : false)),
226
+ pipe((operation, event) => operation === event),
227
+ pipe((operation, event) => (operation ? event.includes(operation) : false)),
217
228
  ]);
218
229
 
219
230
  export const mismatchedEvent = pipe(
@@ -1,7 +1,8 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
3
 
4
- import { AdmissionRequest, Binding, Operation } from "./types";
4
+ import { AdmissionRequest, Binding } from "../types";
5
+ import { Operation } from "../enums";
5
6
  import {
6
7
  carriesIgnoredNamespace,
7
8
  carriedName,
@@ -56,7 +57,7 @@ export function shouldSkipRequest(
56
57
 
57
58
  // prettier-ignore
58
59
  return (
59
- misboundDeleteWithDeletionTimestamp(binding) ?
60
+ misboundDeleteWithDeletionTimestamp(binding) ?
60
61
  `${prefix} Cannot use deletionTimestamp filter on a DELETE operation.` :
61
62
 
62
63
  mismatchedDeletionTimestamp(binding, obj) ?
@@ -4,7 +4,7 @@
4
4
  import { K8s, KubernetesObject, RegisterKind } from "kubernetes-fluent-client";
5
5
  import Log from "./logger";
6
6
  import { Binding, DeepPartial } from "./types";
7
- import { Operation } from "./types";
7
+ import { Operation } from "./enums";
8
8
  import { PeprMutateRequest } from "./mutate-request";
9
9
 
10
10
  export function addFinalizer<K extends KubernetesObject>(request: PeprMutateRequest<K>) {