pepr 0.51.6-nightly.1 → 0.51.6-nightly.11

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 (73) hide show
  1. package/dist/cli/build.d.ts +2 -2
  2. package/dist/cli/build.d.ts.map +1 -1
  3. package/dist/cli/build.helpers.d.ts.map +1 -1
  4. package/dist/cli/crd/create.d.ts +0 -1
  5. package/dist/cli/crd/create.d.ts.map +1 -1
  6. package/dist/cli/crd/index.d.ts +2 -2
  7. package/dist/cli/crd/index.d.ts.map +1 -1
  8. package/dist/cli/deploy.d.ts +3 -3
  9. package/dist/cli/deploy.d.ts.map +1 -1
  10. package/dist/cli/dev.d.ts +2 -2
  11. package/dist/cli/dev.d.ts.map +1 -1
  12. package/dist/cli/format/index.d.ts +2 -2
  13. package/dist/cli/format/index.d.ts.map +1 -1
  14. package/dist/cli/init/index.d.ts +2 -2
  15. package/dist/cli/init/index.d.ts.map +1 -1
  16. package/dist/cli/init/templates.d.ts +13 -12
  17. package/dist/cli/init/templates.d.ts.map +1 -1
  18. package/dist/cli/init/walkthrough.d.ts.map +1 -1
  19. package/dist/cli/kfc.d.ts +2 -2
  20. package/dist/cli/kfc.d.ts.map +1 -1
  21. package/dist/cli/monitor.d.ts +2 -2
  22. package/dist/cli/monitor.d.ts.map +1 -1
  23. package/dist/cli/update/index.d.ts +2 -2
  24. package/dist/cli/update/index.d.ts.map +1 -1
  25. package/dist/cli/uuid.d.ts +2 -2
  26. package/dist/cli/uuid.d.ts.map +1 -1
  27. package/dist/cli.js +254 -166
  28. package/dist/controller.js +1 -1
  29. package/dist/lib/assets/assets.d.ts +13 -2
  30. package/dist/lib/assets/assets.d.ts.map +1 -1
  31. package/dist/lib/assets/deploy.d.ts.map +1 -1
  32. package/dist/lib/assets/{envrionment.d.ts → environment.d.ts} +1 -1
  33. package/dist/lib/assets/environment.d.ts.map +1 -0
  34. package/dist/lib/assets/helm.d.ts +4 -3
  35. package/dist/lib/assets/helm.d.ts.map +1 -1
  36. package/dist/lib/assets/{pods.d.ts → k8sObjects.d.ts} +4 -2
  37. package/dist/lib/assets/k8sObjects.d.ts.map +1 -0
  38. package/dist/lib/assets/networking.d.ts +0 -2
  39. package/dist/lib/assets/networking.d.ts.map +1 -1
  40. package/dist/lib/assets/yaml/generateAllYaml.d.ts +8 -3
  41. package/dist/lib/assets/yaml/generateAllYaml.d.ts.map +1 -1
  42. package/dist/lib/assets/yaml/overridesFile.d.ts +4 -1
  43. package/dist/lib/assets/yaml/overridesFile.d.ts.map +1 -1
  44. package/package.json +19 -19
  45. package/src/cli/build.helpers.ts +17 -2
  46. package/src/cli/build.ts +29 -41
  47. package/src/cli/crd/create.ts +14 -19
  48. package/src/cli/crd/generate.ts +1 -1
  49. package/src/cli/crd/index.ts +2 -2
  50. package/src/cli/deploy.ts +15 -15
  51. package/src/cli/dev.ts +8 -8
  52. package/src/cli/format/index.ts +3 -3
  53. package/src/cli/init/index.ts +12 -9
  54. package/src/cli/init/walkthrough.ts +2 -4
  55. package/src/cli/kfc.ts +2 -2
  56. package/src/cli/monitor.ts +2 -2
  57. package/src/cli/update/index.ts +3 -4
  58. package/src/cli/uuid.ts +2 -2
  59. package/src/cli.ts +2 -2
  60. package/src/lib/assets/assets.ts +81 -22
  61. package/src/lib/assets/deploy.ts +26 -12
  62. package/src/lib/assets/helm.ts +31 -3
  63. package/src/lib/assets/{pods.ts → k8sObjects.ts} +69 -22
  64. package/src/lib/assets/networking.ts +0 -52
  65. package/src/lib/assets/yaml/generateAllYaml.ts +38 -11
  66. package/src/lib/assets/yaml/overridesFile.ts +4 -1
  67. package/src/templates/tsconfig.module.json +2 -2
  68. package/dist/cli/root.d.ts +0 -5
  69. package/dist/cli/root.d.ts.map +0 -1
  70. package/dist/lib/assets/envrionment.d.ts.map +0 -1
  71. package/dist/lib/assets/pods.d.ts.map +0 -1
  72. package/src/cli/root.ts +0 -12
  73. /package/src/lib/assets/{envrionment.ts → environment.ts} +0 -0
