pepr 0.42.0 → 0.42.2

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 (149) hide show
  1. package/dist/cli/build.d.ts +1 -0
  2. package/dist/cli/build.d.ts.map +1 -1
  3. package/dist/cli/build.helpers.d.ts +66 -0
  4. package/dist/cli/build.helpers.d.ts.map +1 -1
  5. package/dist/cli/deploy.d.ts +15 -0
  6. package/dist/cli/deploy.d.ts.map +1 -1
  7. package/dist/cli/dev.d.ts.map +1 -1
  8. package/dist/cli/format.d.ts.map +1 -1
  9. package/dist/cli/format.helpers.d.ts +3 -0
  10. package/dist/cli/format.helpers.d.ts.map +1 -0
  11. package/dist/cli/init/enums.d.ts +10 -0
  12. package/dist/cli/init/enums.d.ts.map +1 -0
  13. package/dist/cli/init/index.d.ts.map +1 -1
  14. package/dist/cli/init/templates.d.ts +15 -11
  15. package/dist/cli/init/templates.d.ts.map +1 -1
  16. package/dist/cli/init/utils.d.ts.map +1 -1
  17. package/dist/cli/init/walkthrough.d.ts +3 -2
  18. package/dist/cli/init/walkthrough.d.ts.map +1 -1
  19. package/dist/cli/kfc.d.ts.map +1 -1
  20. package/dist/cli/monitor.d.ts +23 -0
  21. package/dist/cli/monitor.d.ts.map +1 -1
  22. package/dist/cli/root.d.ts.map +1 -1
  23. package/dist/cli/update.d.ts.map +1 -1
  24. package/dist/cli/uuid.d.ts.map +1 -1
  25. package/dist/cli.js +483 -586
  26. package/dist/controller.js +1 -195
  27. package/dist/fixtures/loader.d.ts.map +1 -1
  28. package/dist/lib/assets/deploy.d.ts.map +1 -1
  29. package/dist/lib/assets/destroy.d.ts.map +1 -1
  30. package/dist/lib/assets/helm.d.ts +1 -1
  31. package/dist/lib/assets/helm.d.ts.map +1 -1
  32. package/dist/lib/assets/index.d.ts +1 -1
  33. package/dist/lib/assets/index.d.ts.map +1 -1
  34. package/dist/lib/assets/pods.d.ts +6 -22
  35. package/dist/lib/assets/pods.d.ts.map +1 -1
  36. package/dist/lib/assets/rbac.d.ts.map +1 -1
  37. package/dist/lib/assets/webhooks.d.ts.map +1 -1
  38. package/dist/lib/assets/yaml.d.ts.map +1 -1
  39. package/dist/lib/controller/index.d.ts +2 -2
  40. package/dist/lib/controller/index.d.ts.map +1 -1
  41. package/dist/lib/controller/store.d.ts +1 -2
  42. package/dist/lib/controller/store.d.ts.map +1 -1
  43. package/dist/lib/controller/storeCache.d.ts +2 -1
  44. package/dist/lib/controller/storeCache.d.ts.map +1 -1
  45. package/dist/lib/{capability.d.ts → core/capability.d.ts} +1 -1
  46. package/dist/lib/core/capability.d.ts.map +1 -0
  47. package/dist/lib/{module.d.ts → core/module.d.ts} +2 -2
  48. package/dist/lib/core/module.d.ts.map +1 -0
  49. package/dist/lib/core/queue.d.ts.map +1 -0
  50. package/dist/lib/{schedule.d.ts → core/schedule.d.ts} +0 -1
  51. package/dist/lib/core/schedule.d.ts.map +1 -0
  52. package/dist/lib/{storage.d.ts → core/storage.d.ts} +4 -4
  53. package/dist/lib/core/storage.d.ts.map +1 -0
  54. package/dist/lib/deploymentChecks.d.ts.map +1 -1
  55. package/dist/lib/errors.d.ts +0 -5
  56. package/dist/lib/errors.d.ts.map +1 -1
  57. package/dist/lib/filesystemService.d.ts.map +1 -1
  58. package/dist/lib/filter/adjudicators/adjudicators.d.ts +5 -4
  59. package/dist/lib/filter/adjudicators/adjudicators.d.ts.map +1 -1
  60. package/dist/lib/filter/filter.d.ts +33 -1
  61. package/dist/lib/filter/filter.d.ts.map +1 -1
  62. package/dist/lib/finalizer.d.ts.map +1 -1
  63. package/dist/lib/helpers.d.ts +4 -9
  64. package/dist/lib/helpers.d.ts.map +1 -1
  65. package/dist/lib/included-files.d.ts.map +1 -1
  66. package/dist/lib/mutate-request.d.ts +2 -2
  67. package/dist/lib/mutate-request.d.ts.map +1 -1
  68. package/dist/lib/processors/mutate-processor.d.ts +28 -0
  69. package/dist/lib/processors/mutate-processor.d.ts.map +1 -0
  70. package/dist/lib/processors/validate-processor.d.ts +9 -0
  71. package/dist/lib/processors/validate-processor.d.ts.map +1 -0
  72. package/dist/lib/{watch-processor.d.ts → processors/watch-processor.d.ts} +2 -2
  73. package/dist/lib/processors/watch-processor.d.ts.map +1 -0
  74. package/dist/lib/telemetry/logger.d.ts.map +1 -1
  75. package/dist/lib/telemetry/metrics.d.ts.map +1 -1
  76. package/dist/lib/utils.d.ts.map +1 -1
  77. package/dist/lib/validate-request.d.ts +2 -2
  78. package/dist/lib/validate-request.d.ts.map +1 -1
  79. package/dist/lib.d.ts +2 -2
  80. package/dist/lib.d.ts.map +1 -1
  81. package/dist/lib.js +508 -341
  82. package/dist/lib.js.map +4 -4
  83. package/dist/sdk/heredoc.d.ts.map +1 -1
  84. package/package.json +9 -9
  85. package/src/cli/build.helpers.ts +180 -0
  86. package/src/cli/build.ts +85 -133
  87. package/src/cli/deploy.ts +113 -74
  88. package/src/cli/dev.ts +2 -2
  89. package/src/cli/format.helpers.ts +27 -0
  90. package/src/cli/format.ts +4 -18
  91. package/src/cli/init/enums.ts +9 -0
  92. package/src/cli/init/index.ts +4 -3
  93. package/src/cli/init/templates.ts +30 -2
  94. package/src/cli/init/utils.ts +3 -3
  95. package/src/cli/init/walkthrough.ts +7 -8
  96. package/src/cli/kfc.ts +1 -1
  97. package/src/cli/monitor.ts +108 -65
  98. package/src/cli/root.ts +1 -1
  99. package/src/cli/update.ts +1 -1
  100. package/src/cli/uuid.ts +1 -1
  101. package/src/fixtures/loader.ts +2 -2
  102. package/src/lib/assets/deploy.ts +11 -11
  103. package/src/lib/assets/destroy.ts +1 -1
  104. package/src/lib/assets/helm.ts +6 -6
  105. package/src/lib/assets/index.ts +23 -23
  106. package/src/lib/assets/pods.ts +11 -6
  107. package/src/lib/assets/webhooks.ts +31 -46
  108. package/src/lib/assets/yaml.ts +12 -9
  109. package/src/lib/controller/index.ts +13 -11
  110. package/src/lib/controller/store.ts +25 -12
  111. package/src/lib/controller/storeCache.ts +16 -3
  112. package/src/lib/{capability.ts → core/capability.ts} +25 -14
  113. package/src/lib/{module.ts → core/module.ts} +10 -10
  114. package/src/lib/{queue.ts → core/queue.ts} +13 -5
  115. package/src/lib/{storage.ts → core/storage.ts} +33 -24
  116. package/src/lib/deploymentChecks.ts +2 -2
  117. package/src/lib/errors.ts +3 -8
  118. package/src/lib/filesystemService.ts +1 -1
  119. package/src/lib/filter/adjudicators/adjudicators.ts +40 -9
  120. package/src/lib/filter/filter.ts +204 -111
  121. package/src/lib/finalizer.ts +2 -2
  122. package/src/lib/helpers.ts +20 -133
  123. package/src/lib/included-files.ts +1 -1
  124. package/src/lib/mutate-request.ts +11 -11
  125. package/src/lib/processors/mutate-processor.ts +225 -0
  126. package/src/lib/processors/validate-processor.ts +93 -0
  127. package/src/lib/{watch-processor.ts → processors/watch-processor.ts} +19 -15
  128. package/src/lib/telemetry/logger.ts +3 -1
  129. package/src/lib/tls.ts +5 -1
  130. package/src/lib/utils.ts +5 -5
  131. package/src/lib/validate-request.ts +4 -4
  132. package/src/lib.ts +2 -2
  133. package/src/runtime/controller.ts +2 -2
  134. package/src/sdk/cosign.ts +4 -4
  135. package/src/sdk/heredoc.ts +1 -1
  136. package/dist/lib/capability.d.ts.map +0 -1
  137. package/dist/lib/module.d.ts.map +0 -1
  138. package/dist/lib/mutate-processor.d.ts +0 -6
  139. package/dist/lib/mutate-processor.d.ts.map +0 -1
  140. package/dist/lib/queue.d.ts.map +0 -1
  141. package/dist/lib/schedule.d.ts.map +0 -1
  142. package/dist/lib/storage.d.ts.map +0 -1
  143. package/dist/lib/validate-processor.d.ts +0 -6
  144. package/dist/lib/validate-processor.d.ts.map +0 -1
  145. package/dist/lib/watch-processor.d.ts.map +0 -1
  146. package/src/lib/mutate-processor.ts +0 -165
  147. package/src/lib/validate-processor.ts +0 -85
  148. /package/dist/lib/{queue.d.ts → core/queue.d.ts} +0 -0
  149. /package/src/lib/{schedule.ts → core/schedule.ts} +0 -0
