pepr 0.44.0 → 0.45.0-nightly.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/build.d.ts +3 -3
  3. package/dist/cli/build.d.ts.map +1 -1
  4. package/dist/cli/build.helpers.d.ts +13 -7
  5. package/dist/cli/build.helpers.d.ts.map +1 -1
  6. package/dist/cli/deploy.d.ts.map +1 -1
  7. package/dist/cli/init/templates.d.ts +7 -8
  8. package/dist/cli/init/templates.d.ts.map +1 -1
  9. package/dist/cli.js +120 -100
  10. package/dist/controller.js +1 -1
  11. package/dist/lib/assets/assets.d.ts +2 -2
  12. package/dist/lib/assets/assets.d.ts.map +1 -1
  13. package/dist/lib/assets/index.d.ts +1 -1
  14. package/dist/lib/assets/index.d.ts.map +1 -1
  15. package/dist/lib/assets/pods.d.ts +1 -1
  16. package/dist/lib/assets/pods.d.ts.map +1 -1
  17. package/dist/lib/assets/rbac.d.ts.map +1 -1
  18. package/dist/lib/assets/webhooks.d.ts +2 -0
  19. package/dist/lib/assets/webhooks.d.ts.map +1 -1
  20. package/dist/lib/assets/yaml/overridesFile.d.ts +2 -4
  21. package/dist/lib/assets/yaml/overridesFile.d.ts.map +1 -1
  22. package/dist/lib/controller/index.d.ts +7 -2
  23. package/dist/lib/controller/index.d.ts.map +1 -1
  24. package/dist/lib/core/envChecks.d.ts +4 -0
  25. package/dist/lib/core/envChecks.d.ts.map +1 -0
  26. package/dist/lib/core/module.d.ts +1 -48
  27. package/dist/lib/core/module.d.ts.map +1 -1
  28. package/dist/lib/core/storage.d.ts.map +1 -1
  29. package/dist/lib/processors/mutate-processor.d.ts +1 -1
  30. package/dist/lib/processors/mutate-processor.d.ts.map +1 -1
  31. package/dist/lib/processors/validate-processor.d.ts +1 -1
  32. package/dist/lib/processors/validate-processor.d.ts.map +1 -1
  33. package/dist/lib/processors/watch-processor.d.ts.map +1 -1
  34. package/dist/lib/telemetry/metrics.d.ts.map +1 -1
  35. package/dist/lib/types.d.ts +45 -0
  36. package/dist/lib/types.d.ts.map +1 -1
  37. package/dist/lib.js +2008 -1990
  38. package/dist/lib.js.map +4 -4
  39. package/package.json +16 -13
  40. package/src/cli/build.helpers.ts +28 -13
  41. package/src/cli/build.ts +65 -65
  42. package/src/cli/deploy.ts +32 -26
  43. package/src/cli/init/index.ts +2 -2
  44. package/src/cli/init/templates.ts +6 -5
  45. package/src/cli/init/walkthrough.ts +1 -1
  46. package/src/lib/assets/assets.ts +2 -2
  47. package/src/lib/assets/index.ts +1 -2
  48. package/src/lib/assets/pods.ts +1 -1
  49. package/src/lib/assets/rbac.ts +1 -2
  50. package/src/lib/assets/webhooks.ts +1 -1
  51. package/src/lib/assets/yaml/overridesFile.ts +4 -6
  52. package/src/lib/controller/index.ts +19 -11
  53. package/src/lib/core/capability.ts +1 -1
  54. package/src/lib/core/envChecks.ts +6 -0
  55. package/src/lib/core/module.ts +20 -69
  56. package/src/lib/core/schedule.ts +2 -2
  57. package/src/lib/core/storage.ts +2 -1
  58. package/src/lib/processors/mutate-processor.ts +2 -2
  59. package/src/lib/processors/validate-processor.ts +1 -1
  60. package/src/lib/processors/watch-processor.ts +5 -3
  61. package/src/lib/telemetry/metrics.ts +4 -6
  62. package/src/lib/types.ts +48 -0
  63. package/src/sdk/heredoc.ts +2 -2