package/src/cli/dev.ts CHANGED
@@ -5,30 +5,30 @@ import prompt from "prompts";
5
5
  import { Assets } from "../lib/assets/assets";
6
6
  import { ChildProcess, fork } from "child_process";
7
7
  import { K8s, kind } from "kubernetes-fluent-client";
8
- import { RootCmd } from "./root";
8
+ import { Command } from "commander";
9
9
  import { Store } from "../lib/k8s";
10
10
  import { buildModule, loadModule } from "./build";
11
11
  import { deployWebhook } from "../lib/assets/deploy";
12
12
  import { promises as fs } from "fs";
13
13
  import { validateCapabilityNames } from "../lib/helpers";
14
14
 
15
- export default function (program: RootCmd): void {
15
+ export default function (program: Command): void {
16
16
  program
17
17
  .command("dev")
18
18
  .description("Setup a local webhook development environment")
19
- .option("-h, --host [host]", "Host to listen on", "host.k3d.internal")
20
- .option("--confirm", "Skip confirmation prompt")
19
+ .option("-H, --host <host>", "Host to listen on", "host.k3d.internal")
20
+ .option("-y, --yes", "Skip confirmation prompt")
21
21
  .action(async opts => {
22
- // Prompt the user to confirm if they didn't pass the --confirm flag
23
- if (!opts.confirm) {
22
+ // Prompt the user to confirm if they didn't pass the --yes flag
23
+ if (!opts.yes) {
24
24
  const confirm = await prompt({
25
25
  type: "confirm",
26
- name: "confirm",
26
+ name: "yes",
27
27
  message: "This will remove and redeploy the module. Continue?",
28
28
  });
29
29
 
30
30
  // Exit if the user doesn't confirm
31
- if (!confirm.confirm) {
31
+ if (!confirm.yes) {
32
32
  process.exitCode = 0;
33
33
  return;
34
34
  }
@@ -4,9 +4,9 @@
4
4
  import { ESLint } from "eslint";
5
5
  import { formatWithPrettier } from "./format.helpers";
6
6
 
7
- import { RootCmd } from "../root";
7
+ import { Command } from "commander";
8
8
 
9
- export default function (program: RootCmd): void {
9
+ export default function (program: Command): void {
10
10
  program
11
11
  .command("format")
12
12
  .description("Lint and format this Pepr module")
@@ -55,7 +55,7 @@ export async function peprFormat(validateOnly: boolean): Promise<boolean> {
55
55
  await ESLint.outputFixes(results);
56
56
  }
57
57
 
58
- hasFailure = await formatWithPrettier(results, validateOnly);
58
+ hasFailure = hasFailure || (await formatWithPrettier(results, validateOnly));
59
59
 
60
60
  return !hasFailure;
61
61
  } catch (e) {
@@ -5,7 +5,7 @@ import { execSync } from "child_process";
5
5
  import { resolve } from "path";
6
6
  import prompts from "prompts";
7
7
 
8
- import { RootCmd } from "../root";
8
+ import { Command } from "commander";
9
9
  import {
10
10
  codeSettings,
11
11
  eslint,
@@ -24,20 +24,22 @@ import { createDir, sanitizeName, write } from "./utils";
24
24
  import { confirm, PromptOptions, walkthrough } from "./walkthrough";
25
25
  import { ErrorList } from "../../lib/errors";
26
26
  import { UUID_LENGTH_LIMIT } from "./enums";
27
+ import { Option } from "commander";
27
28
 
28
- export default function (program: RootCmd): void {
29
+ export default function (program: Command): void {
29
30
  let response = {} as PromptOptions;
30
31
  let pkgOverride = "";
31
32
  program
32
33
  .command("init")
33
34
  .description("Initialize a new Pepr Module")
34
- .option("--confirm", "Skip verification prompt when creating a new module.")
35
- .option("--description <string>", "Explain the purpose of the new module.")
36
- .option("--name <string>", "Set the name of the new module.")
37
- .option("--skip-post-init", "Skip npm install, git init, and VSCode launch.")
38
- .option(`--errorBehavior <${ErrorList.join("|")}>`, "Set an errorBehavior.")
35
+ .option("-d, --description <string>", "Explain the purpose of the new module.")
36
+ .addOption(
37
+ new Option("-e, --error-behavior <behavior>", "Set an error behavior.").choices(ErrorList),
38
+ )
39
+ .option("-n, --name <string>", "Set the name of the new module.")
40
+ .option("-s, --skip-post-init", "Skip npm install, git init, and VSCode launch.")
39
41
  .option(
40
- "--uuid [string]",
42
+ "-u, --uuid <string>",
41
43
  "Unique identifier for your module with a max length of 36 characters.",
42
44
  (uuid: string): string => {
43
45
  if (uuid.length > UUID_LENGTH_LIMIT) {
@@ -46,6 +48,7 @@ export default function (program: RootCmd): void {
46
48
  return uuid.toLocaleLowerCase();
47
49
  },
48
50
  )
51
+ .option("-y, --yes", "Skip verification prompt when creating a new module.")
49
52
  .hook("preAction", async thisCommand => {
50
53
  // TODO: Overrides for testing. Don't be so gross with Node CLI testing
51
54
  // TODO: See pepr/#1140
@@ -68,7 +71,7 @@ export default function (program: RootCmd): void {
68
71
  const dirName = sanitizeName(response.name);
69
72
  const packageJSON = genPkgJSON(response, pkgOverride);
70
73
 
71
- const confirmed = await confirm(dirName, packageJSON, peprTSTemplate.path, opts.confirm);
74
+ const confirmed = await confirm(dirName, packageJSON, peprTSTemplate.path, opts.yes);
72
75
 
73
76
  if (confirmed) {
74
77
  console.log("Creating new Pepr module...");
@@ -137,7 +137,7 @@ export async function confirm(
137
137
  ): Promise<boolean> {
138
138
  const confirmationPrompt: PromptObject = {
139
139
  type: "confirm",
140
- name: "confirm",
140
+ name: "yes",
141
141
  message: "Create the new Pepr module?",
142
142
  };
143
143
  const confirmationMessage = `To be generated:
@@ -162,9 +162,7 @@ ${packageJSON.print.replace(/^/gm, " │ ")}
162
162
  console.log(confirmationMessage);
163
163
  const confirm = await prompt([confirmationPrompt]);
164
164
  const shouldCreateModule =
165
- confirm.confirm === "y" || confirm.confirm === "yes" || confirm.confirm === true
166
- ? true
167
- : false;
165
+ confirm.yes === "y" || confirm.yes === "yes" || confirm.yes === true ? true : false;
168
166
  return shouldCreateModule;
169
167
  }
170
168
  }
package/src/cli/kfc.ts CHANGED
@@ -4,9 +4,9 @@
4
4
  import { execSync } from "child_process";
5
5
  import prompt from "prompts";
6
6
 
7
- import { RootCmd } from "./root";
7
+ import { Command } from "commander";
8
8
 
9
- export default function (program: RootCmd): void {
9
+ export default function (program: Command): void {
10
10
  program
11
11
  .command("kfc [args...]")
12
12
  .description("Execute Kubernetes Fluent Client commands")
@@ -5,7 +5,7 @@ import { Log as K8sLog, KubeConfig, KubernetesListObject } from "@kubernetes/cli
5
5
  import { K8s, kind } from "kubernetes-fluent-client";
6
6
  import stream from "stream";
7
7
  import { ResponseItem } from "../lib/types";
8
- import { RootCmd } from "./root";
8
+ import { Command } from "commander";
9
9
 
10
10
  interface LogPayload {
11
11
  namespace: string;
@@ -22,7 +22,7 @@ interface LogPayload {
22
22
  };
23
23
  }
24
24
 
25
- export default function (program: RootCmd): void {
25
+ export default function (program: Command): void {
26
26
  program
27
27
  .command("monitor [module-uuid]")
28
28
  .description("Monitor a Pepr Module")
@@ -15,13 +15,13 @@ import {
15
15
  tsConfig,
16
16
  } from "../init/templates";
17
17
  import { write } from "../init/utils";
18
- import { RootCmd } from "../root";
18
+ import { Command } from "commander";
19
19
 
20
- export default function (program: RootCmd): void {
20
+ export default function (program: Command): void {
21
21
  program
22
22
  .command("update")
23
23
  .description("Update this Pepr module. Not recommended for prod as it may change files.")
24
- .option("--skip-template-update", "Skip updating the template files")
24
+ .option("-s, --skip-template-update", "Do not update template files")
25
25
  .action(async opts => {
26
26
  if (!opts.skipTemplateUpdate) {
27
27
  const { confirm } = await prompt({
@@ -87,7 +87,6 @@ export default function (program: RootCmd): void {
87
87
  await write(tsPath, helloPepr.data);
88
88
  }
89
89
  }
90
- throw new Error("another error, for testing");
91
90
  } catch (e) {
92
91
  console.error(`Error updating template files:`, e);
93
92
  process.exitCode = 1;
package/src/cli/uuid.ts CHANGED
@@ -3,9 +3,9 @@
3
3
 
4
4
  import { KubernetesListObject } from "@kubernetes/client-node";
5
5
  import { K8s, kind } from "kubernetes-fluent-client";
6
- import { RootCmd } from "./root";
6
+ import { Command } from "commander";
7
7
 
8
- export default function (program: RootCmd): void {
8
+ export default function (program: Command): void {
9
9
  program
10
10
  .command("uuid [uuid]")
11
11
  .description("Module UUID(s) currently deployed in the cluster")
package/src/cli.ts CHANGED
@@ -12,7 +12,7 @@ import monitor from "./cli/monitor";
12
12
  import init from "./cli/init/index";
13
13
  import uuid from "./cli/uuid";
14
14
  import { version } from "./cli/init/templates";
15
- import { RootCmd } from "./cli/root";
15
+ import { Command } from "commander";
16
16
  import update from "./cli/update";
17
17
  import kfc from "./cli/kfc";
18
18
  import crd from "./cli/crd";
@@ -21,7 +21,7 @@ if (process.env.npm_lifecycle_event !== "npx") {
21
21
  console.info("Pepr should be run via `npx pepr <command>` instead of `pepr <command>`.");
22
22
  }
23
23
 
24
- const program = new RootCmd();
24
+ const program = new Command();
25
25
  if (!process.env.PEPR_NODE_WARNINGS) {
26
26
  process.removeAllListeners("warning");
27
27
  }
@@ -8,6 +8,7 @@ import {
8
8
  namespaceTemplate,
9
9
  clusterRoleTemplate,
10
10
  admissionDeployTemplate,
11
+ serviceTemplate,
11
12
  serviceMonitorTemplate,
12
13
  watcherDeployTemplate,
13
14
  } from "./helm";
@@ -23,10 +24,39 @@ import { loadCapabilities } from "./loader";
23
24
  import { namespaceComplianceValidator, dedent } from "../helpers";
24
25
  import { promises as fs } from "fs";
25
26
  import { storeRole, storeRoleBinding, clusterRoleBinding, serviceAccount } from "./rbac";
26
- import { watcherService, service, tlsSecret, apiPathSecret } from "./networking";
27
+ import { tlsSecret, apiPathSecret } from "./networking";
27
28
  import { WebhookType } from "../enums";
28
29
  import { kind } from "kubernetes-fluent-client";
29
30
 
31
+ export function norWatchOrAdmission(capabilities: CapabilityExport[]): boolean {
32
+ return !isAdmission(capabilities) && !isWatcher(capabilities);
33
+ }
34
+ export function isAdmission(capabilities: CapabilityExport[]): boolean {
35
+ for (const capability of capabilities) {
36
+ const admissionBindings = capability.bindings.filter(
37
+ binding => binding.isFinalize || binding.isMutate || binding.isValidate,
38
+ );
39
+ if (admissionBindings.length > 0) {
40
+ return true;
41
+ }
42
+ }
43
+ return false;
44
+ }
45
+ export function isWatcher(capabilities: CapabilityExport[]): boolean {
46
+ for (const capability of capabilities) {
47
+ if (capability.hasSchedule) {
48
+ return true;
49
+ }
50
+ const watcherBindings = capability.bindings.filter(
51
+ binding => binding.isFinalize || binding.isWatch || binding.isQueue,
52
+ );
53
+ if (watcherBindings.length > 0) {
54
+ return true;
55
+ }
56
+ }
57
+ return false;
58
+ }
59
+
30
60
  export class Assets {
31
61
  readonly name: string;
32
62
  readonly tls: TLSOut;
@@ -82,20 +112,25 @@ export class Assets {
82
112
  allYaml = async (
83
113
  yamlGenerationFunction: (
84
114
  assets: Assets,
85
- deployments: { default: V1Deployment; watch: V1Deployment | null },
115
+ deployments: { admission: V1Deployment | null; watch: V1Deployment | null },
116
+ services: { admission: kind.Service | null; watch: kind.Service | null },
86
117
  ) => Promise<string>,
87
- getDeploymentFunction: (
88
- assets: Assets,
89
- hash: string,
90
- buildTimestamp: string,
91
- imagePullSecret?: string,
92
- ) => kind.Deployment,
93
- getWatcherFunction: (
94
- assets: Assets,
95
- hash: string,
96
- buildTimestamp: string,
97
- imagePullSecret?: string,
98
- ) => kind.Deployment | null,
118
+ getControllerManifests: {
119
+ getDeploymentFunction: (
120
+ assets: Assets,
121
+ hash: string,
122
+ buildTimestamp: string,
123
+ imagePullSecret?: string,
124
+ ) => kind.Deployment | null;
125
+ getWatcherFunction: (
126
+ assets: Assets,
127
+ hash: string,
128
+ buildTimestamp: string,
129
+ imagePullSecret?: string,
130
+ ) => kind.Deployment | null;
131
+ getServiceFunction: (name: string, assets: Assets) => kind.Service | null;
132
+ getWatcherServiceFunction: (name: string, assets: Assets) => kind.Service | null;
133
+ },
99
134
  imagePullSecret?: string,
100
135
  ): Promise<string> => {
101
136
  this.capabilities = await loadCapabilities(this.path);
@@ -116,11 +151,26 @@ export class Assets {
116
151
  const moduleHash = crypto.createHash("sha256").update(code).digest("hex");
117
152
 
118
153
  const deployments = {
119
- default: getDeploymentFunction(this, moduleHash, this.buildTimestamp, imagePullSecret),
120
- watch: getWatcherFunction(this, moduleHash, this.buildTimestamp, imagePullSecret),
154
+ admission: getControllerManifests.getDeploymentFunction(
155
+ this,
156
+ moduleHash,
157
+ this.buildTimestamp,
158
+ imagePullSecret,
159
+ ),
160
+ watch: getControllerManifests.getWatcherFunction(
161
+ this,
162
+ moduleHash,
163
+ this.buildTimestamp,
164
+ imagePullSecret,
165
+ ),
121
166
  };
122
167
 
123
- return yamlGenerationFunction(this, deployments);
168
+ const services = {
169
+ admission: getControllerManifests.getServiceFunction(this.name, this),
170
+ watch: getControllerManifests.getWatcherServiceFunction(this.name, this),
171
+ };
172
+
173
+ return yamlGenerationFunction(this, deployments, services);
124
174
  };
125
175
 
126
176
  writeWebhookFiles = async (
@@ -131,7 +181,7 @@ export class Assets {
131
181
  if (validateWebhook || mutateWebhook) {
132
182
  await fs.writeFile(
133
183
  helm.files.admissionDeploymentYaml,
134
- dedent(admissionDeployTemplate(this.buildTimestamp)),
184
+ dedent(admissionDeployTemplate(this.buildTimestamp, "admission")),
135
185
  );
136
186
  await fs.writeFile(
137
187
  helm.files.admissionServiceMonitorYaml,
@@ -194,8 +244,14 @@ export class Assets {
194
244
  (): string => dedent(chartYaml(this.config.uuid, this.config.description || "")),
195
245
  ],
196
246
  [helm.files.namespaceYaml, (): string => dedent(namespaceTemplate())],
197
- [helm.files.watcherServiceYaml, (): string => toYaml(watcherService(this.name))],
198
- [helm.files.admissionServiceYaml, (): string => toYaml(service(this.name))],
247
+ [
248
+ helm.files.watcherServiceYaml,
249
+ (): string => dedent(serviceTemplate(this.name, "watcher")),
250
+ ],
251
+ [
252
+ helm.files.admissionServiceYaml,
253
+ (): string => dedent(serviceTemplate(this.name, "admission")),
254
+ ],
199
255
  [helm.files.tlsSecretYaml, (): string => toYaml(tlsSecret(this.name, this.tls))],
200
256
  [
201
257
  helm.files.apiPathSecretYaml,
@@ -221,7 +277,10 @@ export class Assets {
221
277
  apiPath: this.apiPath,
222
278
  capabilities: this.capabilities,
223
279
  };
224
- await overridesFile(overrideData, helm.files.valuesYaml, this.imagePullSecrets);
280
+ await overridesFile(overrideData, helm.files.valuesYaml, this.imagePullSecrets, {
281
+ admission: isAdmission(this.capabilities) || norWatchOrAdmission(this.capabilities),
282
+ watcher: isWatcher(this.capabilities),
283
+ });
225
284
 
226
285
  const webhooks = {
227
286
  mutate: await webhookGeneratorFunction(
@@ -242,7 +301,7 @@ export class Assets {
242
301
  if (watchDeployment) {
243
302
  await fs.writeFile(
244
303
  helm.files.watcherDeploymentYaml,
245
- dedent(watcherDeployTemplate(this.buildTimestamp)),
304
+ dedent(watcherDeployTemplate(this.buildTimestamp, "watcher")),
246
305
  );
247
306
  await fs.writeFile(
248
307
  helm.files.watcherServiceMonitorYaml,
@@ -6,10 +6,17 @@ import { promises as fs } from "fs";
6
6
  import { K8s, kind } from "kubernetes-fluent-client";
7
7
  import { V1PolicyRule as PolicyRule } from "@kubernetes/client-node";
8
8
 
9
- import { Assets } from "./assets";
9
+ import { Assets, isAdmission, norWatchOrAdmission } from "./assets";
10
10
  import Log from "../telemetry/logger";
11
- import { apiPathSecret, service, tlsSecret, watcherService } from "./networking";
12
- import { getDeployment, getModuleSecret, getNamespace, getWatcher } from "./pods";
11
+ import { apiPathSecret, tlsSecret } from "./networking";
12
+ import {
13
+ getDeployment,
14
+ service,
15
+ watcherService,
16
+ getModuleSecret,
17
+ getNamespace,
18
+ getWatcher,
19
+ } from "./k8sObjects";
13
20
  import {
14
21
  clusterRole,
15
22
  clusterRoleBinding,
@@ -148,9 +155,19 @@ async function setupController(
148
155
  const mod = getModuleSecret(name, code, hash);
149
156
  await K8s(kind.Secret).Apply(mod, { force });
150
157
 
151
- Log.info("Applying controller service");
152
- const svc = service(name);
153
- await K8s(kind.Service).Apply(svc, { force });
158
+ if (isAdmission(assets.capabilities) || norWatchOrAdmission(assets.capabilities)) {
159
+ const svc = service(name, assets);
160
+ if (svc) {
161
+ Log.info("Applying controller service");
162
+ await K8s(kind.Service).Apply(svc, { force });
163
+ }
164
+
165
+ const dep = getDeployment(assets, hash, assets.buildTimestamp);
166
+ if (dep) {
167
+ Log.info("Applying deployment");
168
+ await K8s(kind.Deployment).Apply(dep, { force });
169
+ }
170
+ }
154
171
 
155
172
  Log.info("Applying TLS secret");
156
173
  const tls = tlsSecret(name, assets.tls);
@@ -159,10 +176,6 @@ async function setupController(
159
176
  Log.info("Applying API path secret");
160
177
  const apiPath = apiPathSecret(name, assets.apiPath);
161
178
  await K8s(kind.Secret).Apply(apiPath, { force });
162
-
163
- Log.info("Applying deployment");
164
- const dep = getDeployment(assets, hash, assets.buildTimestamp);
165
- await K8s(kind.Deployment).Apply(dep, { force });
166
179
  }
167
180
 
168
181
  // Setup the watcher deployment and service
@@ -172,9 +185,10 @@ async function setupWatcher(assets: Assets, hash: string, force: boolean): Promi
172
185
  if (watchDeployment) {
173
186
  Log.info("Applying watcher deployment");
174
187
  await K8s(kind.Deployment).Apply(watchDeployment, { force });
175
-
188
+ }
189
+ const watchSvc = watcherService(assets.name, assets);
190
+ if (watchSvc) {
176
191
  Log.info("Applying watcher service");
177
- const watchSvc = watcherService(assets.name);
178
192
  await K8s(kind.Service).Apply(watchSvc, { force });
179
193
  }
180
194
  }
@@ -1,6 +1,8 @@
1
1
  // SPDX-License-Identifier: Apache-2.0
2
2
  // SPDX-FileCopyrightText: 2023-Present The Pepr Authors
3
3
 
4
+ type ControllerType = "admission" | "watcher";
5
+
4
6
  export function clusterRoleTemplate(): string {
5
7
  return `
6
8
  apiVersion: rbac.authorization.k8s.io/v1
@@ -61,8 +63,9 @@ export function chartYaml(name: string, description?: string): string {
61
63
  `;
62
64
  }
63
65
 
64
- export function watcherDeployTemplate(buildTimestamp: string): string {
66
+ export function watcherDeployTemplate(buildTimestamp: string, type: ControllerType): string {
65
67
  return `
68
+ {{- if .Values.${type}.enabled }}
66
69
  apiVersion: apps/v1
67
70
  kind: Deployment
68
71
  metadata:
@@ -154,11 +157,13 @@ export function watcherDeployTemplate(buildTimestamp: string): string {
154
157
  {{- if .Values.watcher.extraVolumes }}
155
158
  {{- toYaml .Values.watcher.extraVolumes | nindent 8 }}
156
159
  {{- end }}
160
+ {{- end }}
157
161
  `;
158
162
  }
159
163
 
160
- export function admissionDeployTemplate(buildTimestamp: string): string {
164
+ export function admissionDeployTemplate(buildTimestamp: string, type: ControllerType): string {
161
165
  return `
166
+ {{- if .Values.${type}.enabled }}
162
167
  apiVersion: apps/v1
163
168
  kind: Deployment
164
169
  metadata:
@@ -270,9 +275,10 @@ export function admissionDeployTemplate(buildTimestamp: string): string {
270
275
  {{- if .Values.admission.extraVolumes }}
271
276
  {{- toYaml .Values.admission.extraVolumes | nindent 8 }}
272
277
  {{- end }}
278
+ {{- end }}
273
279
  `;
274
280
  }
275
- type ControllerType = "admission" | "watcher";
281
+
276
282
  export function serviceMonitorTemplate(name: string, type: ControllerType): string {
277
283
  return `
278
284
  {{- if .Values.${type}.serviceMonitor.enabled }}
@@ -300,3 +306,25 @@ export function serviceMonitorTemplate(name: string, type: ControllerType): stri
300
306
  {{- end }}
301
307
  `;
302
308
  }
309
+
310
+ export function serviceTemplate(name: string, type: ControllerType): string {
311
+ const svcName = type === "admission" ? name : `${name}-${type}`;
312
+ return `
313
+ {{- if .Values.${type}.enabled }}
314
+ apiVersion: v1
315
+ kind: Service
316
+ metadata:
317
+ name: ${svcName}
318
+ namespace: pepr-system
319
+ labels:
320
+ pepr.dev/controller: ${type}
321
+ spec:
322
+ selector:
323
+ app: ${svcName}
324
+ pepr.dev/controller: ${type}
325
+ ports:
326
+ - port: 443
327
+ targetPort: 3000
328
+ {{- end }}
329
+ `;
330
+ }
@@ -5,9 +5,8 @@ import { KubernetesObject } from "@kubernetes/client-node";
5
5
  import { kind } from "kubernetes-fluent-client";
6
6
  import { gzipSync } from "zlib";
7
7
  import { secretOverLimit } from "../helpers";
8
- import { Assets } from "./assets";
9
- import { Binding } from "../types";
10
- import { genEnv } from "./envrionment";
8
+ import { Assets, isAdmission, isWatcher, norWatchOrAdmission } from "./assets";
9
+ import { genEnv } from "./environment";
11
10
 
12
11
  /** Generate the pepr-system namespace */
13
12
  export function getNamespace(namespaceLabels?: Record<string, string>): KubernetesObject {
@@ -37,27 +36,13 @@ export function getWatcher(
37
36
  buildTimestamp: string,
38
37
  imagePullSecret?: string,
39
38
  ): kind.Deployment | null {
40
- const { name, image, capabilities, config } = assets;
41
-
42
- let hasSchedule = false;
43
-
44
- // Append the watcher suffix
45
- const app = `${name}-watcher`;
46
- const bindings: Binding[] = [];
47
-
48
- // Loop through the capabilities and find any Watch Actions
49
- for (const capability of capabilities) {
50
- if (capability.hasSchedule) {
51
- hasSchedule = true;
52
- }
53
- const watchers = capability.bindings.filter(binding => binding.isWatch);
54
- bindings.push(...watchers);
55
- }
39
+ const { name, image, config } = assets;
56
40
 
57
- // If there are no watchers, don't deploy the watcher
58
- if (bindings.length < 1 && !hasSchedule) {
41
+ if (!isWatcher(assets.capabilities)) {
59
42
  return null;
60
43
  }
44
+ // Append the watcher suffix
45
+ const app = `${name}-watcher`;
61
46
 
62
47
  const deploy: kind.Deployment = {
63
48
  apiVersion: "apps/v1",
@@ -196,10 +181,14 @@ export function getDeployment(
196
181
  hash: string,
197
182
  buildTimestamp: string,
198
183
  imagePullSecret?: string,
199
- ): kind.Deployment {
184
+ ): kind.Deployment | null {
200
185
  const { name, image, config } = assets;
201
186
  const app = name;
202
187
 
188
+ if (!isAdmission(assets.capabilities) && !norWatchOrAdmission(assets.capabilities)) {
189
+ return null;
190
+ }
191
+
203
192
  const deploy: kind.Deployment = {
204
193
  apiVersion: "apps/v1",
205
194
  kind: "Deployment",
@@ -364,3 +353,61 @@ export function getModuleSecret(name: string, data: Buffer, hash: string): kind.
364
353
  };
365
354
  }
366
355
  }
356
+
357
+ export function service(name: string, assets: Assets): kind.Service | null {
358
+ if (!isAdmission(assets.capabilities) && !norWatchOrAdmission(assets.capabilities)) {
359
+ return null;
360
+ }
361
+ return {
362
+ apiVersion: "v1",
363
+ kind: "Service",
364
+ metadata: {
365
+ name,
366
+ namespace: "pepr-system",
367
+ labels: {
368
+ "pepr.dev/controller": "admission",
369
+ },
370
+ },
371
+ spec: {
372
+ selector: {
373
+ app: name,
374
+ "pepr.dev/controller": "admission",
375
+ },
376
+ ports: [
377
+ {
378
+ port: 443,
379
+ targetPort: 3000,
380
+ },
381
+ ],
382
+ },
383
+ };
384
+ }
385
+
386
+ export function watcherService(name: string, assets: Assets): kind.Service | null {
387
+ if (!isWatcher(assets.capabilities)) {
388
+ return null;
389
+ }
390
+ return {
391
+ apiVersion: "v1",
392
+ kind: "Service",
393
+ metadata: {
394
+ name: `${name}-watcher`,
395
+ namespace: "pepr-system",
396
+ labels: {
397
+ "pepr.dev/controller": "watcher",
398
+ },
399
+ },
400
+ spec: {
401
+ selector: {
402
+ app: `${name}-watcher`,
403
+ "pepr.dev/controller": "watcher",
404
+ },
405
+ ports: [
406
+ {
407
+ port: 443,
408
+ targetPort: 3000,
409
+ },
410
+ ],
411
+ },
412
+ };
413
+ }