pepr 0.46.3 → 0.47.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 (44) hide show
  1. package/dist/cli/build.helpers.d.ts.map +1 -1
  2. package/dist/cli/init/index.d.ts.map +1 -1
  3. package/dist/cli/init/templates.d.ts +4 -3
  4. package/dist/cli/init/templates.d.ts.map +1 -1
  5. package/dist/cli/init/walkthrough.d.ts +1 -0
  6. package/dist/cli/init/walkthrough.d.ts.map +1 -1
  7. package/dist/cli/types.d.ts +1 -1
  8. package/dist/cli/types.d.ts.map +1 -1
  9. package/dist/cli.js +493 -459
  10. package/dist/controller.js +1 -1
  11. package/dist/lib/assets/assets.d.ts +3 -2
  12. package/dist/lib/assets/assets.d.ts.map +1 -1
  13. package/dist/lib/assets/envrionment.d.ts +4 -0
  14. package/dist/lib/assets/envrionment.d.ts.map +1 -0
  15. package/dist/lib/assets/pods.d.ts +1 -3
  16. package/dist/lib/assets/pods.d.ts.map +1 -1
  17. package/dist/lib/assets/yaml/overridesFile.d.ts +1 -2
  18. package/dist/lib/assets/yaml/overridesFile.d.ts.map +1 -1
  19. package/dist/lib/filter/adjudication.d.ts +22 -0
  20. package/dist/lib/filter/adjudication.d.ts.map +1 -0
  21. package/dist/lib/filter/filter.d.ts +0 -19
  22. package/dist/lib/filter/filter.d.ts.map +1 -1
  23. package/dist/lib/types.d.ts +1 -0
  24. package/dist/lib/types.d.ts.map +1 -1
  25. package/dist/lib.js +229 -229
  26. package/dist/lib.js.map +4 -4
  27. package/package.json +9 -7
  28. package/src/cli/build.helpers.ts +3 -2
  29. package/src/cli/init/index.ts +20 -3
  30. package/src/cli/init/templates.ts +3 -3
  31. package/src/cli/init/walkthrough.ts +20 -0
  32. package/src/cli/types.ts +1 -1
  33. package/src/lib/assets/assets.ts +24 -5
  34. package/src/lib/assets/envrionment.ts +26 -0
  35. package/src/lib/assets/pods.ts +2 -26
  36. package/src/lib/assets/yaml/overridesFile.ts +2 -3
  37. package/src/lib/filter/adjudication.ts +196 -0
  38. package/src/lib/filter/filter.ts +20 -194
  39. package/src/lib/types.ts +1 -0
  40. package/src/fixtures/data/admission-create-clusterrole.json +0 -52
  41. package/src/fixtures/data/admission-create-deployment.json +0 -93
  42. package/src/fixtures/data/admission-create-pod.json +0 -272
  43. package/src/fixtures/data/admission-delete-pod.json +0 -272
  44. package/src/fixtures/loader.ts +0 -28
package/package.json CHANGED
@@ -13,9 +13,10 @@
13
13
  "/dist",
14
14
  "/src",
15
15
  "!src/**/*.test.ts",
16
+ "!src/fixtures/**",
16
17
  "!dist/**/*.test.d.ts*"
17
18
  ],
18
- "version": "0.46.3",
19
+ "version": "0.47.0",
19
20
  "main": "dist/lib.js",
20
21
  "types": "dist/lib.d.ts",
