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.
- package/dist/cli/build.helpers.d.ts.map +1 -1
- package/dist/cli/init/index.d.ts.map +1 -1
- package/dist/cli/init/templates.d.ts +4 -3
- package/dist/cli/init/templates.d.ts.map +1 -1
- package/dist/cli/init/walkthrough.d.ts +1 -0
- package/dist/cli/init/walkthrough.d.ts.map +1 -1
- package/dist/cli/types.d.ts +1 -1
- package/dist/cli/types.d.ts.map +1 -1
- package/dist/cli.js +493 -459
- package/dist/controller.js +1 -1
- package/dist/lib/assets/assets.d.ts +3 -2
- package/dist/lib/assets/assets.d.ts.map +1 -1
- package/dist/lib/assets/envrionment.d.ts +4 -0
- package/dist/lib/assets/envrionment.d.ts.map +1 -0
- package/dist/lib/assets/pods.d.ts +1 -3
- package/dist/lib/assets/pods.d.ts.map +1 -1
- package/dist/lib/assets/yaml/overridesFile.d.ts +1 -2
- package/dist/lib/assets/yaml/overridesFile.d.ts.map +1 -1
- package/dist/lib/filter/adjudication.d.ts +22 -0
- package/dist/lib/filter/adjudication.d.ts.map +1 -0
- package/dist/lib/filter/filter.d.ts +0 -19
- package/dist/lib/filter/filter.d.ts.map +1 -1
- package/dist/lib/types.d.ts +1 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib.js +229 -229
- package/dist/lib.js.map +4 -4
- package/package.json +9 -7
- package/src/cli/build.helpers.ts +3 -2
- package/src/cli/init/index.ts +20 -3
- package/src/cli/init/templates.ts +3 -3
- package/src/cli/init/walkthrough.ts +20 -0
- package/src/cli/types.ts +1 -1
- package/src/lib/assets/assets.ts +24 -5
- package/src/lib/assets/envrionment.ts +26 -0
- package/src/lib/assets/pods.ts +2 -26
- package/src/lib/assets/yaml/overridesFile.ts +2 -3
- package/src/lib/filter/adjudication.ts +196 -0
- package/src/lib/filter/filter.ts +20 -194
- package/src/lib/types.ts +1 -0
- package/src/fixtures/data/admission-create-clusterrole.json +0 -52
- package/src/fixtures/data/admission-create-deployment.json +0 -93
- package/src/fixtures/data/admission-create-pod.json +0 -272
- package/src/fixtures/data/admission-delete-pod.json +0 -272
- 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.
|
|
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:
|
|
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": "
|
|
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.
|
|
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.
|
|
81
|
+
"ts-jest": "29.3.1",
|
|
80
82
|
"undici": "^7.0.1"
|
|
81
83
|
},
|
|
82
84
|
"overrides": {
|
package/src/cli/build.helpers.ts
CHANGED
|
@@ -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
|
}
|
package/src/cli/init/index.ts
CHANGED
|
@@ -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."
|
|
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([
|
|
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
|
|
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 =
|
|
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
package/src/lib/assets/assets.ts
CHANGED
|
@@ -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:
|
|
101
|
-
watch:
|
|
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(
|
|
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 =
|
|
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
|
+
}
|
package/src/lib/assets/pods.ts
CHANGED
|
@@ -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
|
|
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 "../
|
|
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
|
+
}
|