pepr 0.40.1 → 0.42.1

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/README.md +11 -5
  2. package/dist/cli/build.d.ts +1 -0
  3. package/dist/cli/build.d.ts.map +1 -1
  4. package/dist/cli/build.helpers.d.ts +66 -0
  5. package/dist/cli/build.helpers.d.ts.map +1 -1
  6. package/dist/cli/deploy.d.ts.map +1 -1
  7. package/dist/cli/init/templates.d.ts +2 -2
  8. package/dist/cli/monitor.d.ts +23 -0
  9. package/dist/cli/monitor.d.ts.map +1 -1
  10. package/dist/cli.js +536 -429
  11. package/dist/controller.js +52 -27
  12. package/dist/lib/assets/destroy.d.ts.map +1 -1
  13. package/dist/lib/assets/helm.d.ts +1 -1
  14. package/dist/lib/assets/helm.d.ts.map +1 -1
  15. package/dist/lib/assets/index.d.ts.map +1 -1
  16. package/dist/lib/assets/pods.d.ts +5 -19
  17. package/dist/lib/assets/pods.d.ts.map +1 -1
  18. package/dist/lib/assets/webhooks.d.ts.map +1 -1
  19. package/dist/lib/assets/yaml.d.ts.map +1 -1
  20. package/dist/lib/capability.d.ts.map +1 -1
  21. package/dist/lib/controller/index.d.ts.map +1 -1
  22. package/dist/lib/controller/index.util.d.ts +10 -0
  23. package/dist/lib/controller/index.util.d.ts.map +1 -0
  24. package/dist/lib/controller/store.d.ts +0 -1
  25. package/dist/lib/controller/store.d.ts.map +1 -1
  26. package/dist/lib/controller/storeCache.d.ts +1 -0
  27. package/dist/lib/controller/storeCache.d.ts.map +1 -1
  28. package/dist/lib/deploymentChecks.d.ts +3 -0
  29. package/dist/lib/deploymentChecks.d.ts.map +1 -0
  30. package/dist/lib/enums.d.ts +5 -5
  31. package/dist/lib/enums.d.ts.map +1 -1
  32. package/dist/lib/filesystemService.d.ts +2 -0
  33. package/dist/lib/filesystemService.d.ts.map +1 -0
  34. package/dist/lib/filter/adjudicators/adjudicators.d.ts +73 -0
  35. package/dist/lib/filter/adjudicators/adjudicators.d.ts.map +1 -0
  36. package/dist/lib/filter/adjudicators/defaultTestObjects.d.ts +7 -0
  37. package/dist/lib/filter/adjudicators/defaultTestObjects.d.ts.map +1 -0
  38. package/dist/lib/helpers.d.ts +1 -4
  39. package/dist/lib/helpers.d.ts.map +1 -1
  40. package/dist/lib/mutate-request.d.ts +2 -2
  41. package/dist/lib/mutate-request.d.ts.map +1 -1
  42. package/dist/lib/queue.d.ts.map +1 -1
  43. package/dist/lib/schedule.d.ts.map +1 -1
  44. package/dist/lib/storage.d.ts +5 -5
  45. package/dist/lib/storage.d.ts.map +1 -1
  46. package/dist/lib/{logger.d.ts → telemetry/logger.d.ts} +1 -1
  47. package/dist/lib/telemetry/logger.d.ts.map +1 -0
  48. package/dist/lib/{metrics.d.ts → telemetry/metrics.d.ts} +3 -1
  49. package/dist/lib/telemetry/metrics.d.ts.map +1 -0
  50. package/dist/lib/types.d.ts +10 -9
  51. package/dist/lib/types.d.ts.map +1 -1
  52. package/dist/lib/utils.d.ts.map +1 -1
  53. package/dist/lib/validate-processor.d.ts +4 -1
  54. package/dist/lib/validate-processor.d.ts.map +1 -1
  55. package/dist/lib/watch-processor.d.ts.map +1 -1
  56. package/dist/lib.d.ts +1 -1
  57. package/dist/lib.d.ts.map +1 -1
  58. package/dist/lib.js +283 -231
  59. package/dist/lib.js.map +4 -4
  60. package/dist/sdk/sdk.d.ts +3 -4
  61. package/dist/sdk/sdk.d.ts.map +1 -1
  62. package/package.json +5 -5
  63. package/src/cli/build.helpers.ts +180 -0
  64. package/src/cli/build.ts +85 -132
  65. package/src/cli/deploy.ts +2 -1
  66. package/src/cli/init/templates.ts +1 -1
  67. package/src/cli/monitor.ts +108 -65
  68. package/src/lib/assets/deploy.ts +7 -7
  69. package/src/lib/assets/destroy.ts +2 -2
  70. package/src/lib/assets/helm.ts +6 -6
  71. package/src/lib/assets/index.ts +110 -89
  72. package/src/lib/assets/pods.ts +10 -5
  73. package/src/lib/assets/webhooks.ts +3 -3
  74. package/src/lib/assets/yaml.ts +12 -9
  75. package/src/lib/capability.ts +29 -19
  76. package/src/lib/controller/index.ts +41 -69
  77. package/src/lib/controller/index.util.ts +47 -0
  78. package/src/lib/controller/store.ts +24 -11
  79. package/src/lib/controller/storeCache.ts +11 -2
  80. package/src/lib/deploymentChecks.ts +43 -0
  81. package/src/lib/enums.ts +5 -5
  82. package/src/lib/filesystemService.ts +16 -0
  83. package/src/lib/filter/{adjudicators.ts → adjudicators/adjudicators.ts} +67 -35
  84. package/src/lib/filter/adjudicators/defaultTestObjects.ts +46 -0
  85. package/src/lib/filter/filter.ts +1 -1
  86. package/src/lib/finalizer.ts +1 -1
  87. package/src/lib/helpers.ts +31 -88
  88. package/src/lib/mutate-processor.ts +1 -1
  89. package/src/lib/mutate-request.ts +11 -11
  90. package/src/lib/queue.ts +13 -5
  91. package/src/lib/schedule.ts +8 -8
  92. package/src/lib/storage.ts +48 -39
  93. package/src/lib/{logger.ts → telemetry/logger.ts} +1 -1
  94. package/src/lib/{metrics.ts → telemetry/metrics.ts} +18 -17
  95. package/src/lib/types.ts +12 -9
  96. package/src/lib/utils.ts +6 -6
  97. package/src/lib/validate-processor.ts +48 -40
  98. package/src/lib/watch-processor.ts +19 -15
  99. package/src/lib.ts +1 -1
  100. package/src/runtime/controller.ts +1 -1
  101. package/src/sdk/cosign.ts +4 -4
  102. package/src/sdk/sdk.ts +6 -9
  103. package/src/templates/capabilities/hello-pepr.ts +19 -9
  104. package/dist/lib/filter/adjudicators.d.ts +0 -69
  105. package/dist/lib/filter/adjudicators.d.ts.map +0 -1
  106. package/dist/lib/logger.d.ts.map +0 -1
  107. package/dist/lib/metrics.d.ts.map +0 -1