21
22
  "scripts": {
@@ -27,32 +28,33 @@
27
28
  "build:image:unicorn": "npm run build && docker buildx build --output type=docker --tag pepr:dev $(node scripts/read-unicorn-build-args.mjs) .",
28
29
  "set:version": "node scripts/set-version.js",
29
30
  "test": "npm run test:unit && npm run test:journey && npm run test:journey-wasm",
30
- "test:unit": "npm run gen-data-json && jest src --coverage --detectOpenHandles --coverageDirectory=./coverage --testPathIgnorePatterns='cosign.e2e.test.ts'",
31
+ "test:artifacts": "npm run build && jest src/build-artifact.test.ts",
31
32
  "test:integration": "npm run test:integration:prep && npm run test:integration:run",
32
33
  "test:integration:prep": "./integration/prep.sh",
33
34
  "test:integration:run": "jest --maxWorkers=4 integration",
34
35
  "test:journey": "npm run test:journey:k3d && npm run build && npm run test:journey:image && npm run test:journey:run",
35
- "test:journey:unicorn": "npm run test:journey:k3d && npm run build && npm run test:journey:image:unicorn && npm run test:journey:run",
36
36
  "test:journey-wasm": "npm run test:journey:k3d && npm run build && npm run test:journey:image && npm run test:journey:run-wasm",
37
37
  "test:journey-wasm:unicorn": "npm run test:journey:k3d && npm run build && npm run test:journey:image:unicorn && npm run test:journey:run-wasm",
38
- "test:journey:k3d": "k3d cluster delete pepr-dev && k3d cluster create pepr-dev --k3s-arg '--debug@server:0' --wait && kubectl rollout status deployment -n kube-system",
39
38
  "test:journey:image": "docker buildx build --output type=docker --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev",
40
39
  "test:journey:image:unicorn": "docker buildx build --output type=docker --tag pepr:dev $(node scripts/read-unicorn-build-args.mjs) . && k3d image import pepr:dev -c pepr-dev",
40
+ "test:journey:k3d": "k3d cluster delete pepr-dev && k3d cluster create pepr-dev --k3s-arg '--debug@server:0' --wait && kubectl rollout status deployment -n kube-system",
41
41
  "test:journey:run": "jest --detectOpenHandles journey/entrypoint.test.ts && npm run test:journey:upgrade",
42
42
  "test:journey:run-wasm": "jest --detectOpenHandles journey/entrypoint-wasm.test.ts",
43
+ "test:journey:unicorn": "npm run test:journey:k3d && npm run build && npm run test:journey:image:unicorn && npm run test:journey:run",
43
44
  "test:journey:upgrade": "npm run test:journey:k3d && npm run test:journey:image && jest --detectOpenHandles journey/pepr-upgrade.test.ts",
45
+ "test:unit": "npm run gen-data-json && jest src --coverage --detectOpenHandles --coverageDirectory=./coverage --testPathIgnorePatterns='build-artifact.test.ts'",
44
46
  "format:check": "eslint src && prettier --config .prettierrc src --check",
45
47
  "format:fix": "eslint src --fix && prettier --config .prettierrc src --write",
46
48
  "prepare": "if [ \"$NODE_ENV\" != 'production' ]; then husky; fi"
47
49
  },
48
50
  "dependencies": {
49
51
  "@types/ramda": "0.30.2",
50
- "express": "4.21.2",
52
+ "express": "5.1.0",
51
53
  "fast-json-patch": "3.1.1",
52
54
  "heredoc": "^1.3.1",
53
55
  "http-status-codes": "^2.3.0",
54
56
  "json-pointer": "^0.6.2",
55
- "kubernetes-fluent-client": "3.4.5",
57
+ "kubernetes-fluent-client": "3.4.6",
56
58
  "pino": "9.6.0",
57
59
  "pino-pretty": "13.0.0",
58
60
  "prom-client": "15.1.3",
@@ -76,7 +78,7 @@
76
78
  "jest": "29.7.0",
77
79
  "js-yaml": "^4.1.0",
78
80
  "shellcheck": "^3.0.0",
79
- "ts-jest": "29.2.6",
81
+ "ts-jest": "29.3.1",
80
82
  "undici": "^7.0.1"
81
83
  },
