pepr 0.45.0 → 0.45.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.
- package/README.md +7 -7
- package/dist/cli/build.d.ts +1 -1
- package/dist/cli/build.d.ts.map +1 -1
- package/dist/cli/init/templates.d.ts +1 -2
- package/dist/cli/init/templates.d.ts.map +1 -1
- package/dist/cli.js +2 -2
- package/dist/controller.js +1 -1
- package/dist/lib/assets/assets.d.ts +2 -2
- package/dist/lib/assets/assets.d.ts.map +1 -1
- package/dist/lib/assets/index.d.ts +1 -1
- package/dist/lib/assets/index.d.ts.map +1 -1
- package/dist/lib/assets/pods.d.ts +1 -1
- package/dist/lib/assets/pods.d.ts.map +1 -1
- package/dist/lib/assets/yaml/overridesFile.d.ts +1 -1
- package/dist/lib/assets/yaml/overridesFile.d.ts.map +1 -1
- package/dist/lib/controller/index.d.ts +1 -1
- package/dist/lib/controller/index.d.ts.map +1 -1
- package/dist/lib/core/envChecks.d.ts +4 -0
- package/dist/lib/core/envChecks.d.ts.map +1 -0
- package/dist/lib/core/module.d.ts +1 -51
- package/dist/lib/core/module.d.ts.map +1 -1
- package/dist/lib/processors/mutate-processor.d.ts +1 -1
- package/dist/lib/processors/mutate-processor.d.ts.map +1 -1
- package/dist/lib/processors/validate-processor.d.ts +1 -1
- package/dist/lib/processors/validate-processor.d.ts.map +1 -1
- package/dist/lib/processors/watch-processor.d.ts +22 -1
- package/dist/lib/processors/watch-processor.d.ts.map +1 -1
- package/dist/lib/telemetry/metrics.d.ts +2 -3
- package/dist/lib/telemetry/metrics.d.ts.map +1 -1
- package/dist/lib/types.d.ts +45 -0
- package/dist/lib/types.d.ts.map +1 -1
- package/dist/lib.js +2027 -2027
- package/dist/lib.js.map +4 -4
- package/dist/sdk/sdk.d.ts +6 -1
- package/dist/sdk/sdk.d.ts.map +1 -1
- package/package.json +6 -7
- package/src/cli/build.ts +3 -3
- package/src/cli/init/templates.ts +1 -1
- package/src/lib/assets/assets.ts +2 -2
- package/src/lib/assets/index.ts +1 -2
- package/src/lib/assets/pods.ts +1 -1
- package/src/lib/assets/yaml/overridesFile.ts +1 -1
- package/src/lib/controller/index.ts +2 -1
- package/src/lib/core/capability.ts +1 -1
- package/src/lib/core/envChecks.ts +6 -0
- package/src/lib/core/module.ts +3 -62
- package/src/lib/processors/mutate-processor.ts +1 -1
- package/src/lib/processors/validate-processor.ts +1 -1
- package/src/lib/processors/watch-processor.ts +58 -33
- package/src/lib/telemetry/metrics.ts +3 -3
- package/src/lib/types.ts +48 -0
- package/src/sdk/sdk.ts +8 -4
package/dist/sdk/sdk.d.ts
CHANGED
|
@@ -19,7 +19,12 @@ export declare function containers(request: PeprValidateRequest<kind.Pod> | Pepr
|
|
|
19
19
|
* @param reportingComponent The component that is reporting the event, for example "uds.dev/operator"
|
|
20
20
|
* @param reportingInstance The instance of the component that is reporting the event, for example process.env.HOSTNAME
|
|
21
21
|
*/
|
|
22
|
-
export declare function writeEvent(cr: GenericKind, event: Partial<kind.CoreEvent>,
|
|
22
|
+
export declare function writeEvent(cr: GenericKind, event: Partial<kind.CoreEvent>, options: {
|
|
23
|
+
eventType: string;
|
|
24
|
+
eventReason: string;
|
|
25
|
+
reportingComponent: string;
|
|
26
|
+
reportingInstance: string;
|
|
27
|
+
}): Promise<void>;
|
|
23
28
|
/**
|
|
24
29
|
* Get the owner reference for a custom resource
|
|
25
30
|
* @param customResource the custom resource to get the owner reference for
|
package/dist/sdk/sdk.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/sdk/sdk.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAO,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAElE;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,EACpE,aAAa,CAAC,EAAE,YAAY,GAAG,gBAAgB,GAAG,qBAAqB,GACtE,WAAW,EAAE,CAef;AAED;;;;;;;;;GASG;AAEH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,WAAW,EACf,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAC9B,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/sdk/sdk.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACxE,OAAO,EAAE,WAAW,EAAO,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAElE;;;;;GAKG;AACH,wBAAgB,UAAU,CACxB,OAAO,EAAE,mBAAmB,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,EACpE,aAAa,CAAC,EAAE,YAAY,GAAG,gBAAgB,GAAG,qBAAqB,GACtE,WAAW,EAAE,CAef;AAED;;;;;;;;;GASG;AAEH,wBAAsB,UAAU,CAC9B,EAAE,EAAE,WAAW,EACf,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,EAC9B,OAAO,EAAE;IACP,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,iBAAiB,EAAE,MAAM,CAAC;CAC3B,GACA,OAAO,CAAC,IAAI,CAAC,CAuBf;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,cAAc,EAAE,WAAW,EAC3B,kBAAkB,CAAC,EAAE,OAAO,EAC5B,UAAU,CAAC,EAAE,OAAO,GACnB,gBAAgB,EAAE,CAcpB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAYzD"}
|
package/package.json
CHANGED
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
"!src/**/*.test.ts",
|
|
16
16
|
"!dist/**/*.test.d.ts*"
|
|
17
17
|
],
|
|
18
|
-
"version": "0.45.
|
|
18
|
+
"version": "0.45.1",
|
|
19
19
|
"main": "dist/lib.js",
|
|
20
20
|
"types": "dist/lib.d.ts",
|
|
21
21
|
"scripts": {
|
|
@@ -25,17 +25,16 @@
|
|
|
25
25
|
"build": "tsc && node build.mjs && npm pack",
|
|
26
26
|
"build:image": "npm run build && docker buildx build --output type=docker --tag pepr:dev .",
|
|
27
27
|
"set:version": "node scripts/set-version.js",
|
|
28
|
-
"test": "npm run test:unit && npm run test:journey",
|
|
28
|
+
"test": "npm run test:unit && npm run test:journey && npm run test:journey-wasm",
|
|
29
29
|
"test:unit": "npm run gen-data-json && jest src --coverage --detectOpenHandles --coverageDirectory=./coverage --testPathIgnorePatterns='cosign.e2e.test.ts'",
|
|
30
30
|
"test:integration": "npm run test:integration:prep && npm run test:integration:run",
|
|
31
31
|
"test:integration:prep": "./integration/prep.sh",
|
|
32
32
|
"test:integration:run": "jest --maxWorkers=4 integration",
|
|
33
33
|
"test:journey": "npm run test:journey:k3d && npm run build && npm run test:journey:image && npm run test:journey:run",
|
|
34
|
-
"test:journey:prep": "if [ ! -d ./pepr-upgrade-test ]; then git clone https://github.com/defenseunicorns/pepr-upgrade-test.git ; fi",
|
|
35
34
|
"test:journey-wasm": "npm run test:journey:k3d && npm run build && npm run test:journey:image && npm run test:journey:run-wasm",
|
|
36
35
|
"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",
|
|
37
36
|
"test:journey:image": "docker buildx build --output type=docker --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev",
|
|
38
|
-
"test:journey:run": "jest --detectOpenHandles journey/entrypoint.test.ts && npm run test:journey:
|
|
37
|
+
"test:journey:run": "jest --detectOpenHandles journey/entrypoint.test.ts && npm run test:journey:upgrade",
|
|
39
38
|
"test:journey:run-wasm": "jest --detectOpenHandles journey/entrypoint-wasm.test.ts",
|
|
40
39
|
"test:journey:upgrade": "npm run test:journey:k3d && npm run test:journey:image && jest --detectOpenHandles journey/pepr-upgrade.test.ts",
|
|
41
40
|
"format:check": "eslint src && prettier src --check",
|
|
@@ -49,12 +48,12 @@
|
|
|
49
48
|
"follow-redirects": "1.15.9",
|
|
50
49
|
"http-status-codes": "^2.3.0",
|
|
51
50
|
"json-pointer": "^0.6.2",
|
|
52
|
-
"kubernetes-fluent-client": "3.
|
|
51
|
+
"kubernetes-fluent-client": "3.4.0",
|
|
53
52
|
"pino": "9.6.0",
|
|
54
53
|
"pino-pretty": "13.0.0",
|
|
55
54
|
"prom-client": "15.1.3",
|
|
56
55
|
"ramda": "0.30.1",
|
|
57
|
-
"sigstore": "3.
|
|
56
|
+
"sigstore": "3.1.0"
|
|
58
57
|
},
|
|
59
58
|
"devDependencies": {
|
|
60
59
|
"@commitlint/cli": "19.7.1",
|
|
@@ -84,7 +83,7 @@
|
|
|
84
83
|
"@typescript-eslint/eslint-plugin": "8.23.0",
|
|
85
84
|
"@typescript-eslint/parser": "8.23.0",
|
|
86
85
|
"commander": "13.1.0",
|
|
87
|
-
"esbuild": "0.
|
|
86
|
+
"esbuild": "0.25.0",
|
|
88
87
|
"eslint": "8.57.0",
|
|
89
88
|
"node-forge": "1.3.1",
|
|
90
89
|
"prettier": "3.4.2",
|
package/src/cli/build.ts
CHANGED
|
@@ -11,7 +11,7 @@ import { RootCmd } from "./root";
|
|
|
11
11
|
import { Option } from "commander";
|
|
12
12
|
import { parseTimeout } from "../lib/helpers";
|
|
13
13
|
import { peprFormat } from "./format";
|
|
14
|
-
import { ModuleConfig } from "../lib/
|
|
14
|
+
import { ModuleConfig } from "../lib/types";
|
|
15
15
|
import {
|
|
16
16
|
watchForChanges,
|
|
17
17
|
determineRbacMode,
|
|
@@ -95,7 +95,7 @@ export default function (program: RootCmd): void {
|
|
|
95
95
|
.addOption(
|
|
96
96
|
new Option(
|
|
97
97
|
"-v, --version <version>",
|
|
98
|
-
"The version of the Pepr image to use in the deployment manifests. Example: '0.27.3'.",
|
|
98
|
+
"DEPRECATED: The version of the Pepr image to use in the deployment manifests. Example: '0.27.3'.",
|
|
99
99
|
).conflicts(["customImage", "registryInfo"]),
|
|
100
100
|
)
|
|
101
101
|
.option(
|
|
@@ -164,7 +164,7 @@ export default function (program: RootCmd): void {
|
|
|
164
164
|
console.info(`✅ Module built successfully at ${path}`);
|
|
165
165
|
return;
|
|
166
166
|
}
|
|
167
|
-
// set the image version if provided
|
|
167
|
+
// set the image version if provided -- DEPRECATED
|
|
168
168
|
if (opts.version) cfg.pepr.peprVersion = opts.version;
|
|
169
169
|
|
|
170
170
|
// Generate a secret for the module
|
|
@@ -11,7 +11,7 @@ import prettierJSON from "../../templates/.prettierrc.json";
|
|
|
11
11
|
import samplesJSON from "../../templates/capabilities/hello-pepr.samples.json";
|
|
12
12
|
import settingsJSON from "../../templates/settings.json";
|
|
13
13
|
import tsConfigJSON from "../../templates/tsconfig.module.json";
|
|
14
|
-
import { CustomLabels } from "../../lib/
|
|
14
|
+
import { CustomLabels } from "../../lib/types";
|
|
15
15
|
import { InitOptions } from "../types";
|
|
16
16
|
import { OnError, RbacMode } from "./enums";
|
|
17
17
|
import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
|
package/src/lib/assets/assets.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import crypto from "crypto";
|
|
2
2
|
import { CapabilityExport } from "../types";
|
|
3
|
-
import { ModuleConfig } from "../
|
|
3
|
+
import { ModuleConfig } from "../types";
|
|
4
4
|
import { TLSOut, genTLS } from "../tls";
|
|
5
5
|
import { WebhookIgnore } from "../k8s";
|
|
6
6
|
import {
|
|
@@ -81,7 +81,7 @@ export class Assets {
|
|
|
81
81
|
|
|
82
82
|
allYaml = async (
|
|
83
83
|
yamlGenerationFunction: (
|
|
84
|
-
|
|
84
|
+
assets: Assets,
|
|
85
85
|
deployments: { default: V1Deployment; watch: V1Deployment | null },
|
|
86
86
|
) => Promise<string>,
|
|
87
87
|
imagePullSecret?: string,
|
package/src/lib/assets/index.ts
CHANGED
|
@@ -5,14 +5,13 @@ import { dumpYaml } from "@kubernetes/client-node";
|
|
|
5
5
|
import { kind } from "kubernetes-fluent-client";
|
|
6
6
|
import { replaceString } from "../helpers";
|
|
7
7
|
import { resolve } from "path";
|
|
8
|
-
import { ModuleConfig } from "../
|
|
8
|
+
import { ModuleConfig } from "../types";
|
|
9
9
|
|
|
10
10
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
11
11
|
export function toYaml(obj: any): string {
|
|
12
12
|
return dumpYaml(obj, { noRefs: true });
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
// Unit Test Me!!
|
|
16
15
|
export function createWebhookYaml(
|
|
17
16
|
name: string,
|
|
18
17
|
config: ModuleConfig,
|
package/src/lib/assets/pods.ts
CHANGED
|
@@ -6,7 +6,7 @@ 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 "../
|
|
9
|
+
import { ModuleConfig } from "../types";
|
|
10
10
|
import { Binding } from "../types";
|
|
11
11
|
|
|
12
12
|
/** Generate the pepr-system namespace */
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { genEnv } from "../pods";
|
|
2
|
-
import { ModuleConfig } from "../../
|
|
2
|
+
import { ModuleConfig } from "../../types";
|
|
3
3
|
import { CapabilityExport } from "../../types";
|
|
4
4
|
import { dumpYaml } from "@kubernetes/client-node";
|
|
5
5
|
import { clusterRole } from "../rbac";
|
|
@@ -9,7 +9,8 @@ import { Capability } from "../core/capability";
|
|
|
9
9
|
import { MutateResponse, ValidateResponse } from "../k8s";
|
|
10
10
|
import Log from "../telemetry/logger";
|
|
11
11
|
import { metricsCollector, MetricsCollector } from "../telemetry/metrics";
|
|
12
|
-
import {
|
|
12
|
+
import { isWatchMode } from "../core/envChecks";
|
|
13
|
+
import { ModuleConfig } from "../types";
|
|
13
14
|
import { mutateProcessor } from "../processors/mutate-processor";
|
|
14
15
|
import { validateProcessor } from "../processors/validate-processor";
|
|
15
16
|
import { StoreController } from "./store";
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import { GenericClass, GroupVersionKind, modelToGroupVersionKind } from "kubernetes-fluent-client";
|
|
5
5
|
import { pickBy } from "ramda";
|
|
6
6
|
import Log from "../telemetry/logger";
|
|
7
|
-
import { isBuildMode, isDevMode, isWatchMode } from "./
|
|
7
|
+
import { isBuildMode, isDevMode, isWatchMode } from "./envChecks";
|
|
8
8
|
import { PeprStore, Storage } from "./storage";
|
|
9
9
|
import { OnSchedule, Schedule } from "./schedule";
|
|
10
10
|
import { Event } from "../enums";
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export const isWatchMode = (): boolean => process.env.PEPR_WATCH_MODE === "true";
|
|
2
|
+
// Track if Pepr is running in build mode
|
|
3
|
+
|
|
4
|
+
export const isBuildMode = (): boolean => process.env.PEPR_MODE === "build";
|
|
5
|
+
|
|
6
|
+
export const isDevMode = (): boolean => process.env.PEPR_MODE === "dev";
|
package/src/lib/core/module.ts
CHANGED
|
@@ -4,71 +4,12 @@ import { clone } from "ramda";
|
|
|
4
4
|
import { Capability } from "./capability";
|
|
5
5
|
import { Controller, ControllerHooks } from "../controller";
|
|
6
6
|
import { ValidateError } from "../errors";
|
|
7
|
-
import {
|
|
8
|
-
import { CapabilityExport, AdmissionRequest } from "../types";
|
|
7
|
+
import { CapabilityExport } from "../types";
|
|
9
8
|
import { setupWatch } from "../processors/watch-processor";
|
|
10
9
|
import { Log } from "../../lib";
|
|
11
|
-
import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
|
|
12
10
|
import { resolveIgnoreNamespaces } from "../assets/webhooks";
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
export type CustomLabels = { namespace: Record<string, string> } | Record<string, never>;
|
|
17
|
-
|
|
18
|
-
/** Configuration that MAY be set a Pepr module's package.json. */
|
|
19
|
-
export type ModuleConfigOptions = {
|
|
20
|
-
/** The Pepr version this module uses */
|
|
21
|
-
peprVersion: string;
|
|
22
|
-
/** The user-defined version of the module */
|
|
23
|
-
appVersion: string;
|
|
24
|
-
/** A description of the Pepr module and what it does. */
|
|
25
|
-
description: string;
|
|
26
|
-
/** The webhookTimeout */
|
|
27
|
-
webhookTimeout: number;
|
|
28
|
-
/** Reject K8s resource AdmissionRequests on error. */
|
|
29
|
-
onError: string;
|
|
30
|
-
/** Define the log level for the in-cluster controllers */
|
|
31
|
-
logLevel: string;
|
|
32
|
-
/** Propagate env variables to in-cluster controllers */
|
|
33
|
-
env: Record<string, string>;
|
|
34
|
-
/** Custom RBAC rules */
|
|
35
|
-
rbac: PolicyRule[];
|
|
36
|
-
/** The RBAC mode; if "scoped", generates scoped rules, otherwise uses wildcard rules. */
|
|
37
|
-
rbacMode: string;
|
|
38
|
-
/** Custom Labels for Kubernetes Objects */
|
|
39
|
-
customLabels: CustomLabels;
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
/** Global configuration for the Pepr runtime. */
|
|
43
|
-
export type ModuleConfig = {
|
|
44
|
-
/** A unique identifier for this Pepr module. This is automatically generated by Pepr. */
|
|
45
|
-
uuid: string;
|
|
46
|
-
/** Configure global exclusions that will never be processed by Pepr. */
|
|
47
|
-
alwaysIgnore: WebhookIgnore;
|
|
48
|
-
} & Partial<ModuleConfigOptions>;
|
|
49
|
-
|
|
50
|
-
export type PackageJSON = {
|
|
51
|
-
description: string;
|
|
52
|
-
pepr: ModuleConfig;
|
|
53
|
-
};
|
|
54
|
-
|
|
55
|
-
export type PeprModuleOptions = {
|
|
56
|
-
deferStart?: boolean;
|
|
57
|
-
|
|
58
|
-
/** A user-defined callback to pre-process or intercept a Pepr request from K8s immediately before it is processed */
|
|
59
|
-
beforeHook?: (req: AdmissionRequest) => void;
|
|
60
|
-
|
|
61
|
-
/** A user-defined callback to post-process or intercept a Pepr response just before it is returned to K8s */
|
|
62
|
-
afterHook?: (res: MutateResponse | ValidateResponse) => void;
|
|
63
|
-
};
|
|
64
|
-
|
|
65
|
-
// Track if this is a watch mode controller
|
|
66
|
-
export const isWatchMode = (): boolean => process.env.PEPR_WATCH_MODE === "true";
|
|
67
|
-
|
|
68
|
-
// Track if Pepr is running in build mode
|
|
69
|
-
export const isBuildMode = (): boolean => process.env.PEPR_MODE === "build";
|
|
70
|
-
|
|
71
|
-
export const isDevMode = (): boolean => process.env.PEPR_MODE === "dev";
|
|
11
|
+
import { isBuildMode, isDevMode, isWatchMode } from "./envChecks";
|
|
12
|
+
import { PackageJSON, PeprModuleOptions, ModuleConfig } from "../types";
|
|
72
13
|
|
|
73
14
|
export class PeprModule {
|
|
74
15
|
#controller!: Controller;
|
|
@@ -10,7 +10,7 @@ import { shouldSkipRequest } from "../filter/filter";
|
|
|
10
10
|
import { MutateResponse } from "../k8s";
|
|
11
11
|
import { AdmissionRequest, Binding } from "../types";
|
|
12
12
|
import Log from "../telemetry/logger";
|
|
13
|
-
import { ModuleConfig } from "../
|
|
13
|
+
import { ModuleConfig } from "../types";
|
|
14
14
|
import { PeprMutateRequest } from "../mutate-request";
|
|
15
15
|
import { base64Encode, convertFromBase64Map, convertToBase64Map } from "../utils";
|
|
16
16
|
import { OnError } from "../../cli/init/enums";
|
|
@@ -9,7 +9,7 @@ import { AdmissionRequest, Binding } from "../types";
|
|
|
9
9
|
import Log from "../telemetry/logger";
|
|
10
10
|
import { convertFromBase64Map } from "../utils";
|
|
11
11
|
import { PeprValidateRequest } from "../validate-request";
|
|
12
|
-
import { ModuleConfig } from "../
|
|
12
|
+
import { ModuleConfig } from "../types";
|
|
13
13
|
import { resolveIgnoreNamespaces } from "../assets/webhooks";
|
|
14
14
|
import { MeasureWebhookTimeout } from "../telemetry/webhookTimeouts";
|
|
15
15
|
import { WebhookType } from "../enums";
|
|
@@ -4,11 +4,12 @@ import Log from "../telemetry/logger";
|
|
|
4
4
|
import { Binding } from "../types";
|
|
5
5
|
import { Capability } from "../core/capability";
|
|
6
6
|
import { Event } from "../enums";
|
|
7
|
-
import { K8s, KubernetesObject, WatchCfg, WatchEvent } from "kubernetes-fluent-client";
|
|
7
|
+
import { K8s, KubernetesObject, WatchCfg, WatchEvent, GenericClass } from "kubernetes-fluent-client";
|
|
8
8
|
import { Queue } from "../core/queue";
|
|
9
|
-
import { WatchPhase } from "kubernetes-fluent-client/dist/fluent/types";
|
|
9
|
+
import { WatchPhase, WatcherType } from "kubernetes-fluent-client/dist/fluent/types";
|
|
10
|
+
import { KubernetesListObject } from "kubernetes-fluent-client/dist/types";
|
|
10
11
|
import { filterNoMatchReason } from "../filter/filter";
|
|
11
|
-
import { metricsCollector } from "../telemetry/metrics";
|
|
12
|
+
import { metricsCollector, MetricsCollectorInstance } from "../telemetry/metrics";
|
|
12
13
|
import { removeFinalizer } from "../finalizer";
|
|
13
14
|
|
|
14
15
|
// stores Queue instances
|
|
@@ -157,36 +158,8 @@ async function runBinding(
|
|
|
157
158
|
}
|
|
158
159
|
}, watchCfg);
|
|
159
160
|
|
|
160
|
-
//
|
|
161
|
-
watcher
|
|
162
|
-
Log.error(err, "Watch failed after 5 attempts, giving up");
|
|
163
|
-
process.exit(1);
|
|
164
|
-
});
|
|
165
|
-
|
|
166
|
-
watcher.events.on(WatchEvent.CONNECT, url => logEvent(WatchEvent.CONNECT, url));
|
|
167
|
-
|
|
168
|
-
watcher.events.on(WatchEvent.DATA_ERROR, err => logEvent(WatchEvent.DATA_ERROR, err.message));
|
|
169
|
-
watcher.events.on(WatchEvent.RECONNECT, retryCount =>
|
|
170
|
-
logEvent(WatchEvent.RECONNECT, `Reconnecting after ${retryCount} attempt${retryCount === 1 ? "" : "s"}`),
|
|
171
|
-
);
|
|
172
|
-
watcher.events.on(WatchEvent.RECONNECT_PENDING, () => logEvent(WatchEvent.RECONNECT_PENDING));
|
|
173
|
-
watcher.events.on(WatchEvent.GIVE_UP, err => logEvent(WatchEvent.GIVE_UP, err.message));
|
|
174
|
-
watcher.events.on(WatchEvent.ABORT, err => logEvent(WatchEvent.ABORT, err.message));
|
|
175
|
-
watcher.events.on(WatchEvent.OLD_RESOURCE_VERSION, err => logEvent(WatchEvent.OLD_RESOURCE_VERSION, err));
|
|
176
|
-
watcher.events.on(WatchEvent.NETWORK_ERROR, err => logEvent(WatchEvent.NETWORK_ERROR, err.message));
|
|
177
|
-
watcher.events.on(WatchEvent.LIST_ERROR, err => logEvent(WatchEvent.LIST_ERROR, err.message));
|
|
178
|
-
watcher.events.on(WatchEvent.LIST, list => logEvent(WatchEvent.LIST, JSON.stringify(list, undefined, 2)));
|
|
179
|
-
watcher.events.on(WatchEvent.CACHE_MISS, windowName => {
|
|
180
|
-
metricsCollector.incCacheMiss(windowName);
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
watcher.events.on(WatchEvent.INIT_CACHE_MISS, windowName => {
|
|
184
|
-
metricsCollector.initCacheMissWindow(windowName);
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
watcher.events.on(WatchEvent.INC_RESYNC_FAILURE_COUNT, retryCount => {
|
|
188
|
-
metricsCollector.incRetryCount(retryCount);
|
|
189
|
-
});
|
|
161
|
+
// Register event handlers
|
|
162
|
+
registerWatchEventHandlers(watcher, logEvent, metricsCollector);
|
|
190
163
|
|
|
191
164
|
// Start the watch
|
|
192
165
|
try {
|
|
@@ -205,3 +178,55 @@ export function logEvent(event: WatchEvent, message: string = "", obj?: Kubernet
|
|
|
205
178
|
Log.debug(logMessage);
|
|
206
179
|
}
|
|
207
180
|
}
|
|
181
|
+
|
|
182
|
+
export type WatchEventArgs<K extends WatchEvent, T extends GenericClass> = {
|
|
183
|
+
[WatchEvent.LIST]: KubernetesListObject<InstanceType<T>>;
|
|
184
|
+
[WatchEvent.RECONNECT]: number;
|
|
185
|
+
[WatchEvent.CACHE_MISS]: string;
|
|
186
|
+
[WatchEvent.INIT_CACHE_MISS]: string;
|
|
187
|
+
[WatchEvent.GIVE_UP]: Error;
|
|
188
|
+
[WatchEvent.ABORT]: Error;
|
|
189
|
+
[WatchEvent.OLD_RESOURCE_VERSION]: string;
|
|
190
|
+
[WatchEvent.NETWORK_ERROR]: Error;
|
|
191
|
+
[WatchEvent.LIST_ERROR]: Error;
|
|
192
|
+
[WatchEvent.DATA_ERROR]: Error;
|
|
193
|
+
[WatchEvent.CONNECT]: string;
|
|
194
|
+
[WatchEvent.RECONNECT_PENDING]: undefined;
|
|
195
|
+
[WatchEvent.DATA]: undefined;
|
|
196
|
+
[WatchEvent.INC_RESYNC_FAILURE_COUNT]: number;
|
|
197
|
+
}[K];
|
|
198
|
+
|
|
199
|
+
export type LogEventFunction = (event: WatchEvent, message?: string) => void;
|
|
200
|
+
export function registerWatchEventHandlers(
|
|
201
|
+
watcher: WatcherType<GenericClass>,
|
|
202
|
+
logEvent: LogEventFunction,
|
|
203
|
+
metricsCollector: MetricsCollectorInstance,
|
|
204
|
+
): void {
|
|
205
|
+
const eventHandlers: {
|
|
206
|
+
[K in WatchEvent]?: (arg: WatchEventArgs<K, GenericClass>) => void;
|
|
207
|
+
} = {
|
|
208
|
+
[WatchEvent.DATA]: () => null,
|
|
209
|
+
[WatchEvent.GIVE_UP]: err => {
|
|
210
|
+
// If failure continues, log and exit
|
|
211
|
+
logEvent(WatchEvent.GIVE_UP, err.message);
|
|
212
|
+
process.exit(1);
|
|
213
|
+
},
|
|
214
|
+
[WatchEvent.CONNECT]: url => logEvent(WatchEvent.CONNECT, url),
|
|
215
|
+
[WatchEvent.DATA_ERROR]: err => logEvent(WatchEvent.DATA_ERROR, err.message),
|
|
216
|
+
[WatchEvent.RECONNECT]: retryCount =>
|
|
217
|
+
logEvent(WatchEvent.RECONNECT, `Reconnecting after ${retryCount} attempt${retryCount === 1 ? "" : "s"}`),
|
|
218
|
+
[WatchEvent.RECONNECT_PENDING]: () => logEvent(WatchEvent.RECONNECT_PENDING),
|
|
219
|
+
[WatchEvent.ABORT]: err => logEvent(WatchEvent.ABORT, err.message),
|
|
220
|
+
[WatchEvent.OLD_RESOURCE_VERSION]: errMessage => logEvent(WatchEvent.OLD_RESOURCE_VERSION, errMessage),
|
|
221
|
+
[WatchEvent.NETWORK_ERROR]: err => logEvent(WatchEvent.NETWORK_ERROR, err.message),
|
|
222
|
+
[WatchEvent.LIST_ERROR]: err => logEvent(WatchEvent.LIST_ERROR, err.message),
|
|
223
|
+
[WatchEvent.LIST]: list => logEvent(WatchEvent.LIST, JSON.stringify(list, undefined, 2)),
|
|
224
|
+
[WatchEvent.CACHE_MISS]: windowName => metricsCollector.incCacheMiss(windowName),
|
|
225
|
+
[WatchEvent.INIT_CACHE_MISS]: windowName => metricsCollector.initCacheMissWindow(windowName),
|
|
226
|
+
[WatchEvent.INC_RESYNC_FAILURE_COUNT]: retryCount => metricsCollector.incRetryCount(retryCount),
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
Object.entries(eventHandlers).forEach(([event, handler]) => {
|
|
230
|
+
watcher.events.on(event, handler);
|
|
231
|
+
});
|
|
232
|
+
}
|
|
@@ -9,7 +9,7 @@ import Log from "./logger";
|
|
|
9
9
|
|
|
10
10
|
const loggingPrefix = "MetricsCollector";
|
|
11
11
|
|
|
12
|
-
type MetricsCollectorInstance = InstanceType<typeof MetricsCollector>;
|
|
12
|
+
export type MetricsCollectorInstance = InstanceType<typeof MetricsCollector>;
|
|
13
13
|
interface MetricNames {
|
|
14
14
|
errors: string;
|
|
15
15
|
alerts: string;
|
|
@@ -148,8 +148,8 @@ export class MetricsCollector {
|
|
|
148
148
|
* Increments the retry count gauge.
|
|
149
149
|
* @param count - The count to increment by.
|
|
150
150
|
*/
|
|
151
|
-
incRetryCount = (count:
|
|
152
|
-
this.incGauge(this.#metricNames.resyncFailureCount, { count });
|
|
151
|
+
incRetryCount = (count: number): void => {
|
|
152
|
+
this.incGauge(this.#metricNames.resyncFailureCount, { count: count.toString() });
|
|
153
153
|
};
|
|
154
154
|
|
|
155
155
|
/**
|
package/src/lib/types.ts
CHANGED
|
@@ -8,6 +8,7 @@ import { Logger } from "pino";
|
|
|
8
8
|
import { PeprMutateRequest } from "./mutate-request";
|
|
9
9
|
import { PeprValidateRequest } from "./validate-request";
|
|
10
10
|
import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
|
|
11
|
+
import { WebhookIgnore, MutateResponse, ValidateResponse } from "./k8s";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Specifically for deploying images with a private registry
|
|
@@ -356,4 +357,51 @@ export interface GroupVersionResource {
|
|
|
356
357
|
// DeepPartial utility type for deep optional properties
|
|
357
358
|
export type DeepPartial<T> = {
|
|
358
359
|
[P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
|
|
360
|
+
}; /** Custom Labels Type for package.json */
|
|
361
|
+
|
|
362
|
+
export type CustomLabels = { namespace: Record<string, string> } | Record<string, never>;
|
|
363
|
+
/** Configuration that MAY be set a Pepr module's package.json. */
|
|
364
|
+
export type ModuleConfigOptions = {
|
|
365
|
+
/** The Pepr version this module uses */
|
|
366
|
+
peprVersion: string;
|
|
367
|
+
/** The user-defined version of the module */
|
|
368
|
+
appVersion: string;
|
|
369
|
+
/** A description of the Pepr module and what it does. */
|
|
370
|
+
description: string;
|
|
371
|
+
/** The webhookTimeout */
|
|
372
|
+
webhookTimeout: number;
|
|
373
|
+
/** Reject K8s resource AdmissionRequests on error. */
|
|
374
|
+
onError: string;
|
|
375
|
+
/** Define the log level for the in-cluster controllers */
|
|
376
|
+
logLevel: string;
|
|
377
|
+
/** Propagate env variables to in-cluster controllers */
|
|
378
|
+
env: Record<string, string>;
|
|
379
|
+
/** Custom RBAC rules */
|
|
380
|
+
rbac: PolicyRule[];
|
|
381
|
+
/** The RBAC mode; if "scoped", generates scoped rules, otherwise uses wildcard rules. */
|
|
382
|
+
rbacMode: string;
|
|
383
|
+
/** Custom Labels for Kubernetes Objects */
|
|
384
|
+
customLabels: CustomLabels;
|
|
385
|
+
};
|
|
386
|
+
/** Global configuration for the Pepr runtime. */
|
|
387
|
+
export type ModuleConfig = {
|
|
388
|
+
/** A unique identifier for this Pepr module. This is automatically generated by Pepr. */
|
|
389
|
+
uuid: string;
|
|
390
|
+
/** Configure global exclusions that will never be processed by Pepr. */
|
|
391
|
+
alwaysIgnore: WebhookIgnore;
|
|
392
|
+
} & Partial<ModuleConfigOptions>;
|
|
393
|
+
|
|
394
|
+
export type PackageJSON = {
|
|
395
|
+
description: string;
|
|
396
|
+
pepr: ModuleConfig;
|
|
359
397
|
};
|
|
398
|
+
|
|
399
|
+
export type PeprModuleOptions = {
|
|
400
|
+
deferStart?: boolean;
|
|
401
|
+
|
|
402
|
+
/** A user-defined callback to pre-process or intercept a Pepr request from K8s immediately before it is processed */
|
|
403
|
+
beforeHook?: (req: AdmissionRequest) => void;
|
|
404
|
+
|
|
405
|
+
/** A user-defined callback to post-process or intercept a Pepr response just before it is returned to K8s */
|
|
406
|
+
afterHook?: (res: MutateResponse | ValidateResponse) => void;
|
|
407
|
+
}; // Track if this is a watch mode controller
|
package/src/sdk/sdk.ts
CHANGED
|
@@ -46,11 +46,15 @@ export function containers(
|
|
|
46
46
|
export async function writeEvent(
|
|
47
47
|
cr: GenericKind,
|
|
48
48
|
event: Partial<kind.CoreEvent>,
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
49
|
+
options: {
|
|
50
|
+
eventType: string;
|
|
51
|
+
eventReason: string;
|
|
52
|
+
reportingComponent: string;
|
|
53
|
+
reportingInstance: string;
|
|
54
|
+
},
|
|
53
55
|
): Promise<void> {
|
|
56
|
+
const { eventType, eventReason, reportingComponent, reportingInstance } = options;
|
|
57
|
+
|
|
54
58
|
await K8s(kind.CoreEvent).Create({
|
|
55
59
|
type: eventType,
|
|
56
60
|
reason: eventReason,
|