package/package.json CHANGED
@@ -15,27 +15,26 @@
15
15
  "!src/**/*.test.ts",
16
16
  "!dist/**/*.test.d.ts*"
17
17
  ],
18
- "version": "0.44.0",
18
+ "version": "0.45.0-nightly.1",
19
19
  "main": "dist/lib.js",
20
20
  "types": "dist/lib.d.ts",
21
21
  "scripts": {
22
22
  "ci": "npm ci",
23
23
  "gen-data-json": "node hack/build-template-data.js",
24
24
  "prebuild": "rm -fr dist/* && npm run gen-data-json",
25
- "version": "node scripts/set-version.js",
26
25
  "build": "tsc && node build.mjs && npm pack",
27
26
  "build:image": "npm run build && docker buildx build --output type=docker --tag pepr:dev .",
27
+ "set:version": "node scripts/set-version.js",
28
28
  "test": "npm run test:unit && npm run test:journey",
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:prep && npm run test:journey:upgrade",
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",
@@ -57,8 +56,8 @@
57
56
  "sigstore": "3.0.0"
58
57
  },
59
58
  "devDependencies": {
60
- "@commitlint/cli": "19.6.1",
61
- "@commitlint/config-conventional": "19.6.0",
59
+ "@commitlint/cli": "19.7.1",
60
+ "@commitlint/config-conventional": "19.7.1",
62
61
  "@fast-check/jest": "^2.0.1",
63
62
  "@jest/globals": "29.7.0",
64
63
  "@types/eslint": "9.6.1",
@@ -72,20 +71,24 @@
72
71
  "husky": "^9.1.6",
73
72
  "jest": "29.7.0",
74
73
  "js-yaml": "^4.1.0",
74
+ "shellcheck": "^3.0.0",
75
75
  "ts-jest": "29.2.5",
76
76
  "undici": "^7.0.1"
77
77
  },
78
+ "overrides": {
79
+ "glob": "^9.0.0"
80
+ },
78
81
  "peerDependencies": {
79
- "@typescript-eslint/eslint-plugin": "7.18.0",
80
- "@typescript-eslint/parser": "7.18.0",
81
82
  "@types/prompts": "2.4.9",
83
+ "@typescript-eslint/eslint-plugin": "8.23.0",
84
+ "@typescript-eslint/parser": "8.23.0",
85
+ "commander": "13.1.0",
86
+ "esbuild": "0.24.2",
82
87
  "eslint": "8.57.0",
83
- "commander": "12.1.0",
84
- "esbuild": "0.24.0",
85
88
  "node-forge": "1.3.1",
86
89
  "prettier": "3.4.2",
87
90
  "prompts": "2.4.2",
88
- "typescript": "^5.3.3",
89
- "uuid": "11.0.3"
91
+ "typescript": "5.7.3",
92
+ "uuid": "11.0.5"
90
93
  }
91
- }
94
+ }
@@ -12,6 +12,34 @@ 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
14
 
15
+ interface ImageOptions {
16
+ customImage?: string;
17
+ registryInfo?: string;
18
+ peprVersion?: string;
19
+ registry?: string;
20
+ }
21
+ /**
22
+ * Assign image string
23
+ * @param imageOptions CLI options for image
24
+ * @returns image string
25
+ */
26
+ export function assignImage(imageOptions: ImageOptions): string {
27
+ const { customImage, registryInfo, peprVersion, registry } = imageOptions;
28
+ if (customImage) {
29
+ return customImage;
30
+ }
31
+
32
+ if (registryInfo) {
33
+ return `${registryInfo}/custom-pepr-controller:${peprVersion}`;
34
+ }
35
+
36
+ if (registry) {
37
+ return checkIronBankImage(registry, "", peprVersion!);
38
+ }
39
+
40
+ return "";
41
+ }
42
+
15
43
  export type Reloader = (opts: BuildResult<BuildOptions>) => void | Promise<void>;