82
84
  "overrides": {
@@ -11,6 +11,7 @@ import { promises as fs } from "fs";
11
11
  import { generateAllYaml } from "../lib/assets/yaml/generateAllYaml";
12
12
  import { webhookConfigGenerator } from "../lib/assets/webhooks";
13
13
  import { generateZarfYamlGeneric } from "../lib/assets/yaml/generateZarfYaml";
14
+ import { getDeployment, getModuleSecret, getWatcher } from "../lib/assets/pods";
14
15
 
15
16
  interface ImageOptions {
16
17
  customImage?: string;
@@ -191,7 +192,7 @@ export async function generateYamlAndWriteToDisk(obj: {
191
192
  const yamlFile = `pepr-module-${uuid}.yaml`;
192
193
  const chartPath = `${uuid}-chart`;
193
194
  const yamlPath = resolve(outputDir, yamlFile);
194
- const yaml = await assets.allYaml(generateAllYaml, imagePullSecret);
195
+ const yaml = await assets.allYaml(generateAllYaml, getDeployment, getWatcher, imagePullSecret);
195
196
  const zarfPath = resolve(outputDir, "zarf.yaml");
196
197
 
197
198
  let localZarf = "";
@@ -203,6 +204,6 @@ export async function generateYamlAndWriteToDisk(obj: {
203
204
  await fs.writeFile(yamlPath, yaml);
204
205
  await fs.writeFile(zarfPath, localZarf);
205
206
 
206
- await assets.generateHelmChart(webhookConfigGenerator, outputDir);
207
+ await assets.generateHelmChart(webhookConfigGenerator, getWatcher, getModuleSecret, outputDir);
207
208
  console.info(`✅ K8s resource for the module saved to ${yamlPath}`);
208
209
  }
@@ -23,7 +23,6 @@ import {
23
23
  import { createDir, sanitizeName, write } from "./utils";
24
24
  import { confirm, PromptOptions, walkthrough } from "./walkthrough";
25
25
  import { ErrorList } from "../../lib/errors";
26
- import { OnError } from "./enums";
27
26
 
28
27
  export default function (program: RootCmd): void {
29
28
  let response = {} as PromptOptions;
@@ -35,12 +34,30 @@ export default function (program: RootCmd): void {
35
34
  .option("--description <string>", "Explain the purpose of the new module.")
36
35
  .option("--name <string>", "Set the name of the new module.")
37
36
  .option("--skip-post-init", "Skip npm install, git init, and VSCode launch.")
38
- .option(`--errorBehavior <${ErrorList.join("|")}>`, "Set an errorBehavior.", OnError.REJECT)
37
+ .option(`--errorBehavior <${ErrorList.join("|")}>`, "Set an errorBehavior.")
38
+ .option(
39
+ "--uuid [string]",
40
+ "Unique identifier for your module with a max length of 32 characters.",
41
+ (uuid: string): string => {
42
+ const uuidLengthLimit = 36;
43
+ // length of generated uuid
44
+ if (uuid.length > uuidLengthLimit) {
45
+ throw new Error("The UUID must be 36 characters or fewer.");
46
+ }
47
+ return uuid.toLocaleLowerCase();
48
+ },
49
+ )
39
50
  .hook("preAction", async thisCommand => {
40
51
  // TODO: Overrides for testing. Don't be so gross with Node CLI testing
41
52
  // TODO: See pepr/#1140
42
53
  if (process.env.TEST_MODE === "true") {
43
- prompts.inject(["pepr-test-module", "A test module for Pepr", "ignore", "y"]);
54
+ prompts.inject([
55
+ "pepr-test-module",
56
+ "A test module for Pepr",
57
+ "ignore",
58
+ "static-test",
59
+ "y",
60
+ ]);
44
61
  pkgOverride = "file:../pepr-0.0.0-development.tgz";
45
62
  response = await walkthrough();
46
63
  } else {
@@ -3,7 +3,7 @@
3
3
 
4
4
  import { dumpYaml } from "@kubernetes/client-node";
5
5
  import { inspect } from "util";
6
- import { v4 as uuidv4, v5 as uuidv5 } from "uuid";
6
+ import { v4 as uuidv4 } from "uuid";
7
7
 
8
8
  import eslintJSON from "../../templates/.eslintrc.template.json";
9
9
  import peprSnippetsJSON from "../../templates/pepr.code-snippets.json";
@@ -47,8 +47,8 @@ export type peprPackageJSON = {
47
47
  };
48
48
 
49
49
  export function genPkgJSON(opts: InitOptions, pgkVerOverride?: string): peprPackageJSON {
50
- // Generate a random UUID for the module based on the module name
51
- const uuid = uuidv5(opts.name, uuidv4());
50
+ // Generate a random UUID for the module based on the module name if it is not provided
51
+ const uuid = !opts.uuid ? uuidv4() : opts.uuid;
52
52
  // Generate a name for the module based on the module name
53
53
  const name = sanitizeName(opts.name);
54
54
  // Make typescript a dev dependency
@@ -13,6 +13,7 @@ export type PromptOptions = {
13
13
  name: string;
14
14
  description: string;
15
15
  errorBehavior: OnError;
16
+ uuid: string;
16
17
  };
17
18
 
18
19
  export type PartialPromptOptions = Partial<PromptOptions>;
@@ -22,10 +23,29 @@ export async function walkthrough(opts?: PartialPromptOptions): Promise<PromptOp
22
23
  ...(await setName(opts?.name)),
23
24
  ...(await setDescription(opts?.description)),
24
25
  ...(await setErrorBehavior(opts?.errorBehavior)),
26
+ ...(await setUUID(opts?.uuid)),
25
27
  };
26
28
  return result as PromptOptions;
27
29
  }
30
+ async function setUUID(uuid?: string): Promise<Answers<string>> {
31
+ const askUUID: PromptObject = {
32
+ type: "text",
33
+ name: "uuid",
34
+ message: "Enter a unique identifier for the new Pepr module.\n",
35
+ validate: (val: string) => {
36
+ const uuidLengthLimit = 36;
37
+ return (
38
+ val.length <= uuidLengthLimit || `The UUID must be ${uuidLengthLimit} characters or fewer.`
39
+ );
40
+ },
41
+ };
28
42
 
43
+ if (uuid !== undefined) {
44
+ return { uuid };
45
+ }
46
+
47
+ return prompt([askUUID]);
48
+ }
29
49
  export async function setName(name?: string): Promise<Answers<string>> {
30
50
  const askName: PromptObject = {
31
51
  type: "text",
package/src/cli/types.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { Answers } from "prompts";
2
2
 
3
- export type InitOptions = Answers<"name" | "description" | "errorBehavior">;
3
+ export type InitOptions = Answers<"name" | "description" | "errorBehavior" | "uuid">;
@@ -18,7 +18,6 @@ import {
18
18
  } from "@kubernetes/client-node/dist/gen";
19
19
  import { createDirectoryIfNotExists } from "../filesystemService";
20
20
  import { overridesFile } from "./yaml/overridesFile";
21
- import { getDeployment, getModuleSecret, getWatcher } from "./pods";
22
21
  import { helmLayout, createWebhookYaml, toYaml } from "./index";
23
22
  import { loadCapabilities } from "./loader";
24
23
  import { namespaceComplianceValidator, dedent } from "../helpers";
@@ -26,6 +25,7 @@ import { promises as fs } from "fs";
26
25
  import { storeRole, storeRoleBinding, clusterRoleBinding, serviceAccount } from "./rbac";
27
26
  import { watcherService, service, tlsSecret, apiPathSecret } from "./networking";
28
27
  import { WebhookType } from "../enums";
28
+ import { kind } from "kubernetes-fluent-client";
29
29
 
30
30
  export class Assets {
31
31
  readonly name: string;
@@ -84,6 +84,18 @@ export class Assets {
84
84
  assets: Assets,
85
85
  deployments: { default: V1Deployment; watch: V1Deployment | null },
86
86
  ) => Promise<string>,
87
+ getDeploymentFunction: (
88
+ assets: Assets,
89
+ hash: string,
90
+ buildTimestamp: string,
91
+ imagePullSecret?: string,
92
+ ) => kind.Deployment,
93
+ getWatcherFunction: (
94
+ assets: Assets,
95
+ hash: string,
96
+ buildTimestamp: string,
97
+ imagePullSecret?: string,
98
+ ) => kind.Deployment | null,
87
99
  imagePullSecret?: string,
88
100
  ): Promise<string> => {
89
101
  this.capabilities = await loadCapabilities(this.path);
@@ -97,8 +109,8 @@ export class Assets {
97
109
  const moduleHash = crypto.createHash("sha256").update(code).digest("hex");
98
110
 
99
111
  const deployments = {
100
- default: getDeployment(this, moduleHash, this.buildTimestamp, imagePullSecret),
101
- watch: getWatcher(this, moduleHash, this.buildTimestamp, imagePullSecret),
112
+ default: getDeploymentFunction(this, moduleHash, this.buildTimestamp, imagePullSecret),
113
+ watch: getWatcherFunction(this, moduleHash, this.buildTimestamp, imagePullSecret),
102
114
  };
103
115
 
104
116
  return yamlGenerationFunction(this, deployments);
@@ -141,6 +153,13 @@ export class Assets {
141
153
  mutateOrValidate: WebhookType,
142
154
  timeoutSeconds: number | undefined,
143
155
  ) => Promise<V1MutatingWebhookConfiguration | V1ValidatingWebhookConfiguration | null>,
156
+ getWatcherFunction: (
157
+ assets: Assets,
158
+ hash: string,
159
+ buildTimestamp: string,
160
+ imagePullSecret?: string,
161
+ ) => kind.Deployment | null,
162
+ getModuleSecretFunction: (name: string, data: Buffer, hash: string) => kind.Secret,
144
163
  basePath: string,
145
164
  ): Promise<void> => {
146
165
  const helm = helmLayout(basePath, this.config.uuid);
@@ -175,7 +194,7 @@ export class Assets {
175
194
  [helm.files.serviceAccountYaml, (): string => toYaml(serviceAccount(this.name))],
176
195
  [
177
196
  helm.files.moduleSecretYaml,
178
- (): string => toYaml(getModuleSecret(this.name, code, moduleHash)),
197
+ (): string => toYaml(getModuleSecretFunction(this.name, code, moduleHash)),
179
198
  ],
180
199
  ];
181
200
  await Promise.all(pairs.map(async ([file, content]) => await fs.writeFile(file, content())));
@@ -205,7 +224,7 @@ export class Assets {
205
224
 
206
225
  await this.writeWebhookFiles(webhooks.validate, webhooks.mutate, helm);
207
226
 
208
- const watchDeployment = getWatcher(this, moduleHash, this.buildTimestamp);
227
+ const watchDeployment = getWatcherFunction(this, moduleHash, this.buildTimestamp);
209
228
  if (watchDeployment) {
210
229
  await fs.writeFile(
211
230
  helm.files.watcherDeploymentYaml,
@@ -0,0 +1,26 @@
1
+ import { V1EnvVar } from "@kubernetes/client-node";
2
+ import { ModuleConfig } from "../types";
3
+
4
+ export function genEnv(
5
+ config: ModuleConfig,
6
+ watchMode = false,
7
+ ignoreWatchMode = false,
8
+ ): V1EnvVar[] {
9
+ const noWatchDef = {
10
+ PEPR_PRETTY_LOG: "false",
11
+ LOG_LEVEL: config.logLevel || "info",
12
+ };
13
+
14
+ const def = {
15
+ PEPR_WATCH_MODE: watchMode ? "true" : "false",
16
+ ...noWatchDef,
17
+ };
18
+
19
+ if (config.env && config.env["PEPR_WATCH_MODE"]) {
20
+ delete config.env["PEPR_WATCH_MODE"];
21
+ }
22
+ const cfg = config.env || {};
23
+ return ignoreWatchMode
24
+ ? Object.entries({ ...noWatchDef, ...cfg }).map(([name, value]) => ({ name, value }))
25
+ : Object.entries({ ...def, ...cfg }).map(([name, value]) => ({ name, value }));
26
+ }
@@ -1,13 +1,13 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
3
 
4
- import { KubernetesObject, V1EnvVar } from "@kubernetes/client-node";
4
+ import { KubernetesObject } from "@kubernetes/client-node";
5
5
  import { kind } from "kubernetes-fluent-client";
6
6
  import { gzipSync } from "zlib";
7
7
  import { secretOverLimit } from "../helpers";
8
8
  import { Assets } from "./assets";
9
- import { ModuleConfig } from "../types";
10
9
  import { Binding } from "../types";
10
+ import { genEnv } from "./envrionment";
11
11
 
12
12
  /** Generate the pepr-system namespace */
13
13
  export function getNamespace(namespaceLabels?: Record<string, string>): KubernetesObject {
@@ -365,27 +365,3 @@ export function getModuleSecret(name: string, data: Buffer, hash: string): kind.
365
365
  };
366
366
  }
367
367
  }
368
-
369
- export function genEnv(
370
- config: ModuleConfig,
371
- watchMode = false,
372
- ignoreWatchMode = false,
373
- ): V1EnvVar[] {
374
- const noWatchDef = {
375
- PEPR_PRETTY_LOG: "false",
376
- LOG_LEVEL: config.logLevel || "info",
377
- };
378
-
379
- const def = {
380
- PEPR_WATCH_MODE: watchMode ? "true" : "false",
381
- ...noWatchDef,
382
- };
383
-
384
- if (config.env && config.env["PEPR_WATCH_MODE"]) {
385
- delete config.env["PEPR_WATCH_MODE"];
386
- }
387
- const cfg = config.env || {};
388
- return ignoreWatchMode
389
- ? Object.entries({ ...noWatchDef, ...cfg }).map(([name, value]) => ({ name, value }))
390
- : Object.entries({ ...def, ...cfg }).map(([name, value]) => ({ name, value }));
391
- }
@@ -1,6 +1,5 @@
1
- import { genEnv } from "../pods";
2
- import { ModuleConfig } from "../../types";
3
- import { CapabilityExport } from "../../types";
1
+ import { genEnv } from "../envrionment";
2
+ import { CapabilityExport, ModuleConfig } from "../../types";
4
3
  import { dumpYaml } from "@kubernetes/client-node";
5
4
  import { clusterRole } from "../rbac";
6
5
  import { promises as fs } from "fs";
@@ -0,0 +1,196 @@
1
+ import { KubernetesObject } from "kubernetes-fluent-client";
2
+ import { AdmissionRequest } from "../common-types";
3
+ import { Binding } from "../types";
4
+ import {
5
+ declaredOperation,
6
+ declaredGroup,
7
+ declaredVersion,
8
+ declaredKind,
9
+ } from "./adjudicators/admissionRequest";
10
+ import {
11
+ definedEvent,
12
+ definedName,
13
+ definedGroup,
14
+ definedVersion,
15
+ definedKind,
16
+ definedNamespaces,
17
+ definedLabels,
18
+ definedAnnotations,
19
+ definedNamespaceRegexes,
20
+ definedNameRegex,
21
+ } from "./adjudicators/binding";
22
+ import {
23
+ carriedName,
24
+ carriedNamespace,
25
+ carriedLabels,
26
+ carriedAnnotations,
27
+ } from "./adjudicators/kubernetesObject";
28
+ import {
29
+ mismatchedDeletionTimestamp,
30
+ mismatchedEvent,
31
+ mismatchedName,
32
+ mismatchedGroup,
33
+ mismatchedVersion,
34
+ mismatchedKind,
35
+ mismatchedNamespace,
36
+ mismatchedLabels,
37
+ mismatchedAnnotations,
38
+ mismatchedNamespaceRegex,
39
+ mismatchedNameRegex,
40
+ } from "./adjudicators/mismatch";
41
+ import {
42
+ misboundNamespace,
43
+ misboundDeleteWithDeletionTimestamp,
44
+ unbindableNamespaces,
45
+ uncarryableNamespace,
46
+ carriesIgnoredNamespace,
47
+ missingCarriableNamespace,
48
+ } from "./adjudicators/postCollection";
49
+ import { AdjudicationResult } from "../types";
50
+
51
+ export function adjudicateMisboundNamespace(binding: Binding): AdjudicationResult {
52
+ return misboundNamespace(binding) ? "Cannot use namespace filter on a namespace object." : null;
53
+ }
54
+
55
+ export function adjudicateMisboundDeleteWithDeletionTimestamp(
56
+ binding: Binding,
57
+ ): AdjudicationResult {
58
+ return misboundDeleteWithDeletionTimestamp(binding)
59
+ ? "Cannot use deletionTimestamp filter on a DELETE operation."
60
+ : null;
61
+ }
62
+
63
+ export function adjudicateMismatchedDeletionTimestamp(
64
+ binding: Binding,
65
+ obj: KubernetesObject,
66
+ ): AdjudicationResult {
67
+ return mismatchedDeletionTimestamp(binding, obj)
68
+ ? "Binding defines deletionTimestamp but Object does not carry it."
69
+ : null;
70
+ }
71
+
72
+ export function adjudicateMismatchedEvent(
73
+ binding: Binding,
74
+ req: AdmissionRequest,
75
+ ): AdjudicationResult {
76
+ return mismatchedEvent(binding, req)
77
+ ? `Binding defines event '${definedEvent(binding)}' but Request declares '${declaredOperation(req)}'.`
78
+ : null;
79
+ }
80
+
81
+ export function adjudicateMismatchedName(
82
+ binding: Binding,
83
+ obj: KubernetesObject,
84
+ ): AdjudicationResult {
85
+ return mismatchedName(binding, obj)
86
+ ? `Binding defines name '${definedName(binding)}' but Object carries '${carriedName(obj)}'.`
87
+ : null;
88
+ }
89
+
90
+ export function adjudicateMismatchedGroup(
91
+ binding: Binding,
92
+ req: AdmissionRequest,
93
+ ): AdjudicationResult {
94
+ return mismatchedGroup(binding, req)
95
+ ? `Binding defines group '${definedGroup(binding)}' but Request declares '${declaredGroup(req)}'.`
96
+ : null;
97
+ }
98
+
99
+ export function adjudicateMismatchedVersion(
100
+ binding: Binding,
101
+ req: AdmissionRequest,
102
+ ): AdjudicationResult {
103
+ return mismatchedVersion(binding, req)
104
+ ? `Binding defines version '${definedVersion(binding)}' but Request declares '${declaredVersion(req)}'.`
105
+ : null;
106
+ }
107
+
108
+ export function adjudicateMismatchedKind(
109
+ binding: Binding,
110
+ req: AdmissionRequest,
111
+ ): AdjudicationResult {
112
+ return mismatchedKind(binding, req)
113
+ ? `Binding defines kind '${definedKind(binding)}' but Request declares '${declaredKind(req)}'.`
114
+ : null;
115
+ }
116
+
117
+ export function adjudicateUnbindableNamespaces(
118
+ capabilityNamespaces: string[],
119
+ binding: Binding,
120
+ ): AdjudicationResult {
121
+ return unbindableNamespaces(capabilityNamespaces, binding)
122
+ ? `Binding defines namespaces ${JSON.stringify(definedNamespaces(binding))} but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.`
123
+ : null;
124
+ }
125
+
126
+ export function adjudicateUncarryableNamespace(
127
+ capabilityNamespaces: string[],
128
+ obj: KubernetesObject,
129
+ ): AdjudicationResult {
130
+ return uncarryableNamespace(capabilityNamespaces, obj)
131
+ ? `Object carries namespace '${obj.kind && obj.kind === "Namespace" ? obj.metadata?.name : carriedNamespace(obj)}' but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.`
132
+ : null;
133
+ }
134
+
135
+ export function adjudicateMismatchedNamespace(
136
+ binding: Binding,
137
+ obj: KubernetesObject,
138
+ ): AdjudicationResult {
139
+ return mismatchedNamespace(binding, obj)
140
+ ? `Binding defines namespaces '${JSON.stringify(definedNamespaces(binding))}' but Object carries '${carriedNamespace(obj)}'.`
141
+ : null;
142
+ }
143
+
144
+ export function adjudicateMismatchedLabels(
145
+ binding: Binding,
146
+ obj: KubernetesObject,
147
+ ): AdjudicationResult {
148
+ return mismatchedLabels(binding, obj)
149
+ ? `Binding defines labels '${JSON.stringify(definedLabels(binding))}' but Object carries '${JSON.stringify(carriedLabels(obj))}'.`
150
+ : null;
151
+ }
152
+
153
+ export function adjudicateMismatchedAnnotations(
154
+ binding: Binding,
155
+ obj: KubernetesObject,
156
+ ): AdjudicationResult {
157
+ return mismatchedAnnotations(binding, obj)
158
+ ? `Binding defines annotations '${JSON.stringify(definedAnnotations(binding))}' but Object carries '${JSON.stringify(carriedAnnotations(obj))}'.`
159
+ : null;
160
+ }
161
+
162
+ export function adjudicateMismatchedNamespaceRegex(
163
+ binding: Binding,
164
+ obj: KubernetesObject,
165
+ ): AdjudicationResult {
166
+ return mismatchedNamespaceRegex(binding, obj)
167
+ ? `Binding defines namespace regexes '${JSON.stringify(definedNamespaceRegexes(binding))}' but Object carries '${carriedNamespace(obj)}'.`
168
+ : null;
169
+ }
170
+
171
+ export function adjudicateMismatchedNameRegex(
172
+ binding: Binding,
173
+ obj: KubernetesObject,
174
+ ): AdjudicationResult {
175
+ return mismatchedNameRegex(binding, obj)
176
+ ? `Binding defines name regex '${definedNameRegex(binding)}' but Object carries '${carriedName(obj)}'.`
177
+ : null;
178
+ }
179
+
180
+ export function adjudicateCarriesIgnoredNamespace(
181
+ ignoredNamespaces: string[] | undefined,
182
+ obj: KubernetesObject,
183
+ ): AdjudicationResult {
184
+ return carriesIgnoredNamespace(ignoredNamespaces, obj)
185
+ ? `Object carries namespace '${obj.kind && obj.kind === "Namespace" ? obj.metadata?.name : carriedNamespace(obj)}' but ignored namespaces include '${JSON.stringify(ignoredNamespaces)}'.`
186
+ : null;
187
+ }
188
+
189
+ export function adjudicateMissingCarriableNamespace(
190
+ capabilityNamespaces: string[],
191
+ obj: KubernetesObject,
192
+ ): AdjudicationResult {
193
+ return missingCarriableNamespace(capabilityNamespaces, obj)
194
+ ? `Object does not carry a namespace but namespaces allowed by Capability are '${JSON.stringify(capabilityNamespaces)}'.`
195
+ : null;
196
+ }