package/src/cli/root.ts CHANGED
@@ -5,7 +5,7 @@ import { Command } from "commander";
5
5
 
6
6
  export class RootCmd extends Command {
7
7
  // eslint-disable-next-line class-methods-use-this
8
- createCommand(name: string) {
8
+ createCommand(name: string): Command {
9
9
  const cmd = new Command(name);
10
10
  return cmd;
11
11
  }
package/src/cli/update.ts CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  import { write } from "./init/utils";
18
18
  import { RootCmd } from "./root";
19
19
 
20
- export default function (program: RootCmd) {
20
+ export default function (program: RootCmd): void {
21
21
  program
22
22
  .command("update")
23
23
  .description("Update this Pepr module. Not recommended for prod as it may change files.")
package/src/cli/uuid.ts CHANGED
@@ -5,7 +5,7 @@ import { KubernetesListObject } from "@kubernetes/client-node";
5
5
  import { K8s, kind } from "kubernetes-fluent-client";
6
6
  import { RootCmd } from "./root";
7
7
 
8
- export default function (program: RootCmd) {
8
+ export default function (program: RootCmd): void {
9
9
  program
10
10
  .command("uuid [uuid]")
11
11
  .description("Module UUID(s) currently deployed in the cluster")
@@ -14,11 +14,11 @@ export function AdmissionRequestCreatePod() {
14
14
  return cloneObject<kind.Pod>(admissionRequestCreatePod);
15
15
  }
16
16
 
17
- export function AdmissionRequestDeletePod() {
17
+ export function AdmissionRequestDeletePod(): AdmissionRequest<kind.Pod> {
18
18
  return cloneObject<kind.Pod>(admissionRequestDeletePod);
19
19
  }
20
20
 
21
- export function AdmissionRequestCreateClusterRole() {
21
+ export function AdmissionRequestCreateClusterRole(): AdmissionRequest<kind.ClusterRole> {
22
22
  return cloneObject<kind.ClusterRole>(admissionRequestCreateClusterRole);
23
23
  }
24
24
 
@@ -9,17 +9,17 @@ import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
9
9
  import { Assets } from ".";
10
10
  import Log from "../telemetry/logger";
11
11
  import { apiTokenSecret, service, tlsSecret, watcherService } from "./networking";
12
- import { deployment, moduleSecret, namespace, watcher } from "./pods";
12
+ import { getDeployment, getModuleSecret, getNamespace, getWatcher } from "./pods";
13
13
  import { clusterRole, clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "./rbac";
14
14
  import { peprStoreCRD } from "./store";
15
15
  import { webhookConfig } from "./webhooks";
16
16
  import { CapabilityExport, ImagePullSecret } from "../types";
17
17
 
18
- export async function deployImagePullSecret(imagePullSecret: ImagePullSecret, name: string) {
18
+ export async function deployImagePullSecret(imagePullSecret: ImagePullSecret, name: string): Promise<void> {
19
19
  try {
20
20
  await K8s(kind.Namespace).Get("pepr-system");
21
21
  } catch {
22
- await K8s(kind.Namespace).Apply(namespace());
22
+ await K8s(kind.Namespace).Apply(getNamespace());
23
23
  }
24
24
 
25
25
  try {
@@ -42,13 +42,13 @@ export async function deployImagePullSecret(imagePullSecret: ImagePullSecret, na
42
42
  Log.error(e);
43
43
  }
44
44
  }
45
- export async function deploy(assets: Assets, force: boolean, webhookTimeout?: number) {
45
+ export async function deploy(assets: Assets, force: boolean, webhookTimeout?: number): Promise<void> {
46
46
  Log.info("Establishing connection to Kubernetes");
47
47
 
48
48
  const { name, host, path } = assets;
49
49
 
50
50
  Log.info("Applying pepr-system namespace");
51
- await K8s(kind.Namespace).Apply(namespace(assets.config.customLabels?.namespace));
51
+ await K8s(kind.Namespace).Apply(getNamespace(assets.config.customLabels?.namespace));
52
52
 
53
53
  // Create the mutating webhook configuration if it is needed
54
54
  const mutateWebhook = await webhookConfig(assets, "mutate", webhookTimeout);
@@ -95,7 +95,7 @@ async function setupRBAC(
95
95
  capabilities: CapabilityExport[],
96
96
  force: boolean,
97
97
  config: { rbacMode?: string; rbac?: PolicyRule[] },
98
- ) {
98
+ ): Promise<void> {
99
99
  const { rbacMode, rbac } = config;
100
100
 
101
101
  Log.info("Applying cluster role binding");
@@ -119,11 +119,11 @@ async function setupRBAC(
119
119
  await K8s(kind.RoleBinding).Apply(roleBinding, { force });
120
120
  }
121
121
 
122
- async function setupController(assets: Assets, code: Buffer, hash: string, force: boolean) {
122
+ async function setupController(assets: Assets, code: Buffer, hash: string, force: boolean): Promise<void> {
123
123
  const { name } = assets;
124
124
 
125
125
  Log.info("Applying module secret");
126
- const mod = moduleSecret(name, code, hash);
126
+ const mod = getModuleSecret(name, code, hash);
127
127
  await K8s(kind.Secret).Apply(mod, { force });
128
128
 
129
129
  Log.info("Applying controller service");
@@ -139,14 +139,14 @@ async function setupController(assets: Assets, code: Buffer, hash: string, force
139
139
  await K8s(kind.Secret).Apply(apiToken, { force });
140
140
 
141
141
  Log.info("Applying deployment");
142
- const dep = deployment(assets, hash, assets.buildTimestamp);
142
+ const dep = getDeployment(assets, hash, assets.buildTimestamp);
143
143
  await K8s(kind.Deployment).Apply(dep, { force });
144
144
  }
145
145
 
146
146
  // Setup the watcher deployment and service
147
- async function setupWatcher(assets: Assets, hash: string, force: boolean) {
147
+ async function setupWatcher(assets: Assets, hash: string, force: boolean): Promise<void> {
148
148
  // If the module has a watcher, deploy it
149
- const watchDeployment = watcher(assets, hash, assets.buildTimestamp);
149
+ const watchDeployment = getWatcher(assets, hash, assets.buildTimestamp);
150
150
  if (watchDeployment) {
151
151
  Log.info("Applying watcher deployment");
152
152
  await K8s(kind.Deployment).Apply(watchDeployment, { force });
@@ -6,7 +6,7 @@ import { K8s, kind } from "kubernetes-fluent-client";
6
6
  import Log from "../telemetry/logger";
7
7
  import { peprStoreCRD } from "./store";
8
8
 
9
- export async function destroyModule(name: string) {
9
+ export async function destroyModule(name: string): Promise<void> {
10
10
  const namespace = "pepr-system";
11
11
 
12
12
  Log.info("Destroying Pepr module");
@@ -1,7 +1,7 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
3
 
4
- export function clusterRoleTemplate() {
4
+ export function clusterRoleTemplate(): string {
5
5
  return `
6
6
  apiVersion: rbac.authorization.k8s.io/v1
7
7
  kind: ClusterRole
@@ -15,7 +15,7 @@ export function clusterRoleTemplate() {
15
15
  `;
16
16
  }
17
17
 
18
- export function nsTemplate() {
18
+ export function namespaceTemplate(): string {
19
19
  return `
20
20
  apiVersion: v1
21
21
  kind: Namespace
@@ -32,7 +32,7 @@ export function nsTemplate() {
32
32
  `;
33
33
  }
34
34
 
35
- export function chartYaml(name: string, description?: string) {
35
+ export function chartYaml(name: string, description?: string): string {
36
36
  return `
37
37
  apiVersion: v2
38
38
  name: ${name}
@@ -61,7 +61,7 @@ export function chartYaml(name: string, description?: string) {
61
61
  `;
62
62
  }
63
63
 
64
- export function watcherDeployTemplate(buildTimestamp: string) {
64
+ export function watcherDeployTemplate(buildTimestamp: string): string {
65
65
  return `
66
66
  apiVersion: apps/v1
67
67
  kind: Deployment
@@ -142,7 +142,7 @@ export function watcherDeployTemplate(buildTimestamp: string) {
142
142
  `;
143
143
  }
144
144
 
145
- export function admissionDeployTemplate(buildTimestamp: string) {
145
+ export function admissionDeployTemplate(buildTimestamp: string): string {
146
146
  return `
147
147
  apiVersion: apps/v1
148
148
  kind: Deployment
@@ -228,7 +228,7 @@ export function admissionDeployTemplate(buildTimestamp: string) {
228
228
  `;
229
229
  }
230
230
 
231
- export function serviceMonitorTemplate(name: string) {
231
+ export function serviceMonitorTemplate(name: string): string {
232
232
  return `
233
233
  {{- if .Values.${name}.serviceMonitor.enabled }}
234
234
  apiVersion: monitoring.coreos.com/v1
@@ -4,7 +4,7 @@
4
4
  import crypto from "crypto";
5
5
  import { dumpYaml } from "@kubernetes/client-node";
6
6
  import { kind } from "kubernetes-fluent-client";
7
- import { ModuleConfig } from "../module";
7
+ import { ModuleConfig } from "../core/module";
8
8
  import { TLSOut, genTLS } from "../tls";
9
9
  import { CapabilityExport } from "../types";
10
10
  import { WebhookIgnore } from "../k8s";
@@ -16,7 +16,7 @@ import { dedent } from "../helpers";
16
16
  import { resolve } from "path";
17
17
  import {
18
18
  chartYaml,
19
- nsTemplate,
19
+ namespaceTemplate,
20
20
  admissionDeployTemplate,
21
21
  watcherDeployTemplate,
22
22
  clusterRoleTemplate,
@@ -25,7 +25,7 @@ import {
25
25
  import { promises as fs } from "fs";
26
26
  import { webhookConfig } from "./webhooks";
27
27
  import { apiTokenSecret, service, tlsSecret, watcherService } from "./networking";
28
- import { watcher, moduleSecret } from "./pods";
28
+ import { getWatcher, getModuleSecret } from "./pods";
29
29
 
30
30
  import { clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "./rbac";
31
31
  import { createDirectoryIfNotExists } from "../filesystemService";
@@ -51,7 +51,7 @@ function createWebhookYaml(
51
51
  );
52
52
  }
53
53
 
54
- function helmLayout(basePath: string, unique: string) {
54
+ function helmLayout(basePath: string, unique: string): Record<string, Record<string, string>> {
55
55
  const helm: Record<string, Record<string, string>> = {
56
56
  dirs: {
57
57
  chart: resolve(`${basePath}/${unique}-chart`),
@@ -119,20 +119,20 @@ export class Assets {
119
119
  this.apiToken = crypto.randomBytes(32).toString("hex");
120
120
  }
121
121
 
122
- setHash = (hash: string) => {
122
+ setHash = (hash: string): void => {
123
123
  this.hash = hash;
124
124
  };
125
125
 
126
- deploy = async (force: boolean, webhookTimeout?: number) => {
126
+ deploy = async (force: boolean, webhookTimeout?: number): Promise<void> => {
127
127
  this.capabilities = await loadCapabilities(this.path);
128
128
  await deploy(this, force, webhookTimeout);
129
129
  };
130
130
 
131
- zarfYaml = (path: string) => zarfYaml(this, path);
131
+ zarfYaml = (path: string): string => zarfYaml(this, path);
132
132
 
133
- zarfYamlChart = (path: string) => zarfYamlChart(this, path);
133
+ zarfYamlChart = (path: string): string => zarfYamlChart(this, path);
134
134
 
135
- allYaml = async (imagePullSecret?: string) => {
135
+ allYaml = async (imagePullSecret?: string): Promise<string> => {
136
136
  this.capabilities = await loadCapabilities(this.path);
137
137
  // give error if namespaces are not respected
138
138
  for (const capability of this.capabilities) {
@@ -143,7 +143,7 @@ export class Assets {
143
143
  };
144
144
 
145
145
  /* eslint max-statements: ["warn", 21] */
146
- generateHelmChart = async (basePath: string) => {
146
+ generateHelmChart = async (basePath: string): Promise<void> => {
147
147
  const helm = helmLayout(basePath, this.config.uuid);
148
148
 
149
149
  try {
@@ -156,18 +156,18 @@ export class Assets {
156
156
  const code = await fs.readFile(this.path);
157
157
 
158
158
  const pairs: [string, () => string][] = [
159
- [helm.files.chartYaml, () => dedent(chartYaml(this.config.uuid, this.config.description || ""))],
160
- [helm.files.namespaceYaml, () => dedent(nsTemplate())],
161
- [helm.files.watcherServiceYaml, () => toYaml(watcherService(this.name))],
162
- [helm.files.admissionServiceYaml, () => toYaml(service(this.name))],
163
- [helm.files.tlsSecretYaml, () => toYaml(tlsSecret(this.name, this.tls))],
164
- [helm.files.apiTokenSecretYaml, () => toYaml(apiTokenSecret(this.name, this.apiToken))],
165
- [helm.files.storeRoleYaml, () => toYaml(storeRole(this.name))],
166
- [helm.files.storeRoleBindingYaml, () => toYaml(storeRoleBinding(this.name))],
167
- [helm.files.clusterRoleYaml, () => dedent(clusterRoleTemplate())],
168
- [helm.files.clusterRoleBindingYaml, () => toYaml(clusterRoleBinding(this.name))],
169
- [helm.files.serviceAccountYaml, () => toYaml(serviceAccount(this.name))],
170
- [helm.files.moduleSecretYaml, () => toYaml(moduleSecret(this.name, code, this.hash))],
159
+ [helm.files.chartYaml, (): string => dedent(chartYaml(this.config.uuid, this.config.description || ""))],
160
+ [helm.files.namespaceYaml, (): string => dedent(namespaceTemplate())],
161
+ [helm.files.watcherServiceYaml, (): string => toYaml(watcherService(this.name))],
162
+ [helm.files.admissionServiceYaml, (): string => toYaml(service(this.name))],
163
+ [helm.files.tlsSecretYaml, (): string => toYaml(tlsSecret(this.name, this.tls))],
164
+ [helm.files.apiTokenSecretYaml, (): string => toYaml(apiTokenSecret(this.name, this.apiToken))],
165
+ [helm.files.storeRoleYaml, (): string => toYaml(storeRole(this.name))],
166
+ [helm.files.storeRoleBindingYaml, (): string => toYaml(storeRoleBinding(this.name))],
167
+ [helm.files.clusterRoleYaml, (): string => dedent(clusterRoleTemplate())],
168
+ [helm.files.clusterRoleBindingYaml, (): string => toYaml(clusterRoleBinding(this.name))],
169
+ [helm.files.serviceAccountYaml, (): string => toYaml(serviceAccount(this.name))],
170
+ [helm.files.moduleSecretYaml, (): string => toYaml(getModuleSecret(this.name, code, this.hash))],
171
171
  ];
172
172
  await Promise.all(pairs.map(async ([file, content]) => await fs.writeFile(file, content())));
173
173
 
@@ -191,7 +191,7 @@ export class Assets {
191
191
  await fs.writeFile(helm.files.validationWebhookYaml, createWebhookYaml(this, validateWebhook));
192
192
  }
193
193
 
194
- const watchDeployment = watcher(this, this.hash, this.buildTimestamp);
194
+ const watchDeployment = getWatcher(this, this.hash, this.buildTimestamp);
195
195
  if (watchDeployment) {
196
196
  await fs.writeFile(helm.files.watcherDeploymentYaml, dedent(watcherDeployTemplate(this.buildTimestamp)));
197
197
  await fs.writeFile(helm.files.watcherServiceMonitorYaml, dedent(serviceMonitorTemplate("watcher")));
@@ -1,16 +1,16 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
3
 
4
- import { V1EnvVar } from "@kubernetes/client-node";
4
+ import { KubernetesObject, V1EnvVar } 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 ".";
9
- import { ModuleConfig } from "../module";
9
+ import { ModuleConfig } from "../core/module";
10
10
  import { Binding } from "../types";
11
11
 
12
12
  /** Generate the pepr-system namespace */
13
- export function namespace(namespaceLabels?: Record<string, string>) {
13
+ export function getNamespace(namespaceLabels?: Record<string, string>): KubernetesObject {
14
14
  if (namespaceLabels) {
15
15
  return {
16
16
  apiVersion: "v1",
@@ -31,7 +31,12 @@ export function namespace(namespaceLabels?: Record<string, string>) {
31
31
  }
32
32
  }
33
33
 
34
- export function watcher(assets: Assets, hash: string, buildTimestamp: string, imagePullSecret?: string) {
34
+ export function getWatcher(
35
+ assets: Assets,
36
+ hash: string,
37
+ buildTimestamp: string,
38
+ imagePullSecret?: string,
39
+ ): kind.Deployment | null {
35
40
  const { name, image, capabilities, config } = assets;
36
41
 
37
42
  let hasSchedule = false;
@@ -186,7 +191,7 @@ export function watcher(assets: Assets, hash: string, buildTimestamp: string, im
186
191
  return deploy;
187
192
  }
188
193
 
189
- export function deployment(
194
+ export function getDeployment(
190
195
  assets: Assets,
191
196
  hash: string,
192
197
  buildTimestamp: string,
@@ -336,7 +341,7 @@ export function deployment(
336
341
  return deploy;
337
342
  }
338
343
 
339
- export function moduleSecret(name: string, data: Buffer, hash: string): kind.Secret {
344
+ export function getModuleSecret(name: string, data: Buffer, hash: string): kind.Secret {
340
345
  // Compress the data
341
346
  const compressed = gzipSync(data);
342
347
  const path = `module-${hash}.js.gz`;
@@ -11,6 +11,7 @@ import { concat, equals, uniqWith } from "ramda";
11
11
 
12
12
  import { Assets } from ".";
13
13
  import { Event } from "../enums";
14
+ import { Binding } from "../types";
14
15
 
15
16
  const peprIgnoreLabel: V1LabelSelectorRequirement = {
16
17
  key: "pepr.dev",
@@ -20,57 +21,41 @@ const peprIgnoreLabel: V1LabelSelectorRequirement = {
20
21
 
21
22
  const peprIgnoreNamespaces: string[] = ["kube-system", "pepr-system"];
22
23
 
23
- export async function generateWebhookRules(assets: Assets, isMutateWebhook: boolean) {
24
+ const validateRule = (binding: Binding, isMutateWebhook: boolean): V1RuleWithOperations | undefined => {
25
+ const { event, kind, isMutate, isValidate } = binding;
26
+
27
+ // Skip invalid bindings based on webhook type
28
+ if ((isMutateWebhook && !isMutate) || (!isMutateWebhook && !isValidate)) {
29
+ return undefined;
30
+ }
31
+
32
+ // Translate event to operations
33
+ const operations = event === Event.CREATE_OR_UPDATE ? [Event.CREATE, Event.UPDATE] : [event];
34
+
35
+ // Use the plural property if it exists, otherwise use lowercase kind + s
36
+ const resource = kind.plural || `${kind.kind.toLowerCase()}s`;
37
+
38
+ const ruleObject: V1RuleWithOperations = {
39
+ apiGroups: [kind.group],
40
+ apiVersions: [kind.version || "*"],
41
+ operations,
42
+ resources: [resource, ...(resource === "pods" ? ["pods/ephemeralcontainers"] : [])],
43
+ };
44
+
45
+ return ruleObject;
46
+ };
47
+
48
+ export async function generateWebhookRules(assets: Assets, isMutateWebhook: boolean): Promise<V1RuleWithOperations[]> {
24
49
  const { config, capabilities } = assets;
25
- const rules: V1RuleWithOperations[] = [];
26
50
 
27
- // Iterate through the capabilities and generate the rules
28
- for (const capability of capabilities) {
51
+ const rules = capabilities.flatMap(capability => {
29
52
  console.info(`Module ${config.uuid} has capability: ${capability.name}`);
30
53
 
31
- // Read the bindings and generate the rules
32
- for (const binding of capability.bindings) {
33
- const { event, kind, isMutate, isValidate } = binding;
34
-
35
- // If the module doesn't have a callback for the event, skip it
36
- if (isMutateWebhook && !isMutate) {
37
- continue;
38
- }
39
-
40
- if (!isMutateWebhook && !isValidate) {
41
- continue;
42
- }
43
-
44
- const operations: string[] = [];
45
-
46
- // CreateOrUpdate is a Pepr-specific event that is translated to Create and Update
47
- if (event === Event.CREATE_OR_UPDATE) {
48
- operations.push(Event.CREATE, Event.UPDATE);
49
- } else {
50
- operations.push(event);
51
- }
52
-
53
- // Use the plural property if it exists, otherwise use lowercase kind + s
54
- const resource = kind.plural || `${kind.kind.toLowerCase()}s`;
55
-
56
- const ruleObject = {
57
- apiGroups: [kind.group],
58
- apiVersions: [kind.version || "*"],
59
- operations,
60
- resources: [resource],
61
- };
62
-
63
- // If the resource is pods, add ephemeralcontainers as well
64
- if (resource === "pods") {
65
- ruleObject.resources.push("pods/ephemeralcontainers");
66
- }
67
-
68
- // Add the rule to the rules array
69
- rules.push(ruleObject);
70
- }
71
- }
54
+ return capability.bindings
55
+ .map(binding => validateRule(binding, isMutateWebhook))
56
+ .filter((rule): rule is V1RuleWithOperations => !!rule);
57
+ });
72
58
 
73
- // Return the rules with duplicates removed
74
59
  return uniqWith(equals, rules);
75
60
  }
76
61
 
@@ -6,13 +6,16 @@ import crypto from "crypto";
6
6
  import { promises as fs } from "fs";
7
7
  import { Assets } from ".";
8
8
  import { apiTokenSecret, service, tlsSecret, watcherService } from "./networking";
9
- import { deployment, moduleSecret, namespace, watcher } from "./pods";
9
+ import { getDeployment, getModuleSecret, getNamespace, getWatcher } from "./pods";
10
10
  import { clusterRole, clusterRoleBinding, serviceAccount, storeRole, storeRoleBinding } from "./rbac";
11
11
  import { webhookConfig } from "./webhooks";
12
12
  import { genEnv } from "./pods";
13
13
 
14
14
  // Helm Chart overrides file (values.yaml) generated from assets
15
- export async function overridesFile({ hash, name, image, config, apiToken, capabilities }: Assets, path: string) {
15
+ export async function overridesFile(
16
+ { hash, name, image, config, apiToken, capabilities }: Assets,
17
+ path: string,
18
+ ): Promise<void> {
16
19
  const rbacOverrides = clusterRole(name, capabilities, config.rbacMode, config.rbac).rules;
17
20
 
18
21
  const overrides = {
@@ -166,7 +169,7 @@ export async function overridesFile({ hash, name, image, config, apiToken, capab
166
169
 
167
170
  await fs.writeFile(path, dumpYaml(overrides, { noRefs: true, forceQuotes: true }));
168
171
  }
169
- export function zarfYaml({ name, image, config }: Assets, path: string) {
172
+ export function zarfYaml({ name, image, config }: Assets, path: string): string {
170
173
  const zarfCfg = {
171
174
  kind: "ZarfPackageConfig",
172
175
  metadata: {
@@ -194,7 +197,7 @@ export function zarfYaml({ name, image, config }: Assets, path: string) {
194
197
  return dumpYaml(zarfCfg, { noRefs: true });
195
198
  }
196
199
 
197
- export function zarfYamlChart({ name, image, config }: Assets, path: string) {
200
+ export function zarfYamlChart({ name, image, config }: Assets, path: string): string {
198
201
  const zarfCfg = {
199
202
  kind: "ZarfPackageConfig",
200
203
  metadata: {
@@ -223,7 +226,7 @@ export function zarfYamlChart({ name, image, config }: Assets, path: string) {
223
226
  return dumpYaml(zarfCfg, { noRefs: true });
224
227
  }
225
228
 
226
- export async function allYaml(assets: Assets, imagePullSecret?: string) {
229
+ export async function allYaml(assets: Assets, imagePullSecret?: string): Promise<string> {
227
230
  const { name, tls, apiToken, path, config } = assets;
228
231
  const code = await fs.readFile(path);
229
232
 
@@ -232,19 +235,19 @@ export async function allYaml(assets: Assets, imagePullSecret?: string) {
232
235
 
233
236
  const mutateWebhook = await webhookConfig(assets, "mutate", assets.config.webhookTimeout);
234
237
  const validateWebhook = await webhookConfig(assets, "validate", assets.config.webhookTimeout);
235
- const watchDeployment = watcher(assets, assets.hash, assets.buildTimestamp, imagePullSecret);
238
+ const watchDeployment = getWatcher(assets, assets.hash, assets.buildTimestamp, imagePullSecret);
236
239
 
237
240
  const resources = [
238
- namespace(assets.config.customLabels?.namespace),
241
+ getNamespace(assets.config.customLabels?.namespace),
239
242
  clusterRole(name, assets.capabilities, config.rbacMode, config.rbac),
240
243
  clusterRoleBinding(name),
241
244
  serviceAccount(name),
242
245
  apiTokenSecret(name, apiToken),
243
246
  tlsSecret(name, tls),
244
- deployment(assets, assets.hash, assets.buildTimestamp, imagePullSecret),
247
+ getDeployment(assets, assets.hash, assets.buildTimestamp, imagePullSecret),
245
248
  service(name),
246
249
  watcherService(name),
247
- moduleSecret(name, code, assets.hash),
250
+ getModuleSecret(name, code, assets.hash),
248
251
  storeRole(name),
249
252
  storeRoleBinding(name),
250
253
  ];
@@ -5,13 +5,13 @@ import express, { NextFunction } from "express";
5
5
  import fs from "fs";
6
6
  import https from "https";
7
7
 
8
- import { Capability } from "../capability";
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 { ModuleConfig, isWatchMode } from "../module";
13
- import { mutateProcessor } from "../mutate-processor";
14
- import { validateProcessor } from "../validate-processor";
12
+ import { ModuleConfig, isWatchMode } from "../core/module";
13
+ import { mutateProcessor } from "../processors/mutate-processor";
14
+ import { validateProcessor } from "../processors/validate-processor";
15
15
  import { StoreController } from "./store";
16
16
  import { AdmissionRequest } from "../types";
17
17
  import { karForMutate, karForValidate, KubeAdmissionReview } from "./index.util";
@@ -78,7 +78,7 @@ export class Controller {
78
78
  }
79
79
 
80
80
  /** Start the webhook server */
81
- startServer = (port: number) => {
81
+ startServer = (port: number): void => {
82
82
  if (this.#running) {
83
83
  throw new Error("Cannot start Pepr module: Pepr module was not instantiated with deferStart=true");
84
84
  }
@@ -133,7 +133,7 @@ export class Controller {
133
133
  });
134
134
  };
135
135
 
136
- #bindEndpoints = () => {
136
+ #bindEndpoints = (): void => {
137
137
  // Health check endpoint
138
138
  this.#app.get("/healthz", Controller.#healthz);
139
139
 
@@ -162,7 +162,7 @@ export class Controller {
162
162
  * @param next The next middleware function
163
163
  * @returns
164
164
  */
165
- #validateToken = (req: express.Request, res: express.Response, next: NextFunction) => {
165
+ #validateToken = (req: express.Request, res: express.Response, next: NextFunction): void => {
166
166
  // Validate the token
167
167
  const { token } = req.params;
168
168
  if (token !== this.#token) {
@@ -183,7 +183,7 @@ export class Controller {
183
183
  * @param req the incoming request
184
184
  * @param res the outgoing response
185
185
  */
186
- #metrics = async (req: express.Request, res: express.Response) => {
186
+ #metrics = async (req: express.Request, res: express.Response): Promise<void> => {
187
187
  try {
188
188
  // https://github.com/prometheus/docs/blob/main/content/docs/instrumenting/exposition_formats.md#basic-info
189
189
  res.set("Content-Type", "text/plain; version=0.0.4");
@@ -200,7 +200,9 @@ export class Controller {
200
200
  * @param admissionKind the type of admission request
201
201
  * @returns the request handler
202
202
  */
203
- #admissionReq = (admissionKind: "Mutate" | "Validate") => {
203
+ #admissionReq = (
204
+ admissionKind: "Mutate" | "Validate",
205
+ ): ((req: express.Request, res: express.Response) => Promise<void>) => {
204
206
  // Create the admission request handler
205
207
  return async (req: express.Request, res: express.Response) => {
206
208
  // Start the metrics timer
@@ -259,7 +261,7 @@ export class Controller {
259
261
  * @param res the outgoing response
260
262
  * @param next the next middleware function
261
263
  */
262
- static #logger(req: express.Request, res: express.Response, next: express.NextFunction) {
264
+ static #logger(req: express.Request, res: express.Response, next: express.NextFunction): void {
263
265
  const startTime = Date.now();
264
266
 
265
267
  res.on("finish", () => {
@@ -288,7 +290,7 @@ export class Controller {
288
290
  * @param req the incoming request
289
291
  * @param res the outgoing response
290
292
  */
291
- static #healthz(req: express.Request, res: express.Response) {
293
+ static #healthz(req: express.Request, res: express.Response): void {
292
294
  try {
293
295
  res.send("OK");
294
296
  } catch (err) {