@@ -1,8 +1,8 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
3
 
4
- import { Event, Operation } from "../enums";
5
- import { AdmissionRequest } from "../../lib/types";
4
+ import { Event, Operation } from "../../enums";
5
+ import { AdmissionRequest, Binding } from "../../types";
6
6
  import {
7
7
  __,
8
8
  allPass,
@@ -58,33 +58,60 @@ export const carriesDeletionTimestamp = pipe(
58
58
  );
59
59
  export const missingDeletionTimestamp = complement(carriesDeletionTimestamp);
60
60
 
61
- export const carriedKind = pipe(kubernetesObject => kubernetesObject?.metadata?.kind, defaultTo("not set"));
62
- export const carriedVersion = pipe(kubernetesObject => kubernetesObject?.metadata?.version, defaultTo("not set"));
63
- export const carriedName = pipe(kubernetesObject => kubernetesObject?.metadata?.name, defaultTo(""));
61
+ export const carriedKind = pipe(
62
+ (kubernetesObject: KubernetesObject): string | undefined => kubernetesObject?.kind,
63
+ defaultTo("not set"),
64
+ );
65
+ export const carriedVersion = pipe(
66
+ (kubernetesObject: KubernetesObject): string | undefined => kubernetesObject?.metadata?.resourceVersion,
67
+ defaultTo("not set"),
68
+ );
69
+ export const carriedName = pipe(
70
+ (kubernetesObject: KubernetesObject): string | undefined => kubernetesObject?.metadata?.name,
71
+ defaultTo(""),
72
+ );
64
73
  export const carriesName = pipe(carriedName, equals(""), not);
65
74
  export const missingName = complement(carriesName);
66
75
 
67
- export const carriedNamespace = pipe(kubernetesObject => kubernetesObject?.metadata?.namespace, defaultTo(""));
76
+ export const carriedNamespace = pipe(
77
+ (kubernetesObject: KubernetesObject): string | undefined => kubernetesObject?.metadata?.namespace,
78
+ defaultTo(""),
79
+ );
68
80
  export const carriesNamespace = pipe(carriedNamespace, equals(""), not);
69
81
 
70
- export const carriedAnnotations = pipe(kubernetesObject => kubernetesObject?.metadata?.annotations, defaultTo({}));
82
+ export const carriedAnnotations = pipe(
83
+ (kubernetesObject: KubernetesObject): { [key: string]: string } | undefined =>
84
+ kubernetesObject?.metadata?.annotations,
85
+ defaultTo({}),
86
+ );
71
87
  export const carriesAnnotations = pipe(carriedAnnotations, equals({}), not);
72
88
 
73
- export const carriedLabels = pipe(kubernetesObject => kubernetesObject?.metadata?.labels, defaultTo({}));
89
+ export const carriedLabels = pipe(
90
+ (kubernetesObject: KubernetesObject): { [key: string]: string } | undefined => kubernetesObject?.metadata?.labels,
91
+ defaultTo({}),
92
+ );
74
93
  export const carriesLabels = pipe(carriedLabels, equals({}), not);
75
94
 
76
95
  /*
77
96
  Binding collectors
78
97
  */
79
98
 
80
- export const definesDeletionTimestamp = pipe(binding => binding?.filters?.deletionTimestamp, defaultTo(false));
99
+ export const definesDeletionTimestamp = pipe(
100
+ (binding: Binding): boolean => binding?.filters?.deletionTimestamp ?? false,
101
+ defaultTo(false),
102
+ );
81
103
  export const ignoresDeletionTimestamp = complement(definesDeletionTimestamp);
82
104
 
83
- export const definedName = pipe(binding => binding?.filters?.name, defaultTo(""));
105
+ export const definedName = pipe((binding: Binding): string => {
106
+ return binding.filters.name;
107
+ }, defaultTo(""));
84
108
  export const definesName = pipe(definedName, equals(""), not);
85
109
  export const ignoresName = complement(definesName);
86
110
 
87
- export const definedNameRegex = pipe(binding => binding?.filters?.regexName, defaultTo(""));
111
+ export const definedNameRegex = pipe(
112
+ (binding: Partial<Binding>): string | undefined => binding.filters?.regexName,
113
+ defaultTo(""),
114
+ );
88
115
  export const definesNameRegex = pipe(definedNameRegex, equals(""), not);
89
116
 
90
117
  export const definedNamespaces = pipe(binding => binding?.filters?.namespaces, defaultTo([]));
@@ -93,45 +120,49 @@ export const definesNamespaces = pipe(definedNamespaces, equals([]), not);
93
120
  export const definedNamespaceRegexes = pipe(binding => binding?.filters?.regexNamespaces, defaultTo([]));
94
121
  export const definesNamespaceRegexes = pipe(definedNamespaceRegexes, equals([]), not);
95
122
 
96
- export const definedAnnotations = pipe(binding => binding?.filters?.annotations, defaultTo({}));
123
+ export const definedAnnotations = pipe((binding: Partial<Binding>) => binding?.filters?.annotations, defaultTo({}));
97
124
  export const definesAnnotations = pipe(definedAnnotations, equals({}), not);
98
125
 
99
- export const definedLabels = pipe(binding => binding?.filters?.labels, defaultTo({}));
126
+ export const definedLabels = pipe((binding: Partial<Binding>) => binding?.filters?.labels, defaultTo({}));
100
127
  export const definesLabels = pipe(definedLabels, equals({}), not);
101
128
 
102
- export const definedEvent = pipe(binding => binding?.event, defaultTo(""));
103
- export const definesDelete = pipe(definedEvent, equals(Operation.DELETE));
129
+ export const definedEvent = (binding: Binding): Event => {
130
+ return binding.event;
131
+ };
104
132
 
105
- export const definedGroup = pipe(binding => binding?.kind?.group, defaultTo(""));
133
+ export const definesDelete = pipe(definedEvent, equals(Event.DELETE));
134
+
135
+ export const definedGroup = pipe((binding): string => binding?.kind?.group, defaultTo(""));
106
136
  export const definesGroup = pipe(definedGroup, equals(""), not);
107
137
 
108
- export const definedVersion = pipe(binding => binding?.kind?.version, defaultTo(""));
138
+ export const definedVersion = pipe(
139
+ (binding: Partial<Binding>): string | undefined => binding?.kind?.version,
140
+ defaultTo(""),
141
+ );
109
142
  export const definesVersion = pipe(definedVersion, equals(""), not);
110
143
 
111
- export const definedKind = pipe(binding => binding?.kind?.kind, defaultTo(""));
144
+ export const definedKind = pipe((binding): string => binding?.kind?.kind, defaultTo(""));
112
145
  export const definesKind = pipe(definedKind, equals(""), not);
113
146
 
114
- export const definedCategory = pipe(binding => {
147
+ export const definedCategory = (binding: Partial<Binding>) => {
148
+ // Ordering matters, finalize is a "watch"
115
149
  // prettier-ignore
116
- return (
117
- binding.isFinalize ? "Finalize" :
150
+ return binding.isFinalize ? "Finalize" :
118
151
  binding.isWatch ? "Watch" :
119
152
  binding.isMutate ? "Mutate" :
120
153
  binding.isValidate ? "Validate" :
121
- ""
122
- );
123
- });
154
+ "";
155
+ };
124
156
 
125
- export const definedCallback = pipe(binding => {
157
+ export const definedCallback = (binding: Partial<Binding>) => {
158
+ // Ordering matters, finalize is a "watch"
126
159
  // prettier-ignore
127
- return (
128
- binding.isFinalize ? binding.finalizeCallback :
160
+ return binding.isFinalize ? binding.finalizeCallback :
129
161
  binding.isWatch ? binding.watchCallback :
130
162
  binding.isMutate ? binding.mutateCallback :
131
- binding.isValidate ? binding.validateCallback:
132
- null
133
- );
134
- });
163
+ binding.isValidate ? binding.validateCallback :
164
+ null;
165
+ };
135
166
  export const definedCallbackName = pipe(definedCallback, defaultTo({ name: "" }), callback => callback.name);
136
167
 
137
168
  /*
@@ -245,13 +276,14 @@ export const unbindableNamespaces = allPass([
245
276
  export const misboundDeleteWithDeletionTimestamp = allPass([definesDelete, definesDeletionTimestamp]);
246
277
 
247
278
  export const operationMatchesEvent = anyPass([
248
- pipe(nthArg(1), equals(Event.Any)),
249
- pipe((operation, event) => operation === event),
250
- pipe((operation, event) => (operation ? event.includes(operation) : false)),
279
+ pipe(nthArg(1), equals(Event.ANY)),
280
+ pipe((operation: Operation, event: Event): boolean => operation.valueOf() === event.valueOf()),
281
+ pipe((operation: Operation, event: Event): boolean => (operation ? event.includes(operation) : false)),
251
282
  ]);
252
283
 
253
284
  export const mismatchedEvent = pipe(
254
- (binding, request) => operationMatchesEvent(declaredOperation(request), definedEvent(binding)),
285
+ (binding: Binding, request: AdmissionRequest): boolean =>
286
+ operationMatchesEvent(declaredOperation(request), definedEvent(binding)),
255
287
  not,
256
288
  );
257
289
 
@@ -0,0 +1,46 @@
1
+ import { GroupVersionKind, kind, KubernetesObject } from "kubernetes-fluent-client";
2
+ import { Event, Operation } from "../../enums";
3
+ import { AdmissionRequest, Binding, Filters } from "../../types";
4
+
5
+ export const defaultFilters: Filters = {
6
+ annotations: {},
7
+ deletionTimestamp: false,
8
+ labels: {},
9
+ name: "",
10
+ namespaces: [],
11
+ regexName: "^default$",
12
+ regexNamespaces: [] as string[],
13
+ };
14
+
15
+ const defaultGroupVersionKind: GroupVersionKind = {
16
+ kind: "some-kind",
17
+ group: "some-group",
18
+ };
19
+
20
+ export const defaultBinding: Binding = {
21
+ event: Event.ANY,
22
+ filters: defaultFilters,
23
+ kind: defaultGroupVersionKind,
24
+ model: kind.Pod,
25
+ isFinalize: false,
26
+ isMutate: false,
27
+ isQueue: false,
28
+ isValidate: false,
29
+ isWatch: false,
30
+ };
31
+
32
+ export const defaultAdmissionRequest: AdmissionRequest = {
33
+ uid: "some-uid",
34
+ kind: { kind: "a-kind", group: "a-group" },
35
+ resource: { group: "some-group", version: "some-version", resource: "some-resource" },
36
+ operation: Operation.CONNECT,
37
+ name: "some-name",
38
+ userInfo: {},
39
+ object: {},
40
+ };
41
+
42
+ export const defaultKubernetesObject: KubernetesObject = {
43
+ apiVersion: "some-version",
44
+ kind: "some-kind",
45
+ metadata: { name: "some-name" },
46
+ };
@@ -38,7 +38,7 @@ import {
38
38
  missingCarriableNamespace,
39
39
  unbindableNamespaces,
40
40
  uncarryableNamespace,
41
- } from "./adjudicators";
41
+ } from "./adjudicators/adjudicators";
42
42
 
43
43
  /**
44
44
  * shouldSkipRequest determines if a request should be skipped based on the binding filters.
@@ -2,7 +2,7 @@
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
3
 
4
4
  import { K8s, KubernetesObject, RegisterKind } from "kubernetes-fluent-client";
5
- import Log from "./logger";
5
+ import Log from "./telemetry/logger";
6
6
  import { Binding, DeepPartial } from "./types";
7
7
  import { Operation } from "./enums";
8
8
  import { PeprMutateRequest } from "./mutate-request";
@@ -1,9 +1,8 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
3
 
4
- import { promises as fs } from "fs";
5
- import { K8s, KubernetesObject, kind } from "kubernetes-fluent-client";
6
- import Log from "./logger";
4
+ import { KubernetesObject } from "kubernetes-fluent-client";
5
+ import Log from "./telemetry/logger";
7
6
  import { Binding, CapabilityExport } from "./types";
8
7
  import { sanitizeResourceName } from "../sdk/sdk";
9
8
  import {
@@ -29,16 +28,10 @@ import {
29
28
  missingCarriableNamespace,
30
29
  unbindableNamespaces,
31
30
  uncarryableNamespace,
32
- } from "./filter/adjudicators";
31
+ } from "./filter/adjudicators/adjudicators";
33
32
 
34
33
  export function matchesRegex(pattern: string, testString: string): boolean {
35
- // edge-case
36
- if (!pattern) {
37
- return false;
38
- }
39
-
40
- const regex = new RegExp(pattern);
41
- return regex.test(testString);
34
+ return new RegExp(pattern).test(testString);
42
35
  }
43
36
 
44
37
  export class ValidationError extends Error {}
@@ -73,8 +66,8 @@ export type RBACMap = {
73
66
  * Decide to run callback after the event comes back from API Server
74
67
  **/
75
68
  export function filterNoMatchReason(
76
- binding: Partial<Binding>,
77
- obj: Partial<KubernetesObject>,
69
+ binding: Binding,
70
+ kubernetesObject: Partial<KubernetesObject>,
78
71
  capabilityNamespaces: string[],
79
72
  ignoredNamespaces?: string[],
80
73
  ): string {
@@ -82,30 +75,30 @@ export function filterNoMatchReason(
82
75
 
83
76
  // prettier-ignore
84
77
  return (
85
- mismatchedDeletionTimestamp(binding, obj) ?
78
+ mismatchedDeletionTimestamp(binding, kubernetesObject) ?
86
79
  `${prefix} Binding defines deletionTimestamp but Object does not carry it.` :
87
80
 
88
- mismatchedName(binding, obj) ?
89
- `${prefix} Binding defines name '${definedName(binding)}' but Object carries '${carriedName(obj)}'.` :
81
+ mismatchedName(binding, kubernetesObject) ?
82
+ `${prefix} Binding defines name '${definedName(binding)}' but Object carries '${carriedName(kubernetesObject)}'.` :
90
83
 
91
84
  misboundNamespace(binding) ?
92
85
  `${prefix} Cannot use namespace filter on a namespace object.` :
93
86
 
94
- mismatchedLabels(binding, obj) ?
87
+ mismatchedLabels(binding, kubernetesObject) ?
95
88
  (
96
89
  `${prefix} Binding defines labels '${JSON.stringify(definedLabels(binding))}' ` +
97
- `but Object carries '${JSON.stringify(carriedLabels(obj))}'.`
90
+ `but Object carries '${JSON.stringify(carriedLabels(kubernetesObject))}'.`
98
91
  ) :
99
92
 
100
- mismatchedAnnotations(binding, obj) ?
93
+ mismatchedAnnotations(binding, kubernetesObject) ?
101
94
  (
102
95
  `${prefix} Binding defines annotations '${JSON.stringify(definedAnnotations(binding))}' ` +
103
- `but Object carries '${JSON.stringify(carriedAnnotations(obj))}'.`
96
+ `but Object carries '${JSON.stringify(carriedAnnotations(kubernetesObject))}'.`
104
97
  ) :
105
98
 
106
- uncarryableNamespace(capabilityNamespaces, obj) ?
99
+ uncarryableNamespace(capabilityNamespaces, kubernetesObject) ?
107
100
  (
108
- `${prefix} Object carries namespace '${carriedNamespace(obj)}' ` +
101
+ `${prefix} Object carries namespace '${carriedNamespace(kubernetesObject)}' ` +
109
102
  `but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.`
110
103
  ) :
111
104
 
@@ -115,32 +108,32 @@ export function filterNoMatchReason(
115
108
  `but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.`
116
109
  ) :
117
110
 
118
- mismatchedNamespace(binding, obj) ?
111
+ mismatchedNamespace(binding, kubernetesObject) ?
119
112
  (
120
113
  `${prefix} Binding defines namespaces '${JSON.stringify(definedNamespaces(binding))}' ` +
121
- `but Object carries '${carriedNamespace(obj)}'.`
114
+ `but Object carries '${carriedNamespace(kubernetesObject)}'.`
122
115
  ) :
123
116
 
124
- mismatchedNamespaceRegex(binding, obj) ?
117
+ mismatchedNamespaceRegex(binding, kubernetesObject) ?
125
118
  (
126
119
  `${prefix} Binding defines namespace regexes ` +
127
120
  `'${JSON.stringify(definedNamespaceRegexes(binding))}' ` +
128
- `but Object carries '${carriedNamespace(obj)}'.`
121
+ `but Object carries '${carriedNamespace(kubernetesObject)}'.`
129
122
  ) :
130
123
 
131
- mismatchedNameRegex(binding, obj) ?
124
+ mismatchedNameRegex(binding, kubernetesObject) ?
132
125
  (
133
126
  `${prefix} Binding defines name regex '${definedNameRegex(binding)}' ` +
134
- `but Object carries '${carriedName(obj)}'.`
127
+ `but Object carries '${carriedName(kubernetesObject)}'.`
135
128
  ) :
136
129
 
137
- carriesIgnoredNamespace(ignoredNamespaces, obj) ?
130
+ carriesIgnoredNamespace(ignoredNamespaces, kubernetesObject) ?
138
131
  (
139
- `${prefix} Object carries namespace '${carriedNamespace(obj)}' ` +
132
+ `${prefix} Object carries namespace '${carriedNamespace(kubernetesObject)}' ` +
140
133
  `but ignored namespaces include '${JSON.stringify(ignoredNamespaces)}'.`
141
134
  ) :
142
135
 
143
- missingCarriableNamespace(capabilityNamespaces, obj) ?
136
+ missingCarriableNamespace(capabilityNamespaces, kubernetesObject) ?
144
137
  (
145
138
  `${prefix} Object does not carry a namespace ` +
146
139
  `but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.`
@@ -191,18 +184,6 @@ export function createRBACMap(capabilities: CapabilityExport[]): RBACMap {
191
184
  }, {});
192
185
  }
193
186
 
194
- export async function createDirectoryIfNotExists(path: string) {
195
- try {
196
- await fs.access(path);
197
- } catch (error) {
198
- if (error.code === "ENOENT") {
199
- await fs.mkdir(path, { recursive: true });
200
- } else {
201
- throw error;
202
- }
203
- }
204
- }
205
-
206
187
  export function hasEveryOverlap<T>(array1: T[], array2: T[]): boolean {
207
188
  if (!Array.isArray(array1) || !Array.isArray(array2)) {
208
189
  return false;
@@ -255,11 +236,13 @@ export function generateWatchNamespaceError(
255
236
  return err.replace(/\.([^ ])/g, ". $1");
256
237
  }
257
238
 
258
- // namespaceComplianceValidator ensures that capability bindinds respect ignored and capability namespaces
239
+ // namespaceComplianceValidator ensures that capability bindings respect ignored and capability namespaces
259
240
  export function namespaceComplianceValidator(capability: CapabilityExport, ignoredNamespaces?: string[]) {
260
241
  const { namespaces: capabilityNamespaces, bindings, name } = capability;
261
- const bindingNamespaces = bindings.flatMap((binding: Binding) => binding.filters.namespaces);
262
- const bindingRegexNamespaces = bindings.flatMap((binding: Binding) => binding.filters.regexNamespaces || []);
242
+ const bindingNamespaces: string[] = bindings.flatMap((binding: Binding) => binding.filters.namespaces);
243
+ const bindingRegexNamespaces: string[] = bindings.flatMap(
244
+ (binding: Binding) => binding.filters.regexNamespaces || [],
245
+ );
263
246
 
264
247
  const namespaceError = generateWatchNamespaceError(
265
248
  ignoredNamespaces ? ignoredNamespaces : [],
@@ -310,46 +293,6 @@ export function namespaceComplianceValidator(capability: CapabilityExport, ignor
310
293
  }
311
294
  }
312
295
 
313
- // check to see if all replicas are ready for all deployments in the pepr-system namespace
314
- // returns true if all deployments are ready, false otherwise
315
- export async function checkDeploymentStatus(namespace: string) {
316
- const deployments = await K8s(kind.Deployment).InNamespace(namespace).Get();
317
- let status = false;
318
- let readyCount = 0;
319
-
320
- for (const deployment of deployments.items) {
321
- const readyReplicas = deployment.status?.readyReplicas ? deployment.status?.readyReplicas : 0;
322
- if (deployment.status?.readyReplicas !== deployment.spec?.replicas) {
323
- Log.info(
324
- `Waiting for deployment ${deployment.metadata?.name} rollout to finish: ${readyReplicas} of ${deployment.spec?.replicas} replicas are available`,
325
- );
326
- } else {
327
- Log.info(
328
- `Deployment ${deployment.metadata?.name} rolled out: ${readyReplicas} of ${deployment.spec?.replicas} replicas are available`,
329
- );
330
- readyCount++;
331
- }
332
- }
333
- if (readyCount === deployments.items.length) {
334
- status = true;
335
- }
336
- return status;
337
- }
338
-
339
- // wait for all deployments in the pepr-system namespace to be ready
340
- export async function namespaceDeploymentsReady(namespace: string = "pepr-system") {
341
- Log.info(`Checking ${namespace} deployments status...`);
342
- let ready = false;
343
- while (!ready) {
344
- ready = await checkDeploymentStatus(namespace);
345
- if (ready) {
346
- return ready;
347
- }
348
- await new Promise(resolve => setTimeout(resolve, 1000));
349
- }
350
- Log.info(`All ${namespace} deployments are ready`);
351
- }
352
-
353
296
  // check if secret is over the size limit
354
297
  export function secretOverLimit(str: string): boolean {
355
298
  const encoder = new TextEncoder();
@@ -374,7 +317,7 @@ export const parseTimeout = (value: string, previous: unknown): number => {
374
317
  };
375
318
 
376
319
  // Remove leading whitespace while keeping format of file
377
- export function dedent(file: string) {
320
+ export function dedent(file: string): string {
378
321
  // Check if the first line is empty and remove it
379
322
  const lines = file.split("\n");
380
323
  if (lines[0].trim() === "") {
@@ -391,7 +334,7 @@ export function dedent(file: string) {
391
334
  return file;
392
335
  }
393
336
 
394
- export function replaceString(str: string, stringA: string, stringB: string) {
337
+ export function replaceString(str: string, stringA: string, stringB: string): string {
395
338
  // eslint-disable-next-line no-useless-escape
396
339
  const escapedStringA = stringA.replace(/[-\/\\^$*+?.()|[\]{}]/g, "\\$&");
397
340
  const regExp = new RegExp(escapedStringA, "g");
@@ -9,7 +9,7 @@ import { Errors } from "./errors";
9
9
  import { shouldSkipRequest } from "./filter/filter";
10
10
  import { MutateResponse } from "./k8s";
11
11
  import { AdmissionRequest } from "./types";
12
- import Log from "./logger";
12
+ import Log from "./telemetry/logger";
13
13
  import { ModuleConfig } from "./module";
14
14
  import { PeprMutateRequest } from "./mutate-request";
15
15
  import { base64Encode, convertFromBase64Map, convertToBase64Map } from "./utils";
@@ -11,19 +11,19 @@ export class PeprMutateRequest<T extends KubernetesObject> {
11
11
  Raw: T;
12
12
  #input: AdmissionRequest<T>;
13
13
 
14
- get PermitSideEffects() {
14
+ get PermitSideEffects(): boolean {
15
15
  return !this.#input.dryRun;
16
16
  }
17
17
 
18
- get IsDryRun() {
18
+ get IsDryRun(): boolean | undefined {
19
19
  return this.#input.dryRun;
20
20
  }
21
21
 
22
- get OldResource() {
22
+ get OldResource(): KubernetesObject | undefined {
23
23
  return this.#input.oldObject;
24
24
  }
25
25
 
26
- get Request() {
26
+ get Request(): AdmissionRequest<KubernetesObject> {
27
27
  return this.#input;
28
28
  }
29
29
 
@@ -42,11 +42,11 @@ export class PeprMutateRequest<T extends KubernetesObject> {
42
42
  }
43
43
  }
44
44
 
45
- Merge = (obj: DeepPartial<T>) => {
45
+ Merge = (obj: DeepPartial<T>): void => {
46
46
  this.Raw = mergeDeepRight(this.Raw, obj) as unknown as T;
47
47
  };
48
48
 
49
- SetLabel = (key: string, value: string) => {
49
+ SetLabel = (key: string, value: string): this => {
50
50
  const ref = this.Raw;
51
51
  ref.metadata = ref.metadata ?? {};
52
52
  ref.metadata.labels = ref.metadata.labels ?? {};
@@ -54,7 +54,7 @@ export class PeprMutateRequest<T extends KubernetesObject> {
54
54
  return this;
55
55
  };
56
56
 
57
- SetAnnotation = (key: string, value: string) => {
57
+ SetAnnotation = (key: string, value: string): this => {
58
58
  const ref = this.Raw;
59
59
  ref.metadata = ref.metadata ?? {};
60
60
  ref.metadata.annotations = ref.metadata.annotations ?? {};
@@ -62,25 +62,25 @@ export class PeprMutateRequest<T extends KubernetesObject> {
62
62
  return this;
63
63
  };
64
64
 
65
- RemoveLabel = (key: string) => {
65
+ RemoveLabel = (key: string): this => {
66
66
  if (this.Raw.metadata?.labels?.[key]) {
67
67
  delete this.Raw.metadata.labels[key];
68
68
  }
69
69
  return this;
70
70
  };
71
71
 
72
- RemoveAnnotation = (key: string) => {
72
+ RemoveAnnotation = (key: string): this => {
73
73
  if (this.Raw.metadata?.annotations?.[key]) {
74
74
  delete this.Raw.metadata.annotations[key];
75
75
  }
76
76
  return this;
77
77
  };
78
78
 
79
- HasLabel = (key: string) => {
79
+ HasLabel = (key: string): boolean => {
80
80
  return this.Raw.metadata?.labels?.[key] !== undefined;
81
81
  };
82
82
 
83
- HasAnnotation = (key: string) => {
83
+ HasAnnotation = (key: string): boolean => {
84
84
  return this.Raw.metadata?.annotations?.[key] !== undefined;
85
85
  };
86
86
  }
package/src/lib/queue.ts CHANGED
@@ -3,7 +3,7 @@
3
3
  import { KubernetesObject } from "@kubernetes/client-node";
4
4
  import { WatchPhase } from "kubernetes-fluent-client/dist/fluent/types";
5
5
  import { randomBytes } from "node:crypto";
6
- import Log from "./logger";
6
+ import Log from "./telemetry/logger";
7
7
 
8
8
  type WatchCallback = (obj: KubernetesObject, phase: WatchPhase) => Promise<void>;
9
9
 
@@ -29,11 +29,19 @@ export class Queue<K extends KubernetesObject> {
29
29
  this.#uid = `${Date.now()}-${randomBytes(2).toString("hex")}`;
30
30
  }
31
31
 
32
- label() {
32
+ label(): { name: string; uid: string } {
33
33
  return { name: this.#name, uid: this.#uid };
34
34
  }
35
35
 
36
- stats() {
36
+ stats(): {
37
+ queue: {
38
+ name: string;
39
+ uid: string;
40
+ };
41
+ stats: {
42
+ length: number;
43
+ };
44
+ } {
37
45
  return {
38
46
  queue: this.label(),
39
47
  stats: {
@@ -51,7 +59,7 @@ export class Queue<K extends KubernetesObject> {
51
59
  * @param reconcile The callback to enqueue for reconcile
52
60
  * @returns A promise that resolves when the object is reconciled
53
61
  */
54
- enqueue(item: K, phase: WatchPhase, reconcile: WatchCallback) {
62
+ enqueue(item: K, phase: WatchPhase, reconcile: WatchCallback): Promise<void> {
55
63
  const note = {
56
64
  queue: this.label(),
57
65
  item: {
@@ -73,7 +81,7 @@ export class Queue<K extends KubernetesObject> {
73
81
  *
74
82
  * @returns A promise that resolves when the webapp is reconciled
75
83
  */
76
- async #dequeue() {
84
+ async #dequeue(): Promise<false | undefined> {
77
85
  // If there is a pending promise, do nothing
78
86
  if (this.#pendingPromise) {
79
87
  Log.debug("Pending promise, not dequeuing");
@@ -57,11 +57,11 @@ export class OnSchedule implements Schedule {
57
57
  this.startTime = schedule?.startTime;
58
58
  this.completions = schedule?.completions;
59
59
  }
60
- setStore(store: PeprStore) {
60
+ setStore(store: PeprStore): void {
61
61
  this.store = store;
62
62
  this.startInterval();
63
63
  }
64
- startInterval() {
64
+ startInterval(): void {
65
65
  this.checkStore();
66
66
  this.getDuration();
67
67
  this.setupInterval();
@@ -70,7 +70,7 @@ export class OnSchedule implements Schedule {
70
70
  * Checks the store for this schedule and sets the values if it exists
71
71
  * @returns
72
72
  */
73
- checkStore() {
73
+ checkStore(): void {
74
74
  const result = this.store && this.store.getItem(this.name);
75
75
  if (result) {
76
76
  const storedSchedule = JSON.parse(result);
@@ -84,7 +84,7 @@ export class OnSchedule implements Schedule {
84
84
  * Saves the schedule to the store
85
85
  * @returns
86
86
  */
87
- saveToStore() {
87
+ saveToStore(): void {
88
88
  const schedule = {
89
89
  completions: this.completions,
90
90
  startTime: this.startTime,
@@ -97,7 +97,7 @@ export class OnSchedule implements Schedule {
97
97
  /**
98
98
  * Gets the durations in milliseconds
99
99
  */
100
- getDuration() {
100
+ getDuration(): void {
101
101
  switch (this.unit) {
102
102
  case "seconds":
103
103
  if (this.every < 10) throw new Error("10 Seconds in the smallest interval allowed");
@@ -119,7 +119,7 @@ export class OnSchedule implements Schedule {
119
119
  /**
120
120
  * Sets up the interval
121
121
  */
122
- setupInterval() {
122
+ setupInterval(): void {
123
123
  const now = new Date();
124
124
  let delay: number | undefined;
125
125
 
@@ -146,7 +146,7 @@ export class OnSchedule implements Schedule {
146
146
  /**
147
147
  * Starts the interval
148
148
  */
149
- start() {
149
+ start(): void {
150
150
  this.intervalId = setInterval(() => {
151
151
  if (this.completions === 0) {
152
152
  this.stop();
@@ -165,7 +165,7 @@ export class OnSchedule implements Schedule {
165
165
  /**
166
166
  * Stops the interval
167
167
  */
168
- stop() {
168
+ stop(): void {
169
169
  if (this.intervalId) {
170
170
  clearInterval(this.intervalId);
171
171
  this.intervalId = null;