16
44
  /**
17
45
  * Determine the RBAC mode based on the CLI options and the module's config
@@ -114,19 +142,6 @@ export async function handleCustomImageBuild(
114
142
  }
115
143
  }
116
144
 
117
- /**
118
- * Disables embedding of deployment files into output module
119
- * @param embed
120
- * @param path
121
- * @returns
122
- */
123
- export function handleEmbedding(embed: boolean, path: string): void {
124
- if (!embed) {
125
- console.info(`✅ Module built successfully at ${path}`);
126
- return;
127
- }
128
- }
129
-
130
145
  /**
131
146
  * Check if the capability names are valid
132
147
  * @param capabilities The capabilities to check
package/src/cli/build.ts CHANGED
@@ -11,23 +11,21 @@ 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/types";
14
15
  import {
15
16
  watchForChanges,
16
17
  determineRbacMode,
17
- handleEmbedding,
18
+ assignImage,
18
19
  handleCustomOutputDir,
19
20
  handleValidCapabilityNames,
20
21
  handleCustomImageBuild,
21
- checkIronBankImage,
22
22
  validImagePullSecret,
23
23
  generateYamlAndWriteToDisk,
24
24
  } from "./build.helpers";
25
- import { ModuleConfig } from "../lib/core/module";
26
25
 
27
26
  const peprTS = "pepr.ts";
28
27
  let outputDir: string = "dist";
29
28
  export type Reloader = (opts: BuildResult<BuildOptions>) => void | Promise<void>;
30
-
31
29
  export type PeprNestedFields = Pick<
32
30
  ModuleConfig,
33
31
  | "uuid"
@@ -64,7 +62,7 @@ type BuildModuleReturn = {
64
62
  path: string;
65
63
  cfg: PeprConfig;
66
64
  uuid: string;
67
- } | void;
65
+ };
68
66
 
69
67
  export default function (program: RootCmd): void {
70
68
  program
@@ -97,7 +95,7 @@ export default function (program: RootCmd): void {
97
95
  .addOption(
98
96
  new Option(
99
97
  "-v, --version <version>",
100
- "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'.",
101
99
  ).conflicts(["customImage", "registryInfo"]),
102
100
  )
103
101
  .option(
@@ -134,68 +132,70 @@ export default function (program: RootCmd): void {
134
132
 
135
133
  // Build the module
136
134
  const buildModuleResult = await buildModule(undefined, opts.entryPoint, opts.embed);
137
- if (buildModuleResult?.cfg && buildModuleResult.path && buildModuleResult.uuid) {
138
- const { cfg, path, uuid } = buildModuleResult;
139
- // Files to include in controller image for WASM support
140
- const { includedFiles } = cfg.pepr;
141
-
142
- let image = opts.customImage || "";
143
-
144
- // Check if there is a custom timeout defined
145
- if (opts.timeout !== undefined) {
146
- cfg.pepr.webhookTimeout = opts.timeout;
147
- }
148
-
149
- if (opts.registryInfo !== undefined) {
150
- console.info(`Including ${includedFiles.length} files in controller image.`);
151
-
152
- // for journey test to make sure the image is built
153
- image = `${opts.registryInfo}/custom-pepr-controller:${cfg.pepr.peprVersion}`;
154
-
155
- // only actually build/push if there are files to include
156
- await handleCustomImageBuild(includedFiles, cfg.pepr.peprVersion, cfg.description, image);
157
- }
158
-
159
- // If building without embedding, exit after building
160
- handleEmbedding(opts.embed, path);
161
-
162
- // set the image version if provided
163
- opts.version ? (cfg.pepr.peprVersion = opts.version) : null;
164
-
165
- // Generate a secret for the module
166
- const assets = new Assets(
167
- {
168
- ...cfg.pepr,
169
- appVersion: cfg.version,
170
- description: cfg.description,
171
- alwaysIgnore: {
172
- namespaces: cfg.pepr.alwaysIgnore?.namespaces,
173
- },
174
- // Can override the rbacMode with the CLI option
175
- rbacMode: determineRbacMode(opts, cfg),
176
- },
177
- path,
178
- opts.withPullSecret === "" ? [] : [opts.withPullSecret],
179
- );
180
135
 
181
- // If registry is set to Iron Bank, use Iron Bank image
182
- image = checkIronBankImage(opts.registry, image, cfg.pepr.peprVersion);
136
+ const { cfg, path, uuid } = buildModuleResult!;
137
+ const image = assignImage({
138
+ customImage: opts.customImage,
139
+ registryInfo: opts.registryInfo,
140
+ peprVersion: cfg.pepr.peprVersion,
141
+ registry: opts.registry,
142
+ });
143
+
144
+ // Check if there is a custom timeout defined
145
+ if (opts.timeout !== undefined) {
146
+ cfg.pepr.webhookTimeout = opts.timeout;
147
+ }
183
148
 
184
- // if image is a custom image, use that instead of the default
185
- image !== "" ? (assets.image = image) : null;
149
+ if (opts.registryInfo !== undefined) {
150
+ console.info(`Including ${cfg.pepr.includedFiles.length} files in controller image.`);
151
+ // for journey test to make sure the image is built
186
152
 
187
- // Ensure imagePullSecret is valid
188
- validImagePullSecret(opts.withPullSecret);
153
+ // only actually build/push if there are files to include
154
+ await handleCustomImageBuild(
155
+ cfg.pepr.includedFiles,
156
+ cfg.pepr.peprVersion,
157
+ cfg.description,
158
+ image,
159
+ );
160
+ }
189
161
 
190
- handleValidCapabilityNames(assets.capabilities);
191
- await generateYamlAndWriteToDisk({
192
- uuid,
193
- outputDir,
194
- imagePullSecret: opts.withPullSecret,
195
- zarf: opts.zarf,
196
- assets,
197
- });
162
+ // If building without embedding, exit after building
163
+ if (!opts.embed) {
164
+ console.info(`✅ Module built successfully at ${path}`);
165
+ return;
198
166
  }
167
+ // set the image version if provided -- DEPRECATED
168
+ if (opts.version) cfg.pepr.peprVersion = opts.version;
169
+
170
+ // Generate a secret for the module
171
+ const assets = new Assets(
172
+ {
173
+ ...cfg.pepr,
174
+ appVersion: cfg.version,
175
+ description: cfg.description,
176
+ alwaysIgnore: {
177
+ namespaces: cfg.pepr.alwaysIgnore?.namespaces,
178
+ },
179
+ // Can override the rbacMode with the CLI option
180
+ rbacMode: determineRbacMode(opts, cfg),
181
+ },
182
+ path,
183
+ opts.withPullSecret === "" ? [] : [opts.withPullSecret],
184
+ );
185
+
186
+ if (image !== "") assets.image = image;
187
+
188
+ // Ensure imagePullSecret is valid
189
+ validImagePullSecret(opts.withPullSecret);
190
+
191
+ handleValidCapabilityNames(assets.capabilities);
192
+ await generateYamlAndWriteToDisk({
193
+ uuid,
194
+ outputDir,
195
+ imagePullSecret: opts.withPullSecret,
196
+ zarf: opts.zarf,
197
+ assets,
198
+ });
199
199
  });
200
200
  }
201
201
 
@@ -218,7 +218,7 @@ export async function loadModule(entryPoint = peprTS): Promise<LoadModuleReturn>
218
218
  try {
219
219
  await fs.access(cfgPath);
220
220
  await fs.access(entryPointPath);
221
- } catch (e) {
221
+ } catch {
222
222
  console.error(
223
223
  `Could not find ${cfgPath} or ${entryPointPath} in the current directory. Please run this command from the root of your module's directory.`,
224
224
  );
@@ -253,7 +253,7 @@ export async function buildModule(
253
253
  reloader?: Reloader,
254
254
  entryPoint = peprTS,
255
255
  embed = true,
256
- ): Promise<BuildModuleReturn> {
256
+ ): Promise<BuildModuleReturn | void> {
257
257
  try {
258
258
  const { cfg, modulePath, path, uuid } = await loadModule(entryPoint);
259
259
 
package/src/cli/deploy.ts CHANGED
@@ -93,6 +93,35 @@ export async function getUserConfirmation(opts: { confirm: boolean }): Promise<b
93
93
  return confirm.confirm ? true : false;
94
94
  }
95
95
 
96
+ async function buildAndDeployModule(image: string, force: boolean): Promise<void> {
97
+ const builtModule = await buildModule();
98
+ if (!builtModule) {
99
+ return;
100
+ }
101
+
102
+ // Generate a secret for the module
103
+ const webhook = new Assets(
104
+ { ...builtModule.cfg.pepr, description: builtModule.cfg.description },
105
+ builtModule.path,
106
+ [],
107
+ );
108
+ webhook.image = image ?? webhook.image;
109
+
110
+ try {
111
+ await webhook.deploy(deployWebhook, force, builtModule.cfg.pepr.webhookTimeout ?? 10);
112
+
113
+ // wait for capabilities to be loaded and test names
114
+ validateCapabilityNames(webhook.capabilities);
115
+
116
+ // Wait for the pepr-system resources to be fully up
117
+ await namespaceDeploymentsReady();
118
+ console.info(`✅ Module deployed successfully`);
119
+ } catch (e) {
120
+ console.error(`Error deploying module:`, e);
121
+ process.exit(1);
122
+ }
123
+ }
124
+
96
125
  export default function (program: RootCmd): void {
97
126
  program
98
127
  .command("deploy")
@@ -117,33 +146,10 @@ export default function (program: RootCmd): void {
117
146
  return;
118
147
  }
119
148
 
120
- (await getUserConfirmation(opts)) || process.exit(0);
121
-
122
- const builtModule = await buildModule();
123
- if (!builtModule) {
124
- return;
149
+ if (!(await getUserConfirmation(opts))) {
150
+ process.exit(0);
125
151
  }
126
152
 
127
- // Generate a secret for the module
128
- const webhook = new Assets(
129
- { ...builtModule.cfg.pepr, description: builtModule.cfg.description },
130
- builtModule.path,
131
- [],
132
- );
133
- webhook.image = opts.image ?? webhook.image;
134
-
135
- try {
136
- await webhook.deploy(deployWebhook, opts.force, builtModule.cfg.pepr.webhookTimeout ?? 10);
137
-
138
- // wait for capabilities to be loaded and test names
139
- validateCapabilityNames(webhook.capabilities);
140
-
141
- // Wait for the pepr-system resources to be fully up
142
- await namespaceDeploymentsReady();
143
- console.info(`✅ Module deployed successfully`);
144
- } catch (e) {
145
- console.error(`Error deploying module:`, e);
146
- process.exit(1);
147
- }
153
+ await buildAndDeployModule(opts.image, opts.force);
148
154
  });
149
155
  }
@@ -107,7 +107,7 @@ const doPostInitActions = (dirName: string): void => {
107
107
  execSync("code .", {
108
108
  stdio: "inherit",
109
109
  });
110
- } catch (e) {
111
- // vscode not found, do nothing
110
+ } catch {
111
+ console.warn("VSCode was not found, IDE will not automatically open.");
112
112
  }
113
113
  };
@@ -6,16 +6,17 @@ import { inspect } from "util";
6
6
  import { v4 as uuidv4, v5 as uuidv5 } from "uuid";
7
7
 
8
8
  import eslintJSON from "../../templates/.eslintrc.template.json";
9
+ import peprSnippetsJSON from "../../templates/pepr.code-snippets.json";
9
10
  import prettierJSON from "../../templates/.prettierrc.json";
10
11
  import samplesJSON from "../../templates/capabilities/hello-pepr.samples.json";
11
- import { gitIgnore, helloPeprTS, packageJSON, peprTS, readmeMd } from "../../templates/data.json";
12
- import peprSnippetsJSON from "../../templates/pepr.code-snippets.json";
13
12
  import settingsJSON from "../../templates/settings.json";
14
13
  import tsConfigJSON from "../../templates/tsconfig.module.json";
15
- import { sanitizeName } from "./utils";
14
+ import { CustomLabels } from "../../lib/types";
16
15
  import { InitOptions } from "../types";
17
- import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
18
16
  import { OnError, RbacMode } from "./enums";
17
+ import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
18
+ import { gitIgnore, helloPeprTS, packageJSON, peprTS, readmeMd } from "../../templates/data.json";
19
+ import { sanitizeName } from "./utils";
19
20
 
20
21
  export const { dependencies, devDependencies, peerDependencies, scripts, version } = packageJSON;
21
22
 
@@ -30,7 +31,7 @@ type peprPackageJSON = {
30
31
  uuid: string;
31
32
  onError: OnError;
32
33
  webhookTimeout: number;
33
- customLabels: { namespace: Record<string, string> };
34
+ customLabels: CustomLabels;
34
35
  alwaysIgnore: { namespaces: string[] };
35
36
  includedFiles: string[];
36
37
  env: object;
@@ -38,7 +38,7 @@ export async function setName(name?: string): Promise<Answers<string>> {
38
38
  await fs.access(name, fs.constants.F_OK);
39
39
 
40
40
  return "A directory with this name already exists";
41
- } catch (e) {
41
+ } catch {
42
42
  return val.length > 2 || "The name must be at least 3 characters long";
43
43
  }
44
44
  },
@@ -1,6 +1,6 @@
1
1
  import crypto from "crypto";
2
2
  import { CapabilityExport } from "../types";
3
- import { ModuleConfig } from "../core/module";
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
- assyts: Assets,
84
+ assets: Assets,
85
85
  deployments: { default: V1Deployment; watch: V1Deployment | null },
86
86
  ) => Promise<string>,
87
87
  imagePullSecret?: string,
@@ -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 "../core/module";
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,
@@ -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 "../core/module";
9
+ import { ModuleConfig } from "../types";
10
10
  import { Binding } from "../types";
11
11
 
12
12
  /** Generate the pepr-system namespace */
