pepr 0.36.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/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/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 +115 -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 +1 -1
- package/dist/lib/watch-processor.d.ts.map +1 -1
- package/dist/lib.js +383 -204
- package/dist/lib.js.map +4 -4
- package/package.json +9 -7
- 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 +104 -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 +194 -8
- package/src/lib/filter.ts +46 -107
- package/src/lib/finalizer.test.ts +236 -0
- package/src/lib/finalizer.ts +63 -0
- package/src/lib/helpers.test.ts +329 -69
- package/src/lib/helpers.ts +141 -100
- 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/schedule.ts +1 -1
- package/src/lib/storage.ts +5 -6
- package/src/lib/types.ts +151 -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.ts +19 -5
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// SPDX-FileCopyrightText: 2023-Present The Pepr Authors
|
|
3
|
+
|
|
4
|
+
import { Event, Operation } from "./types";
|
|
5
|
+
import {
|
|
6
|
+
__,
|
|
7
|
+
allPass,
|
|
8
|
+
any,
|
|
9
|
+
anyPass,
|
|
10
|
+
complement,
|
|
11
|
+
curry,
|
|
12
|
+
defaultTo,
|
|
13
|
+
difference,
|
|
14
|
+
equals,
|
|
15
|
+
gt,
|
|
16
|
+
length,
|
|
17
|
+
not,
|
|
18
|
+
nthArg,
|
|
19
|
+
pipe,
|
|
20
|
+
} from "ramda";
|
|
21
|
+
|
|
22
|
+
/*
|
|
23
|
+
Naming scheme:
|
|
24
|
+
- AdmissionRequest - "declares" / "neglects"
|
|
25
|
+
- KubernetesObject - "carries" / "missing"
|
|
26
|
+
- Binding - "defines" / "ignores"
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
/*
|
|
30
|
+
AdmissionRequest collectors
|
|
31
|
+
*/
|
|
32
|
+
export const declaredOperation = pipe(request => request?.operation, defaultTo(""));
|
|
33
|
+
export const declaredGroup = pipe(request => request?.kind?.group, defaultTo(""));
|
|
34
|
+
export const declaredVersion = pipe(request => request?.kind?.version, defaultTo(""));
|
|
35
|
+
export const declaredKind = pipe(request => request?.kind?.kind, defaultTo(""));
|
|
36
|
+
export const declaredUid = pipe(request => request?.uid, defaultTo(""));
|
|
37
|
+
|
|
38
|
+
/*
|
|
39
|
+
KubernetesObject collectors
|
|
40
|
+
*/
|
|
41
|
+
export const carriesDeletionTimestamp = pipe(obj => !!obj.metadata?.deletionTimestamp, defaultTo(false));
|
|
42
|
+
export const missingDeletionTimestamp = complement(carriesDeletionTimestamp);
|
|
43
|
+
|
|
44
|
+
export const carriedName = pipe(obj => obj?.metadata?.name, defaultTo(""));
|
|
45
|
+
export const carriesName = pipe(carriedName, equals(""), not);
|
|
46
|
+
export const missingName = complement(carriesName);
|
|
47
|
+
|
|
48
|
+
export const carriedNamespace = pipe(obj => obj?.metadata?.namespace, defaultTo(""));
|
|
49
|
+
export const carriesNamespace = pipe(carriedNamespace, equals(""), not);
|
|
50
|
+
|
|
51
|
+
export const carriedAnnotations = pipe(obj => obj?.metadata?.annotations, defaultTo({}));
|
|
52
|
+
export const carriesAnnotations = pipe(carriedAnnotations, equals({}), not);
|
|
53
|
+
|
|
54
|
+
export const carriedLabels = pipe(obj => obj?.metadata?.labels, defaultTo({}));
|
|
55
|
+
export const carriesLabels = pipe(carriedLabels, equals({}), not);
|
|
56
|
+
|
|
57
|
+
/*
|
|
58
|
+
Binding collectors
|
|
59
|
+
*/
|
|
60
|
+
export const definesDeletionTimestamp = pipe(binding => binding?.filters?.deletionTimestamp, defaultTo(false));
|
|
61
|
+
export const ignoresDeletionTimestamp = complement(definesDeletionTimestamp);
|
|
62
|
+
|
|
63
|
+
export const definedName = pipe(binding => binding?.filters?.name, defaultTo(""));
|
|
64
|
+
export const definesName = pipe(definedName, equals(""), not);
|
|
65
|
+
export const ignoresName = complement(definesName);
|
|
66
|
+
|
|
67
|
+
export const definedNameRegex = pipe(binding => binding?.filters?.regexName, defaultTo(""));
|
|
68
|
+
export const definesNameRegex = pipe(definedNameRegex, equals(""), not);
|
|
69
|
+
|
|
70
|
+
export const definedNamespaces = pipe(binding => binding?.filters?.namespaces, defaultTo([]));
|
|
71
|
+
export const definesNamespaces = pipe(definedNamespaces, equals([]), not);
|
|
72
|
+
|
|
73
|
+
export const definedNamespaceRegexes = pipe(binding => binding?.filters?.regexNamespaces, defaultTo([]));
|
|
74
|
+
export const definesNamespaceRegexes = pipe(definedNamespaceRegexes, equals([]), not);
|
|
75
|
+
|
|
76
|
+
export const definedAnnotations = pipe(binding => binding?.filters?.annotations, defaultTo({}));
|
|
77
|
+
export const definesAnnotations = pipe(definedAnnotations, equals({}), not);
|
|
78
|
+
|
|
79
|
+
export const definedLabels = pipe(binding => binding?.filters?.labels, defaultTo({}));
|
|
80
|
+
export const definesLabels = pipe(definedLabels, equals({}), not);
|
|
81
|
+
|
|
82
|
+
export const definedEvent = pipe(binding => binding?.event, defaultTo(""));
|
|
83
|
+
export const definesDelete = pipe(definedEvent, equals(Operation.DELETE));
|
|
84
|
+
|
|
85
|
+
export const definedGroup = pipe(binding => binding?.kind?.group, defaultTo(""));
|
|
86
|
+
export const definesGroup = pipe(definedGroup, equals(""), not);
|
|
87
|
+
|
|
88
|
+
export const definedVersion = pipe(binding => binding?.kind?.version, defaultTo(""));
|
|
89
|
+
export const definesVersion = pipe(definedVersion, equals(""), not);
|
|
90
|
+
|
|
91
|
+
export const definedKind = pipe(binding => binding?.kind?.kind, defaultTo(""));
|
|
92
|
+
export const definesKind = pipe(definedKind, equals(""), not);
|
|
93
|
+
|
|
94
|
+
export const definedCategory = pipe(binding => {
|
|
95
|
+
// prettier-ignore
|
|
96
|
+
return (
|
|
97
|
+
binding.isFinalize ? "Finalize" :
|
|
98
|
+
binding.isWatch ? "Watch" :
|
|
99
|
+
binding.isMutate ? "Mutate" :
|
|
100
|
+
binding.isValidate ? "Validate" :
|
|
101
|
+
""
|
|
102
|
+
);
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
export const definedCallback = pipe(binding => {
|
|
106
|
+
// prettier-ignore
|
|
107
|
+
return (
|
|
108
|
+
binding.isFinalize ? binding.finalizeCallback :
|
|
109
|
+
binding.isWatch ? binding.watchCallback :
|
|
110
|
+
binding.isMutate ? binding.mutateCallback :
|
|
111
|
+
binding.isValidate ? binding.validateCallback:
|
|
112
|
+
null
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
export const definedCallbackName = pipe(definedCallback, defaultTo({ name: "" }), cb => cb.name);
|
|
116
|
+
|
|
117
|
+
/*
|
|
118
|
+
post-collection comparitors
|
|
119
|
+
*/
|
|
120
|
+
export const mismatchedDeletionTimestamp = allPass([
|
|
121
|
+
pipe(nthArg(0), definesDeletionTimestamp),
|
|
122
|
+
pipe(nthArg(1), missingDeletionTimestamp),
|
|
123
|
+
]);
|
|
124
|
+
|
|
125
|
+
export const mismatchedName = allPass([
|
|
126
|
+
pipe(nthArg(0), definesName),
|
|
127
|
+
pipe((bnd, obj) => definedName(bnd) !== carriedName(obj)),
|
|
128
|
+
]);
|
|
129
|
+
|
|
130
|
+
export const mismatchedNameRegex = allPass([
|
|
131
|
+
pipe(nthArg(0), definesNameRegex),
|
|
132
|
+
pipe((bnd, obj) => new RegExp(definedNameRegex(bnd)).test(carriedName(obj)), not),
|
|
133
|
+
]);
|
|
134
|
+
|
|
135
|
+
export const bindsToKind = curry(
|
|
136
|
+
allPass([pipe(nthArg(0), definedKind, equals(""), not), pipe((bnd, knd) => definedKind(bnd) === knd)]),
|
|
137
|
+
);
|
|
138
|
+
export const bindsToNamespace = curry(pipe(bindsToKind(__, "Namespace")));
|
|
139
|
+
export const misboundNamespace = allPass([bindsToNamespace, definesNamespaces]);
|
|
140
|
+
|
|
141
|
+
export const mismatchedNamespace = allPass([
|
|
142
|
+
pipe(nthArg(0), definesNamespaces),
|
|
143
|
+
pipe((bnd, obj) => definedNamespaces(bnd).includes(carriedNamespace(obj)), not),
|
|
144
|
+
]);
|
|
145
|
+
|
|
146
|
+
export const mismatchedNamespaceRegex = allPass([
|
|
147
|
+
pipe(nthArg(0), definesNamespaceRegexes),
|
|
148
|
+
pipe((bnd, obj) =>
|
|
149
|
+
pipe(
|
|
150
|
+
any((rex: string) => new RegExp(rex).test(carriedNamespace(obj))),
|
|
151
|
+
not,
|
|
152
|
+
)(definedNamespaceRegexes(bnd)),
|
|
153
|
+
),
|
|
154
|
+
]);
|
|
155
|
+
|
|
156
|
+
export const metasMismatch = pipe(
|
|
157
|
+
(defined, carried) => {
|
|
158
|
+
const result = { defined, carried, unalike: {} };
|
|
159
|
+
|
|
160
|
+
result.unalike = Object.entries(result.defined)
|
|
161
|
+
.map(([key, val]) => {
|
|
162
|
+
const keyMissing = !Object.hasOwn(result.carried, key);
|
|
163
|
+
const noValue = !val;
|
|
164
|
+
const valMissing = !result.carried[key];
|
|
165
|
+
|
|
166
|
+
// prettier-ignore
|
|
167
|
+
return (
|
|
168
|
+
keyMissing ? { [key]: val } :
|
|
169
|
+
noValue ? {} :
|
|
170
|
+
valMissing ? { [key]: val } :
|
|
171
|
+
{}
|
|
172
|
+
)
|
|
173
|
+
})
|
|
174
|
+
.reduce((acc, cur) => ({ ...acc, ...cur }), {});
|
|
175
|
+
|
|
176
|
+
return result.unalike;
|
|
177
|
+
},
|
|
178
|
+
unalike => Object.keys(unalike).length > 0,
|
|
179
|
+
);
|
|
180
|
+
|
|
181
|
+
export const mismatchedAnnotations = allPass([
|
|
182
|
+
pipe(nthArg(0), definesAnnotations),
|
|
183
|
+
pipe((bnd, obj) => metasMismatch(definedAnnotations(bnd), carriedAnnotations(obj))),
|
|
184
|
+
]);
|
|
185
|
+
|
|
186
|
+
export const mismatchedLabels = allPass([
|
|
187
|
+
pipe(nthArg(0), definesLabels),
|
|
188
|
+
pipe((bnd, obj) => metasMismatch(definedLabels(bnd), carriedLabels(obj))),
|
|
189
|
+
]);
|
|
190
|
+
|
|
191
|
+
export const uncarryableNamespace = allPass([
|
|
192
|
+
pipe(nthArg(0), length, gt(__, 0)),
|
|
193
|
+
pipe(nthArg(1), carriesNamespace),
|
|
194
|
+
pipe((nss, obj) => nss.includes(carriedNamespace(obj)), not),
|
|
195
|
+
]);
|
|
196
|
+
|
|
197
|
+
export const carriesIgnoredNamespace = allPass([
|
|
198
|
+
pipe(nthArg(0), length, gt(__, 0)),
|
|
199
|
+
pipe(nthArg(1), carriesNamespace),
|
|
200
|
+
pipe((nss, obj) => nss.includes(carriedNamespace(obj))),
|
|
201
|
+
]);
|
|
202
|
+
|
|
203
|
+
export const unbindableNamespaces = allPass([
|
|
204
|
+
pipe(nthArg(0), length, gt(__, 0)),
|
|
205
|
+
pipe(nthArg(1), definesNamespaces),
|
|
206
|
+
pipe((nss, bnd) => difference(definedNamespaces(bnd), nss), length, equals(0), not),
|
|
207
|
+
]);
|
|
208
|
+
|
|
209
|
+
export const misboundDeleteWithDeletionTimestamp = allPass([definesDelete, definesDeletionTimestamp]);
|
|
210
|
+
|
|
211
|
+
export const operationMatchesEvent = anyPass([
|
|
212
|
+
pipe(nthArg(1), equals(Event.Any)),
|
|
213
|
+
pipe((op, evt) => op === evt),
|
|
214
|
+
pipe((op, evt) => (op ? evt.includes(op) : false)),
|
|
215
|
+
]);
|
|
216
|
+
|
|
217
|
+
export const mismatchedEvent = pipe(
|
|
218
|
+
(binding, request) => operationMatchesEvent(declaredOperation(request), definedEvent(binding)),
|
|
219
|
+
not,
|
|
220
|
+
);
|
|
221
|
+
|
|
222
|
+
export const mismatchedGroup = allPass([
|
|
223
|
+
pipe(nthArg(0), definesGroup),
|
|
224
|
+
pipe((binding, request) => definedGroup(binding) !== declaredGroup(request)),
|
|
225
|
+
]);
|
|
226
|
+
|
|
227
|
+
export const mismatchedVersion = allPass([
|
|
228
|
+
pipe(nthArg(0), definesVersion),
|
|
229
|
+
pipe((binding, request) => definedVersion(binding) !== declaredVersion(request)),
|
|
230
|
+
]);
|
|
231
|
+
|
|
232
|
+
export const mismatchedKind = allPass([
|
|
233
|
+
pipe(nthArg(0), definesKind),
|
|
234
|
+
pipe((binding, request) => definedKind(binding) !== declaredKind(request)),
|
|
235
|
+
]);
|
package/src/lib/assets/index.ts
CHANGED
|
@@ -65,7 +65,7 @@ export class Assets {
|
|
|
65
65
|
this.capabilities = await loadCapabilities(this.path);
|
|
66
66
|
// give error if namespaces are not respected
|
|
67
67
|
for (const capability of this.capabilities) {
|
|
68
|
-
namespaceComplianceValidator(capability, this.alwaysIgnore
|
|
68
|
+
namespaceComplianceValidator(capability, this.alwaysIgnore?.namespaces);
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
return allYaml(this, rbacMode, imagePullSecret);
|
package/src/lib/assets/loader.ts
CHANGED
|
@@ -82,7 +82,7 @@ export async function webhookConfig(
|
|
|
82
82
|
const ignore = [peprIgnoreLabel];
|
|
83
83
|
|
|
84
84
|
const { name, tls, config, apiToken, host } = assets;
|
|
85
|
-
const ignoreNS = concat(peprIgnoreNamespaces, config
|
|
85
|
+
const ignoreNS = concat(peprIgnoreNamespaces, config?.alwaysIgnore?.namespaces || []);
|
|
86
86
|
|
|
87
87
|
// Add any namespaces to ignore
|
|
88
88
|
if (ignoreNS) {
|