@@ -24,8 +24,7 @@ export function clusterRole(
24
24
  const rbacMap = createRBACMap(capabilities);
25
25
  // Generate scoped rules from rbacMap
26
26
  const scopedRules = Object.keys(rbacMap).map(key => {
27
- let group: string;
28
- key.split("/").length < 3 ? (group = "") : (group = key.split("/")[0]);
27
+ const group: string = key.split("/").length < 3 ? "" : key.split("/")[0];
29
28
 
30
29
  return {
31
30
  apiGroups: [group],
@@ -15,7 +15,7 @@ import { Binding } from "../types";
15
15
 
16
16
  export const peprIgnoreNamespaces: string[] = ["kube-system", "pepr-system"];
17
17
 
18
- const validateRule = (binding: Binding, isMutateWebhook: boolean): V1RuleWithOperations | undefined => {
18
+ export const validateRule = (binding: Binding, isMutateWebhook: boolean): V1RuleWithOperations | undefined => {
19
19
  const { event, kind, isMutate, isValidate } = binding;
20
20
 
21
21
  // Skip invalid bindings based on webhook type
@@ -1,21 +1,19 @@
1
1
  import { genEnv } from "../pods";
2
- import { ModuleConfig } from "../../core/module";
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";
6
6
  import { promises as fs } from "fs";
7
7
 
8
- type CommonOverrideValues = {
8
+ type ChartOverrides = {
9
9
  apiToken: string;
10
10
  capabilities: CapabilityExport[];
11
11
  config: ModuleConfig;
12
12
  hash: string;
13
13
  name: string;
14
- };
15
-
16
- type ChartOverrides = CommonOverrideValues & {
17
14
  image: string;
18
15
  };
16
+
19
17
  // Helm Chart overrides file (values.yaml) generated from assets
20
18
  export async function overridesFile(
21
19
  { hash, name, image, config, apiToken, capabilities }: ChartOverrides,
@@ -34,7 +32,7 @@ export async function overridesFile(
34
32
  hash,
35
33
  namespace: {
36
34
  annotations: {},
37
- labels: {
35
+ labels: config.customLabels?.namespace ?? {
38
36
  "pepr.dev": "",
39
37
  },
40
38
  },
@@ -9,13 +9,20 @@ 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 { ModuleConfig, isWatchMode } from "../core/module";
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";
16
17
  import { AdmissionRequest } from "../types";
17
18
  import { karForMutate, karForValidate, KubeAdmissionReview } from "./index.util";
18
19
 
20
+ export interface ControllerHooks {
21
+ beforeHook?: (req: AdmissionRequest) => void;
22
+ afterHook?: (res: MutateResponse | ValidateResponse) => void;
23
+ onReady?: () => void;
24
+ }
25
+
19
26
  if (!process.env.PEPR_NODE_WARNINGS) {
20
27
  process.removeAllListeners("warning");
21
28
  }
@@ -39,20 +46,17 @@ export class Controller {
39
46
  readonly #beforeHook?: (req: AdmissionRequest) => void;
40
47
  readonly #afterHook?: (res: MutateResponse | ValidateResponse) => void;
41
48
 
42
- constructor(
43
- config: ModuleConfig,
44
- capabilities: Capability[],
45
- beforeHook?: (req: AdmissionRequest) => void,
46
- afterHook?: (res: MutateResponse | ValidateResponse) => void,
47
- onReady?: () => void,
48
- ) {
49
+ constructor(config: ModuleConfig, capabilities: Capability[], hooks: ControllerHooks = {}) {
50
+ const { beforeHook, afterHook, onReady } = hooks;
49
51
  this.#config = config;
50
52
  this.#capabilities = capabilities;
51
53
 
52
54
  // Initialize the Pepr store for each capability
53
55
  new StoreController(capabilities, `pepr-${config.uuid}-store`, () => {
54
56
  this.#bindEndpoints();
55
- onReady && onReady();
57
+ if (typeof onReady === "function") {
58
+ onReady();
59
+ }
56
60
  Log.info("✅ Controller startup complete");
57
61
  // Initialize the schedule store for each capability
58
62
  new StoreController(capabilities, `pepr-${config.uuid}-schedule`, () => {
@@ -223,7 +227,9 @@ export class Controller {
223
227
  Log.debug({ ...reqMetadata, request }, "Incoming request body");
224
228
 
225
229
  // Run the before hook if it exists
226
- this.#beforeHook && this.#beforeHook(request || {});
230
+ if (typeof this.#beforeHook === "function") {
231
+ this.#beforeHook(request || {});
232
+ }
227
233
 
228
234
  // Process the request
229
235
  const response: MutateResponse | ValidateResponse[] =
@@ -233,7 +239,9 @@ export class Controller {
233
239
 
234
240
  // Run the after hook if it exists
235
241
  [response].flat().map(res => {
236
- this.#afterHook && this.#afterHook(res);
242
+ if (typeof this.#afterHook === "function") {
243
+ this.#afterHook(res);
244
+ }
237
245
  Log.info({ ...reqMetadata, res }, "Check response");
238
246
  });
239
247
 
@@ -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 "./module";
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";