pepr 0.29.2 → 0.30.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,133 @@
1
+
2
+ # Contributor Covenant Code of Conduct
3
+
4
+ ## Our Pledge
5
+
6
+ We as members, contributors, and leaders pledge to make participation in our
7
+ community a harassment-free experience for everyone, regardless of age, body
8
+ size, visible or invisible disability, ethnicity, sex characteristics, gender
9
+ identity and expression, level of experience, education, socio-economic status,
10
+ nationality, personal appearance, race, caste, color, religion, or sexual
11
+ identity and orientation.
12
+
13
+ We pledge to act and interact in ways that contribute to an open, welcoming,
14
+ diverse, inclusive, and healthy community.
15
+
16
+ ## Our Standards
17
+
18
+ Examples of behavior that contributes to a positive environment for our
19
+ community include:
20
+
21
+ * Demonstrating empathy and kindness toward other people
22
+ * Being respectful of differing opinions, viewpoints, and experiences
23
+ * Giving and gracefully accepting constructive feedback
24
+ * Accepting responsibility and apologizing to those affected by our mistakes,
25
+ and learning from the experience
26
+ * Focusing on what is best not just for us as individuals, but for the overall
27
+ community
28
+
29
+ Examples of unacceptable behavior include:
30
+
31
+ * The use of sexualized language or imagery, and sexual attention or advances of
32
+ any kind
33
+ * Trolling, insulting or derogatory comments, and personal or political attacks
34
+ * Public or private harassment
35
+ * Publishing others' private information, such as a physical or email address,
36
+ without their explicit permission
37
+ * Other conduct which could reasonably be considered inappropriate in a
38
+ professional setting
39
+
40
+ ## Enforcement Responsibilities
41
+
42
+ Community leaders are responsible for clarifying and enforcing our standards of
43
+ acceptable behavior and will take appropriate and fair corrective action in
44
+ response to any behavior that they deem inappropriate, threatening, offensive,
45
+ or harmful.
46
+
47
+ Community leaders have the right and responsibility to remove, edit, or reject
48
+ comments, commits, code, wiki edits, issues, and other contributions that are
49
+ not aligned to this Code of Conduct, and will communicate reasons for moderation
50
+ decisions when appropriate.
51
+
52
+ ## Scope
53
+
54
+ This Code of Conduct applies within all community spaces, and also applies when
55
+ an individual is officially representing the community in public spaces.
56
+ Examples of representing our community include using an official email address,
57
+ posting via an official social media account, or acting as an appointed
58
+ representative at an online or offline event.
59
+
60
+ ## Enforcement
61
+
62
+ Instances of abusive, harassing, or otherwise unacceptable behavior may be
63
+ reported to the community leaders responsible for enforcement at
64
+ pepr-dev-private@googlegroups.com.
65
+ All complaints will be reviewed and investigated promptly and fairly.
66
+
67
+ All community leaders are obligated to respect the privacy and security of the
68
+ reporter of any incident.
69
+
70
+ ## Enforcement Guidelines
71
+
72
+ Community leaders will follow these Community Impact Guidelines in determining
73
+ the consequences for any action they deem in violation of this Code of Conduct:
74
+
75
+ ### 1. Correction
76
+
77
+ **Community Impact**: Use of inappropriate language or other behavior deemed
78
+ unprofessional or unwelcome in the community.
79
+
80
+ **Consequence**: A private, written warning from community leaders, providing
81
+ clarity around the nature of the violation and an explanation of why the
82
+ behavior was inappropriate. A public apology may be requested.
83
+
84
+ ### 2. Warning
85
+
86
+ **Community Impact**: A violation through a single incident or series of
87
+ actions.
88
+
89
+ **Consequence**: A warning with consequences for continued behavior. No
90
+ interaction with the people involved, including unsolicited interaction with
91
+ those enforcing the Code of Conduct, for a specified period of time. This
92
+ includes avoiding interactions in community spaces as well as external channels
93
+ like social media. Violating these terms may lead to a temporary or permanent
94
+ ban.
95
+
96
+ ### 3. Temporary Ban
97
+
98
+ **Community Impact**: A serious violation of community standards, including
99
+ sustained inappropriate behavior.
100
+
101
+ **Consequence**: A temporary ban from any sort of interaction or public
102
+ communication with the community for a specified period of time. No public or
103
+ private interaction with the people involved, including unsolicited interaction
104
+ with those enforcing the Code of Conduct, is allowed during this period.
105
+ Violating these terms may lead to a permanent ban.
106
+
107
+ ### 4. Permanent Ban
108
+
109
+ **Community Impact**: Demonstrating a pattern of violation of community
110
+ standards, including sustained inappropriate behavior, harassment of an
111
+ individual, or aggression toward or disparagement of classes of individuals.
112
+
113
+ **Consequence**: A permanent ban from any sort of public interaction within the
114
+ community.
115
+
116
+ ## Attribution
117
+
118
+ This Code of Conduct is adapted from the [Contributor Covenant][homepage],
119
+ version 2.1, available at
120
+ [https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
121
+
122
+ Community Impact Guidelines were inspired by
123
+ [Mozilla's code of conduct enforcement ladder][Mozilla CoC].
124
+
125
+ For answers to common questions about this code of conduct, see the FAQ at
126
+ [https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
127
+ [https://www.contributor-covenant.org/translations][translations].
128
+
129
+ [homepage]: https://www.contributor-covenant.org
130
+ [v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
131
+ [Mozilla CoC]: https://github.com/mozilla/diversity
132
+ [FAQ]: https://www.contributor-covenant.org/faq
133
+ [translations]: https://www.contributor-covenant.org/translations
package/README.md CHANGED
@@ -6,6 +6,7 @@
6
6
  [![Npm package version](https://badgen.net/npm/v/pepr)](https://npmjs.com/package/pepr)
7
7
  [![Npm package total downloads](https://badgen.net/npm/dt/pepr)](https://npmjs.com/package/pepr)
8
8
  [![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/defenseunicorns/pepr/badge)](https://securityscorecards.dev/viewer/?uri=github.com/defenseunicorns/pepr)
9
+ [![Contributor Covenant](https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg)](code_of_conduct.md)
9
10
 
10
11
  #### **_Type safe Kubernetes middleware for humans_**
11
12
 
package/dist/cli.js CHANGED
@@ -171,7 +171,7 @@ function genCert(key, name2, issuer) {
171
171
  // src/lib/assets/deploy.ts
172
172
  var import_crypto = __toESM(require("crypto"));
173
173
  var import_fs3 = require("fs");
174
- var import_kubernetes_fluent_client3 = require("kubernetes-fluent-client");
174
+ var import_kubernetes_fluent_client4 = require("kubernetes-fluent-client");
175
175
 
176
176
  // src/lib/logger.ts
177
177
  var import_pino = require("pino");
@@ -277,7 +277,26 @@ var import_zlib = require("zlib");
277
277
 
278
278
  // src/lib/helpers.ts
279
279
  var import_fs2 = require("fs");
280
+ var import_kubernetes_fluent_client2 = require("kubernetes-fluent-client");
281
+
282
+ // src/sdk/sdk.ts
280
283
  var import_kubernetes_fluent_client = require("kubernetes-fluent-client");
284
+ function sanitizeResourceName(name2) {
285
+ return name2.toLowerCase().replace(/[^a-z0-9]+/g, "-").slice(0, 250).replace(/^[^a-z]+|[^a-z]+$/g, "");
286
+ }
287
+
288
+ // src/lib/helpers.ts
289
+ var ValidationError = class extends Error {
290
+ };
291
+ function validateCapabilityNames(capabilities) {
292
+ if (capabilities && capabilities.length > 0) {
293
+ for (let i = 0; i < capabilities.length; i++) {
294
+ if (capabilities[i].name !== sanitizeResourceName(capabilities[i].name)) {
295
+ throw new ValidationError(`Capability name is not a valid Kubernetes resource name: ${capabilities[i].name}`);
296
+ }
297
+ }
298
+ }
299
+ }
281
300
  function createRBACMap(capabilities) {
282
301
  return capabilities.reduce((acc, capability) => {
283
302
  capability.bindings.forEach((binding) => {
@@ -361,7 +380,7 @@ function namespaceComplianceValidator(capability, ignoredNamespaces) {
361
380
  }
362
381
  }
363
382
  async function checkDeploymentStatus(namespace2) {
364
- const deployments = await (0, import_kubernetes_fluent_client.K8s)(import_kubernetes_fluent_client.kind.Deployment).InNamespace(namespace2).Get();
383
+ const deployments = await (0, import_kubernetes_fluent_client2.K8s)(import_kubernetes_fluent_client2.kind.Deployment).InNamespace(namespace2).Get();
365
384
  let status = false;
366
385
  let readyCount = 0;
367
386
  for (const deployment2 of deployments.items) {
@@ -854,19 +873,19 @@ function storeRoleBinding(name2) {
854
873
  }
855
874
 
856
875
  // src/lib/k8s.ts
857
- var import_kubernetes_fluent_client2 = require("kubernetes-fluent-client");
858
- var PeprStore = class extends import_kubernetes_fluent_client2.GenericKind {
876
+ var import_kubernetes_fluent_client3 = require("kubernetes-fluent-client");
877
+ var PeprStore = class extends import_kubernetes_fluent_client3.GenericKind {
859
878
  };
860
879
  var peprStoreGVK = {
861
880
  kind: "PeprStore",
862
881
  version: "v1",
863
882
  group: "pepr.dev"
864
883
  };
865
- (0, import_kubernetes_fluent_client2.RegisterKind)(PeprStore, peprStoreGVK);
884
+ (0, import_kubernetes_fluent_client3.RegisterKind)(PeprStore, peprStoreGVK);
866
885
 
867
886
  // src/lib/assets/store.ts
868
- var { group, version, kind: kind2 } = peprStoreGVK;
869
- var singular = kind2.toLocaleLowerCase();
887
+ var { group, version, kind: kind3 } = peprStoreGVK;
888
+ var singular = kind3.toLocaleLowerCase();
870
889
  var plural = `${singular}s`;
871
890
  var name = `${plural}.${group}`;
872
891
  var peprStoreCRD = {
@@ -902,7 +921,7 @@ var peprStoreCRD = {
902
921
  names: {
903
922
  plural,
904
923
  singular,
905
- kind: kind2
924
+ kind: kind3
906
925
  }
907
926
  }
908
927
  };
@@ -921,7 +940,7 @@ async function generateWebhookRules(assets, isMutateWebhook) {
921
940
  for (const capability of capabilities) {
922
941
  console.info(`Module ${config.uuid} has capability: ${capability.name}`);
923
942
  for (const binding of capability.bindings) {
924
- const { event, kind: kind6, isMutate, isValidate } = binding;
943
+ const { event, kind: kind7, isMutate, isValidate } = binding;
925
944
  if (isMutateWebhook && !isMutate) {
926
945
  continue;
927
946
  }
@@ -934,10 +953,10 @@ async function generateWebhookRules(assets, isMutateWebhook) {
934
953
  } else {
935
954
  operations.push(event);
936
955
  }
937
- const resource = kind6.plural || `${kind6.kind.toLowerCase()}s`;
956
+ const resource = kind7.plural || `${kind7.kind.toLowerCase()}s`;
938
957
  const ruleObject = {
939
- apiGroups: [kind6.group],
940
- apiVersions: [kind6.version || "*"],
958
+ apiGroups: [kind7.group],
959
+ apiVersions: [kind7.version || "*"],
941
960
  operations,
942
961
  resources: [resource]
943
962
  };
@@ -1009,25 +1028,25 @@ async function deploy(assets, force, webhookTimeout) {
1009
1028
  logger_default.info("Establishing connection to Kubernetes");
1010
1029
  const { name: name2, host, path } = assets;
1011
1030
  logger_default.info("Applying pepr-system namespace");
1012
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.Namespace).Apply(namespace(assets.config.customLabels?.namespace));
1031
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.Namespace).Apply(namespace(assets.config.customLabels?.namespace));
1013
1032
  const mutateWebhook = await webhookConfig(assets, "mutate", webhookTimeout);
1014
1033
  if (mutateWebhook) {
1015
1034
  logger_default.info("Applying mutating webhook");
1016
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.MutatingWebhookConfiguration).Apply(mutateWebhook, { force });
1035
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.MutatingWebhookConfiguration).Apply(mutateWebhook, { force });
1017
1036
  } else {
1018
1037
  logger_default.info("Mutating webhook not needed, removing if it exists");
1019
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.MutatingWebhookConfiguration).Delete(name2);
1038
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.MutatingWebhookConfiguration).Delete(name2);
1020
1039
  }
1021
1040
  const validateWebhook = await webhookConfig(assets, "validate", webhookTimeout);
1022
1041
  if (validateWebhook) {
1023
1042
  logger_default.info("Applying validating webhook");
1024
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.ValidatingWebhookConfiguration).Apply(validateWebhook, { force });
1043
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.ValidatingWebhookConfiguration).Apply(validateWebhook, { force });
1025
1044
  } else {
1026
1045
  logger_default.info("Validating webhook not needed, removing if it exists");
1027
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.ValidatingWebhookConfiguration).Delete(name2);
1046
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.ValidatingWebhookConfiguration).Delete(name2);
1028
1047
  }
1029
1048
  logger_default.info("Applying the Pepr Store CRD if it doesn't exist");
1030
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.CustomResourceDefinition).Apply(peprStoreCRD, { force });
1049
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.CustomResourceDefinition).Apply(peprStoreCRD, { force });
1031
1050
  if (host) {
1032
1051
  return;
1033
1052
  }
@@ -1043,46 +1062,46 @@ async function deploy(assets, force, webhookTimeout) {
1043
1062
  async function setupRBAC(name2, capabilities, force) {
1044
1063
  logger_default.info("Applying cluster role binding");
1045
1064
  const crb = clusterRoleBinding(name2);
1046
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.ClusterRoleBinding).Apply(crb, { force });
1065
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.ClusterRoleBinding).Apply(crb, { force });
1047
1066
  logger_default.info("Applying cluster role");
1048
1067
  const cr = clusterRole(name2, capabilities);
1049
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.ClusterRole).Apply(cr, { force });
1068
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.ClusterRole).Apply(cr, { force });
1050
1069
  logger_default.info("Applying service account");
1051
1070
  const sa = serviceAccount(name2);
1052
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.ServiceAccount).Apply(sa, { force });
1071
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.ServiceAccount).Apply(sa, { force });
1053
1072
  logger_default.info("Applying store role");
1054
1073
  const role = storeRole(name2);
1055
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.Role).Apply(role, { force });
1074
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.Role).Apply(role, { force });
1056
1075
  logger_default.info("Applying store role binding");
1057
1076
  const roleBinding = storeRoleBinding(name2);
1058
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.RoleBinding).Apply(roleBinding, { force });
1077
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.RoleBinding).Apply(roleBinding, { force });
1059
1078
  }
1060
1079
  async function setupController(assets, code, hash, force) {
1061
1080
  const { name: name2 } = assets;
1062
1081
  logger_default.info("Applying module secret");
1063
1082
  const mod = moduleSecret(name2, code, hash);
1064
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.Secret).Apply(mod, { force });
1083
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.Secret).Apply(mod, { force });
1065
1084
  logger_default.info("Applying controller service");
1066
1085
  const svc = service(name2);
1067
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.Service).Apply(svc, { force });
1086
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.Service).Apply(svc, { force });
1068
1087
  logger_default.info("Applying TLS secret");
1069
1088
  const tls = tlsSecret(name2, assets.tls);
1070
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.Secret).Apply(tls, { force });
1089
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.Secret).Apply(tls, { force });
1071
1090
  logger_default.info("Applying API token secret");
1072
1091
  const apiToken = apiTokenSecret(name2, assets.apiToken);
1073
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.Secret).Apply(apiToken, { force });
1092
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.Secret).Apply(apiToken, { force });
1074
1093
  logger_default.info("Applying deployment");
1075
1094
  const dep = deployment(assets, hash, assets.buildTimestamp);
1076
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.Deployment).Apply(dep, { force });
1095
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.Deployment).Apply(dep, { force });
1077
1096
  }
1078
1097
  async function setupWatcher(assets, hash, force) {
1079
1098
  const watchDeployment = watcher(assets, hash, assets.buildTimestamp);
1080
1099
  if (watchDeployment) {
1081
1100
  logger_default.info("Applying watcher deployment");
1082
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.Deployment).Apply(watchDeployment, { force });
1101
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.Deployment).Apply(watchDeployment, { force });
1083
1102
  logger_default.info("Applying watcher service");
1084
1103
  const watchSvc = watcherService(assets.name);
1085
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.Service).Apply(watchSvc, { force });
1104
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.Service).Apply(watchSvc, { force });
1086
1105
  }
1087
1106
  }
1088
1107
 
@@ -1815,7 +1834,7 @@ var gitIgnore = "# Ignore node_modules and Pepr build artifacts\nnode_modules\nd
1815
1834
  var readmeMd = '# Pepr Module\n\nThis is a Pepr Module. [Pepr](https://github.com/defenseunicorns/pepr) is a type-safe Kubernetes middleware system.\n\nThe `capabilities` directory contains all the capabilities for this module. By default,\na capability is a single typescript file in the format of `capability-name.ts` that is\nimported in the root `pepr.ts` file as `import { HelloPepr } from "./capabilities/hello-pepr";`.\nBecause this is typescript, you can organize this however you choose, e.g. creating a sub-folder\nper-capability or common logic in shared files or folders.\n\nExample Structure:\n\n```\nModule Root\n\u251C\u2500\u2500 package.json\n\u251C\u2500\u2500 pepr.ts\n\u2514\u2500\u2500 capabilities\n \u251C\u2500\u2500 example-one.ts\n \u251C\u2500\u2500 example-three.ts\n \u2514\u2500\u2500 example-two.ts\n```\n';
1816
1835
  var peprTS = 'import { PeprModule } from "pepr";\n// cfg loads your pepr configuration from package.json\nimport cfg from "./package.json";\n\n// HelloPepr is a demo capability that is included with Pepr. Comment or delete the line below to remove it.\nimport { HelloPepr } from "./capabilities/hello-pepr";\n\n/**\n * This is the main entrypoint for this Pepr module. It is run when the module is started.\n * This is where you register your Pepr configurations and capabilities.\n */\nnew PeprModule(cfg, [\n // "HelloPepr" is a demo capability that is included with Pepr. Comment or delete the line below to remove it.\n HelloPepr,\n\n // Your additional capabilities go here\n]);\n';
1817
1836
  var helloPeprTS = 'import {\n Capability,\n K8s,\n Log,\n PeprMutateRequest,\n RegisterKind,\n a,\n fetch,\n fetchStatus,\n kind,\n} from "pepr";\n\n/**\n * The HelloPepr Capability is an example capability to demonstrate some general concepts of Pepr.\n * To test this capability you run `pepr dev`and then run the following command:\n * `kubectl apply -f capabilities/hello-pepr.samples.yaml`\n */\nexport const HelloPepr = new Capability({\n name: "hello-pepr",\n description: "A simple example capability to show how things work.",\n namespaces: ["pepr-demo", "pepr-demo-2"],\n});\n\n// Use the \'When\' function to create a new action, use \'Store\' to persist data\nconst { When, Store } = HelloPepr;\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (Namespace) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action removes the label `remove-me` when a Namespace is created.\n * Note we don\'t need to specify the namespace here, because we\'ve already specified\n * it in the Capability definition above.\n */\nWhen(a.Namespace)\n .IsCreated()\n .Mutate(ns => ns.RemoveLabel("remove-me"));\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Watch Action with K8s SSA (Namespace) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action watches for the `pepr-demo-2` namespace to be created, then creates a ConfigMap with\n * the name `pepr-ssa-demo` and adds the namespace UID to the ConfigMap data. Because Pepr uses\n * server-side apply for this operation, the ConfigMap will be created or updated if it already exists.\n */\nWhen(a.Namespace)\n .IsCreated()\n .WithName("pepr-demo-2")\n .Watch(async ns => {\n Log.info("Namespace pepr-demo-2 was created.");\n\n try {\n // Apply the ConfigMap using K8s server-side apply\n await K8s(kind.ConfigMap).Apply({\n metadata: {\n name: "pepr-ssa-demo",\n namespace: "pepr-demo-2",\n },\n data: {\n "ns-uid": ns.metadata.uid,\n },\n });\n } catch (error) {\n // You can use the Log object to log messages to the Pepr controller pod\n Log.error(error, "Failed to apply ConfigMap using server-side apply.");\n }\n\n // You can share data between actions using the Store, including between different types of actions\n Store.setItem("watch-data", "This data was stored by a Watch Action.");\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 1) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This is a single action. They can be in the same file or put imported from other files.\n * In this example, when a ConfigMap is created with the name `example-1`, then add a label and annotation.\n *\n * Equivalent to manually running:\n * `kubectl label configmap example-1 pepr=was-here`\n * `kubectl annotate configmap example-1 pepr.dev=annotations-work-too`\n */\nWhen(a.ConfigMap)\n .IsCreated()\n .WithName("example-1")\n .Mutate(request => {\n request\n .SetLabel("pepr", "was-here")\n .SetAnnotation("pepr.dev", "annotations-work-too");\n\n // Use the Store to persist data between requests and Pepr controller pods\n Store.setItem("example-1", "was-here");\n\n // This data is written asynchronously and can be read back via `Store.getItem()` or `Store.subscribe()`\n Store.setItem("example-1-data", JSON.stringify(request.Raw.data));\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate & Validate Actions (CM Example 2) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This combines 3 different types of actions: \'Mutate\', \'Validate\', and \'Watch\'. The order\n * of the actions is required, but each action is optional. In this example, when a ConfigMap is created\n * with the name `example-2`, then add a label and annotation, validate that the ConfigMap has the label\n * `pepr`, and log the request.\n */\nWhen(a.ConfigMap)\n .IsCreated()\n .WithName("example-2")\n .Mutate(request => {\n // This Mutate Action will mutate the request before it is persisted to the cluster\n\n // Use `request.Merge()` to merge the new data with the existing data\n request.Merge({\n metadata: {\n labels: {\n pepr: "was-here",\n },\n annotations: {\n "pepr.dev": "annotations-work-too",\n },\n },\n });\n })\n .Validate(request => {\n // This Validate Action will validate the request before it is persisted to the cluster\n\n // Approve the request if the ConfigMap has the label \'pepr\'\n if (request.HasLabel("pepr")) {\n return request.Approve();\n }\n\n // Otherwise, deny the request with an error message (optional)\n return request.Deny("ConfigMap must have label \'pepr\'");\n })\n .Watch((cm, phase) => {\n // This Watch Action will watch the ConfigMap after it has been persisted to the cluster\n Log.info(cm, `ConfigMap was ${phase} with the name example-2`);\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 2a) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action shows a simple validation that will deny any ConfigMap that has the\n * annotation `evil`. Note that the `Deny()` function takes an optional second parameter that is a\n * user-defined status code to return.\n */\nWhen(a.ConfigMap)\n .IsCreated()\n .Validate(request => {\n if (request.HasAnnotation("evil")) {\n return request.Deny("No evil CM annotations allowed.", 400);\n }\n\n return request.Approve();\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 3) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action combines different styles. Unlike the previous actions, this one will look\n * for any ConfigMap in the `pepr-demo` namespace that has the label `change=by-label` during either\n * CREATE or UPDATE. Note that all conditions added such as `WithName()`, `WithLabel()`, `InNamespace()`,\n * are ANDs so all conditions must be true for the request to be processed.\n */\nWhen(a.ConfigMap)\n .IsCreatedOrUpdated()\n .WithLabel("change", "by-label")\n .Mutate(request => {\n // The K8s object e are going to mutate\n const cm = request.Raw;\n\n // Get the username and uid of the K8s request\n const { username, uid } = request.Request.userInfo;\n\n // Store some data about the request in the configmap\n cm.data["username"] = username;\n cm.data["uid"] = uid;\n\n // You can still mix other ways of making changes too\n request.SetAnnotation("pepr.dev", "making-waves");\n });\n\n// This action validates the label `change=by-label` is deleted\nWhen(a.ConfigMap)\n .IsDeleted()\n .WithLabel("change", "by-label")\n .Validate(request => {\n // Log and then always approve the request\n Log.info("CM with label \'change=by-label\' was deleted.");\n return request.Approve();\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 4) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action show how you can use the `Mutate()` function without an inline function.\n * This is useful if you want to keep your actions small and focused on a single task,\n * or if you want to reuse the same function in multiple actions.\n */\nWhen(a.ConfigMap).IsCreated().WithName("example-4").Mutate(example4Cb);\n\n// This function uses the complete type definition, but is not required.\nfunction example4Cb(cm: PeprMutateRequest<a.ConfigMap>) {\n cm.SetLabel("pepr.dev/first", "true");\n cm.SetLabel("pepr.dev/second", "true");\n cm.SetLabel("pepr.dev/third", "true");\n}\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 4a) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This is the same as Example 4, except this only operates on a CM in the `pepr-demo-2` namespace.\n * Note because the Capability defines namespaces, the namespace specified here must be one of those.\n * Alternatively, you can remove the namespace from the Capability definition and specify it here.\n */\nWhen(a.ConfigMap)\n .IsCreated()\n .InNamespace("pepr-demo-2")\n .WithName("example-4a")\n .Mutate(example4Cb);\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (CM Example 5) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This action is a bit more complex. It will look for any ConfigMap in the `pepr-demo`\n * namespace that has the label `chuck-norris` during CREATE. When it finds one, it will fetch a\n * random Chuck Norris joke from the API and add it to the ConfigMap. This is a great example of how\n * you can use Pepr to make changes to your K8s objects based on external data.\n *\n * Note the use of the `async` keyword. This is required for any action that uses `await` or `fetch()`.\n *\n * Also note we are passing a type to the `fetch()` function. This is optional, but it will help you\n * avoid mistakes when working with the data returned from the API. You can also use the `as` keyword to\n * cast the data returned from the API.\n *\n * These are equivalent:\n * ```ts\n * const joke = await fetch<TheChuckNorrisJoke>("https://api.chucknorris.io/jokes/random?category=dev");\n * const joke = await fetch("https://api.chucknorris.io/jokes/random?category=dev") as TheChuckNorrisJoke;\n * ```\n *\n * Alternatively, you can drop the type completely:\n *\n * ```ts\n * fetch("https://api.chucknorris.io/jokes/random?category=dev")\n * ```\n */\ninterface TheChuckNorrisJoke {\n icon_url: string;\n id: string;\n url: string;\n value: string;\n}\n\nWhen(a.ConfigMap)\n .IsCreated()\n .WithLabel("chuck-norris")\n .Mutate(async change => {\n // Try/catch is not needed as a response object will always be returned\n const response = await fetch<TheChuckNorrisJoke>(\n "https://api.chucknorris.io/jokes/random?category=dev",\n );\n\n // Instead, check the `response.ok` field\n if (response.ok) {\n // Add the Chuck Norris joke to the configmap\n change.Raw.data["chuck-says"] = response.data.value;\n return;\n }\n\n // You can also assert on different HTTP response codes\n if (response.status === fetchStatus.NOT_FOUND) {\n // Do something else\n return;\n }\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (Secret Base64 Handling) *\n * ---------------------------------------------------------------------------------------------------\n *\n * The K8s JS client provides incomplete support for base64 encoding/decoding handling for secrets,\n * unlike the GO client. To make this less painful, Pepr automatically handles base64 encoding/decoding\n * secret data before and after the action is executed.\n */\nWhen(a.Secret)\n .IsCreated()\n .WithName("secret-1")\n .Mutate(request => {\n const secret = request.Raw;\n\n // This will be encoded at the end of all processing back to base64: "Y2hhbmdlLXdpdGhvdXQtZW5jb2Rpbmc="\n secret.data.magic = "change-without-encoding";\n\n // You can modify the data directly, and it will be encoded at the end of all processing\n secret.data.example += " - modified by Pepr";\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (Untyped Custom Resource) *\n * ---------------------------------------------------------------------------------------------------\n *\n * Out of the box, Pepr supports all the standard Kubernetes objects. However, you can also create\n * your own types. This is useful if you are working with an Operator that creates custom resources.\n * There are two ways to do this, the first is to use the `When()` function with a `GenericKind`,\n * the second is to create a new class that extends `GenericKind` and use the `RegisterKind()` function.\n *\n * This example shows how to use the `When()` function with a `GenericKind`. Note that you\n * must specify the `group`, `version`, and `kind` of the object (if applicable). This is how Pepr knows\n * if the action should be triggered or not. Since we are using a `GenericKind`,\n * Pepr will not be able to provide any intellisense for the object, so you will need to refer to the\n * Kubernetes API documentation for the object you are working with.\n *\n * You will need to wait for the CRD in `hello-pepr.samples.yaml` to be created, then you can apply\n *\n * ```yaml\n * apiVersion: pepr.dev/v1\n * kind: Unicorn\n * metadata:\n * name: example-1\n * namespace: pepr-demo\n * spec:\n * message: replace-me\n * counter: 0\n * ```\n */\nWhen(a.GenericKind, {\n group: "pepr.dev",\n version: "v1",\n kind: "Unicorn",\n})\n .IsCreated()\n .WithName("example-1")\n .Mutate(request => {\n request.Merge({\n spec: {\n message: "Hello Pepr without type data!",\n counter: Math.random(),\n },\n });\n });\n\n/**\n * ---------------------------------------------------------------------------------------------------\n * Mutate Action (Typed Custom Resource) *\n * ---------------------------------------------------------------------------------------------------\n *\n * This example shows how to use the `RegisterKind()` function to create a new type. This is useful\n * if you are working with an Operator that creates custom resources and you want to have intellisense\n * for the object. Note that you must specify the `group`, `version`, and `kind` of the object (if applicable)\n * as this is how Pepr knows if the action should be triggered or not.\n *\n * Once you register a new Kind with Pepr, you can use the `When()` function with the new Kind. Ideally,\n * you should register custom Kinds at the top of your Capability file or Pepr Module so they are available\n * to all actions, but we are putting it here for demonstration purposes.\n *\n * You will need to wait for the CRD in `hello-pepr.samples.yaml` to be created, then you can apply\n *\n * ```yaml\n * apiVersion: pepr.dev/v1\n * kind: Unicorn\n * metadata:\n * name: example-2\n * namespace: pepr-demo\n * spec:\n * message: replace-me\n * counter: 0\n * ```*\n */\nclass UnicornKind extends a.GenericKind {\n spec: {\n /**\n * JSDoc comments can be added to explain more details about the field.\n *\n * @example\n * ```ts\n * request.Raw.spec.message = "Hello Pepr!";\n * ```\n * */\n message: string;\n counter: number;\n };\n}\n\nRegisterKind(UnicornKind, {\n group: "pepr.dev",\n version: "v1",\n kind: "Unicorn",\n});\n\nWhen(UnicornKind)\n .IsCreated()\n .WithName("example-2")\n .Mutate(request => {\n request.Merge({\n spec: {\n message: "Hello Pepr with type data!",\n counter: Math.random(),\n },\n });\n });\n\n/**\n * A callback function that is called once the Pepr Store is fully loaded.\n */\nStore.onReady(data => {\n Log.info(data, "Pepr Store Ready");\n});\n';
1818
- var packageJSON = { name: "pepr", description: "Kubernetes application engine", author: "Defense Unicorns", homepage: "https://github.com/defenseunicorns/pepr", license: "Apache-2.0", bin: "dist/cli.js", repository: "defenseunicorns/pepr", engines: { node: ">=18.0.0" }, version: "0.29.2", main: "dist/lib.js", types: "dist/lib.d.ts", scripts: { "gen-data-json": "node hack/build-template-data.js", prebuild: "rm -fr dist/* && npm run gen-data-json", build: "tsc && node build.mjs", "build:image": "npm run build && docker buildx build --tag pepr:dev .", test: "npm run test:unit && npm run test:journey", "test:unit": "npm run gen-data-json && jest src --coverage --detectOpenHandles --coverageDirectory=./coverage", "test:journey": "npm run test:journey:k3d && npm run test:journey:build && npm run test:journey:image && npm run test:journey:run", "test:journey:prep": "if [ ! -d ./pepr-upgrade-test ]; then git clone https://github.com/defenseunicorns/pepr-upgrade-test.git ; fi", "test:journey-wasm": "npm run test:journey:k3d && npm run test:journey:build && npm run test:journey:image && npm run test:journey:run-wasm", "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", "test:journey:build": "npm run build && npm pack", "test:journey:image": "docker buildx build --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev", "test:journey:run": "jest --detectOpenHandles journey/entrypoint.test.ts && npm run test:journey:prep && npm run test:journey:upgrade", "test:journey:run-wasm": "jest --detectOpenHandles journey/entrypoint-wasm.test.ts", "test:journey:upgrade": "npm run test:journey:k3d && npm run test:journey:image && jest --detectOpenHandles journey/pepr-upgrade.test.ts", "format:check": "eslint src && prettier src --check", "format:fix": "eslint src --fix && prettier src --write" }, dependencies: { "@types/ramda": "0.29.12", express: "4.19.2", "fast-json-patch": "3.1.1", "kubernetes-fluent-client": "2.3.1", pino: "8.20.0", "pino-pretty": "11.0.0", "prom-client": "15.1.2", ramda: "0.29.1" }, devDependencies: { "@commitlint/cli": "19.2.2", "@commitlint/config-conventional": "19.2.2", "@jest/globals": "29.7.0", "@types/eslint": "8.56.9", "@types/express": "4.17.21", "@types/node": "18.x.x", "@types/node-forge": "1.3.11", "@types/prompts": "2.4.9", "@types/uuid": "9.0.8", jest: "29.7.0", nock: "13.5.4", "ts-jest": "29.1.2" }, peerDependencies: { "@typescript-eslint/eslint-plugin": "6.15.0", "@typescript-eslint/parser": "6.15.0", commander: "11.1.0", esbuild: "0.19.10", eslint: "8.56.0", "node-forge": "1.3.1", prettier: "3.1.1", prompts: "2.4.2", typescript: "5.3.3", uuid: "9.0.1" } };
1837
+ var packageJSON = { name: "pepr", description: "Kubernetes application engine", author: "Defense Unicorns", homepage: "https://github.com/defenseunicorns/pepr", license: "Apache-2.0", bin: "dist/cli.js", repository: "defenseunicorns/pepr", engines: { node: ">=18.0.0" }, version: "0.30.0", main: "dist/lib.js", types: "dist/lib.d.ts", scripts: { "gen-data-json": "node hack/build-template-data.js", prebuild: "rm -fr dist/* && npm run gen-data-json", build: "tsc && node build.mjs", "build:image": "npm run build && docker buildx build --tag pepr:dev .", test: "npm run test:unit && npm run test:journey", "test:unit": "npm run gen-data-json && jest src --coverage --detectOpenHandles --coverageDirectory=./coverage", "test:journey": "npm run test:journey:k3d && npm run test:journey:build && npm run test:journey:image && npm run test:journey:run", "test:journey:prep": "if [ ! -d ./pepr-upgrade-test ]; then git clone https://github.com/defenseunicorns/pepr-upgrade-test.git ; fi", "test:journey-wasm": "npm run test:journey:k3d && npm run test:journey:build && npm run test:journey:image && npm run test:journey:run-wasm", "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", "test:journey:build": "npm run build && npm pack", "test:journey:image": "docker buildx build --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev", "test:journey:run": "jest --detectOpenHandles journey/entrypoint.test.ts && npm run test:journey:prep && npm run test:journey:upgrade", "test:journey:run-wasm": "jest --detectOpenHandles journey/entrypoint-wasm.test.ts", "test:journey:upgrade": "npm run test:journey:k3d && npm run test:journey:image && jest --detectOpenHandles journey/pepr-upgrade.test.ts", "format:check": "eslint src && prettier src --check", "format:fix": "eslint src --fix && prettier src --write" }, dependencies: { "@types/ramda": "0.29.12", express: "4.19.2", "fast-json-patch": "3.1.1", "kubernetes-fluent-client": "2.3.2", pino: "9.0.0", "pino-pretty": "11.0.0", "prom-client": "15.1.2", ramda: "0.30.0" }, devDependencies: { "@commitlint/cli": "19.3.0", "@commitlint/config-conventional": "19.2.2", "@jest/globals": "29.7.0", "@types/eslint": "8.56.10", "@types/express": "4.17.21", "@types/node": "18.x.x", "@types/node-forge": "1.3.11", "@types/prompts": "2.4.9", "@types/uuid": "9.0.8", jest: "29.7.0", nock: "13.5.4", "ts-jest": "29.1.2" }, peerDependencies: { "@typescript-eslint/eslint-plugin": "6.15.0", "@typescript-eslint/parser": "6.15.0", commander: "11.1.0", esbuild: "0.19.10", eslint: "8.56.0", "node-forge": "1.3.1", prettier: "3.1.1", prompts: "2.4.2", typescript: "5.3.3", uuid: "9.0.1" } };
1819
1838
 
1820
1839
  // src/templates/pepr.code-snippets.json
1821
1840
  var pepr_code_snippets_default = {
@@ -2133,6 +2152,12 @@ function build_default(program2) {
2133
2152
  const yamlFile = `pepr-module-${uuid}.yaml`;
2134
2153
  const yamlPath = (0, import_path2.resolve)(outputDir, yamlFile);
2135
2154
  const yaml = await assets.allYaml(opts.rbacMode);
2155
+ try {
2156
+ validateCapabilityNames(assets.capabilities);
2157
+ } catch (e) {
2158
+ console.error(e.message);
2159
+ process.exit(1);
2160
+ }
2136
2161
  const zarfPath = (0, import_path2.resolve)(outputDir, "zarf.yaml");
2137
2162
  const zarf = assets.zarfYaml(yamlFile);
2138
2163
  await import_fs8.promises.writeFile(yamlPath, yaml);
@@ -2294,6 +2319,7 @@ function deploy_default(program2) {
2294
2319
  const timeout = cfg.pepr.webhookTimeout ? cfg.pepr.webhookTimeout : 10;
2295
2320
  try {
2296
2321
  await webhook.deploy(opts.force, timeout);
2322
+ validateCapabilityNames(webhook.capabilities);
2297
2323
  await namespaceDeploymentsReady();
2298
2324
  console.info(`\u2705 Module deployed successfully`);
2299
2325
  } catch (e) {
@@ -2335,6 +2361,12 @@ function dev_default(program2) {
2335
2361
  const runFork = async () => {
2336
2362
  console.info(`Running module ${path}`);
2337
2363
  await webhook.deploy(false, 30);
2364
+ try {
2365
+ validateCapabilityNames(webhook.capabilities);
2366
+ } catch (e) {
2367
+ console.error(e.message);
2368
+ process.exit(1);
2369
+ }
2338
2370
  program3 = (0, import_child_process3.fork)(path, {
2339
2371
  env: {
2340
2372
  ...process.env,
@@ -2369,7 +2401,7 @@ function dev_default(program2) {
2369
2401
 
2370
2402
  // src/cli/monitor.ts
2371
2403
  var import_client_node4 = require("@kubernetes/client-node");
2372
- var import_kubernetes_fluent_client4 = require("kubernetes-fluent-client");
2404
+ var import_kubernetes_fluent_client5 = require("kubernetes-fluent-client");
2373
2405
  var import_stream = __toESM(require("stream"));
2374
2406
  function monitor_default(program2) {
2375
2407
  program2.command("monitor [module-uuid]").description("Monitor a Pepr Module").action(async (uuid) => {
@@ -2382,7 +2414,7 @@ function monitor_default(program2) {
2382
2414
  labels = ["app", `pepr-${uuid}`];
2383
2415
  errorMessage = `No pods found for module ${uuid}`;
2384
2416
  }
2385
- const pods = await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.Pod).InNamespace("pepr-system").WithLabel(labels[0], labels[1]).Get();
2417
+ const pods = await (0, import_kubernetes_fluent_client5.K8s)(import_kubernetes_fluent_client5.kind.Pod).InNamespace("pepr-system").WithLabel(labels[0], labels[1]).Get();
2386
2418
  const podNames = pods.items.flatMap((pod) => pod.metadata.name);
2387
2419
  if (podNames.length < 1) {
2388
2420
  console.error(errorMessage);
@@ -2588,15 +2620,15 @@ function init_default(program2) {
2588
2620
  }
2589
2621
 
2590
2622
  // src/cli/uuid.ts
2591
- var import_kubernetes_fluent_client5 = require("kubernetes-fluent-client");
2623
+ var import_kubernetes_fluent_client6 = require("kubernetes-fluent-client");
2592
2624
  function uuid_default(program2) {
2593
2625
  program2.command("uuid [uuid]").description("Module UUID(s) currently deployed in the cluster").action(async (uuid) => {
2594
2626
  const uuidTable = {};
2595
2627
  let deployments;
2596
2628
  if (!uuid) {
2597
- deployments = await (0, import_kubernetes_fluent_client5.K8s)(import_kubernetes_fluent_client5.kind.Deployment).InNamespace("pepr-system").WithLabel("pepr.dev/uuid").Get();
2629
+ deployments = await (0, import_kubernetes_fluent_client6.K8s)(import_kubernetes_fluent_client6.kind.Deployment).InNamespace("pepr-system").WithLabel("pepr.dev/uuid").Get();
2598
2630
  } else {
2599
- deployments = await (0, import_kubernetes_fluent_client5.K8s)(import_kubernetes_fluent_client5.kind.Deployment).InNamespace("pepr-system").WithLabel("pepr.dev/uuid", uuid).Get();
2631
+ deployments = await (0, import_kubernetes_fluent_client6.K8s)(import_kubernetes_fluent_client6.kind.Deployment).InNamespace("pepr-system").WithLabel("pepr.dev/uuid", uuid).Get();
2600
2632
  }
2601
2633
  deployments.items.map((deploy2) => {
2602
2634
  const uuid2 = deploy2.metadata?.labels?.["pepr.dev/uuid"] || "";
@@ -28,7 +28,7 @@ var import_child_process = require("child_process");
28
28
  var import_crypto = __toESM(require("crypto"));
29
29
  var import_fs = __toESM(require("fs"));
30
30
  var import_zlib = require("zlib");
31
- var import_kubernetes_fluent_client3 = require("kubernetes-fluent-client");
31
+ var import_kubernetes_fluent_client4 = require("kubernetes-fluent-client");
32
32
 
33
33
  // src/lib/logger.ts
34
34
  var import_pino = require("pino");
@@ -49,7 +49,7 @@ if (process.env.LOG_LEVEL) {
49
49
  var logger_default = Log;
50
50
 
51
51
  // src/templates/data.json
52
- var packageJSON = { name: "pepr", description: "Kubernetes application engine", author: "Defense Unicorns", homepage: "https://github.com/defenseunicorns/pepr", license: "Apache-2.0", bin: "dist/cli.js", repository: "defenseunicorns/pepr", engines: { node: ">=18.0.0" }, version: "0.29.2", main: "dist/lib.js", types: "dist/lib.d.ts", scripts: { "gen-data-json": "node hack/build-template-data.js", prebuild: "rm -fr dist/* && npm run gen-data-json", build: "tsc && node build.mjs", "build:image": "npm run build && docker buildx build --tag pepr:dev .", test: "npm run test:unit && npm run test:journey", "test:unit": "npm run gen-data-json && jest src --coverage --detectOpenHandles --coverageDirectory=./coverage", "test:journey": "npm run test:journey:k3d && npm run test:journey:build && npm run test:journey:image && npm run test:journey:run", "test:journey:prep": "if [ ! -d ./pepr-upgrade-test ]; then git clone https://github.com/defenseunicorns/pepr-upgrade-test.git ; fi", "test:journey-wasm": "npm run test:journey:k3d && npm run test:journey:build && npm run test:journey:image && npm run test:journey:run-wasm", "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", "test:journey:build": "npm run build && npm pack", "test:journey:image": "docker buildx build --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev", "test:journey:run": "jest --detectOpenHandles journey/entrypoint.test.ts && npm run test:journey:prep && npm run test:journey:upgrade", "test:journey:run-wasm": "jest --detectOpenHandles journey/entrypoint-wasm.test.ts", "test:journey:upgrade": "npm run test:journey:k3d && npm run test:journey:image && jest --detectOpenHandles journey/pepr-upgrade.test.ts", "format:check": "eslint src && prettier src --check", "format:fix": "eslint src --fix && prettier src --write" }, dependencies: { "@types/ramda": "0.29.12", express: "4.19.2", "fast-json-patch": "3.1.1", "kubernetes-fluent-client": "2.3.1", pino: "8.20.0", "pino-pretty": "11.0.0", "prom-client": "15.1.2", ramda: "0.29.1" }, devDependencies: { "@commitlint/cli": "19.2.2", "@commitlint/config-conventional": "19.2.2", "@jest/globals": "29.7.0", "@types/eslint": "8.56.9", "@types/express": "4.17.21", "@types/node": "18.x.x", "@types/node-forge": "1.3.11", "@types/prompts": "2.4.9", "@types/uuid": "9.0.8", jest: "29.7.0", nock: "13.5.4", "ts-jest": "29.1.2" }, peerDependencies: { "@typescript-eslint/eslint-plugin": "6.15.0", "@typescript-eslint/parser": "6.15.0", commander: "11.1.0", esbuild: "0.19.10", eslint: "8.56.0", "node-forge": "1.3.1", prettier: "3.1.1", prompts: "2.4.2", typescript: "5.3.3", uuid: "9.0.1" } };
52
+ var packageJSON = { name: "pepr", description: "Kubernetes application engine", author: "Defense Unicorns", homepage: "https://github.com/defenseunicorns/pepr", license: "Apache-2.0", bin: "dist/cli.js", repository: "defenseunicorns/pepr", engines: { node: ">=18.0.0" }, version: "0.30.0", main: "dist/lib.js", types: "dist/lib.d.ts", scripts: { "gen-data-json": "node hack/build-template-data.js", prebuild: "rm -fr dist/* && npm run gen-data-json", build: "tsc && node build.mjs", "build:image": "npm run build && docker buildx build --tag pepr:dev .", test: "npm run test:unit && npm run test:journey", "test:unit": "npm run gen-data-json && jest src --coverage --detectOpenHandles --coverageDirectory=./coverage", "test:journey": "npm run test:journey:k3d && npm run test:journey:build && npm run test:journey:image && npm run test:journey:run", "test:journey:prep": "if [ ! -d ./pepr-upgrade-test ]; then git clone https://github.com/defenseunicorns/pepr-upgrade-test.git ; fi", "test:journey-wasm": "npm run test:journey:k3d && npm run test:journey:build && npm run test:journey:image && npm run test:journey:run-wasm", "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", "test:journey:build": "npm run build && npm pack", "test:journey:image": "docker buildx build --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev", "test:journey:run": "jest --detectOpenHandles journey/entrypoint.test.ts && npm run test:journey:prep && npm run test:journey:upgrade", "test:journey:run-wasm": "jest --detectOpenHandles journey/entrypoint-wasm.test.ts", "test:journey:upgrade": "npm run test:journey:k3d && npm run test:journey:image && jest --detectOpenHandles journey/pepr-upgrade.test.ts", "format:check": "eslint src && prettier src --check", "format:fix": "eslint src --fix && prettier src --write" }, dependencies: { "@types/ramda": "0.29.12", express: "4.19.2", "fast-json-patch": "3.1.1", "kubernetes-fluent-client": "2.3.2", pino: "9.0.0", "pino-pretty": "11.0.0", "prom-client": "15.1.2", ramda: "0.30.0" }, devDependencies: { "@commitlint/cli": "19.3.0", "@commitlint/config-conventional": "19.2.2", "@jest/globals": "29.7.0", "@types/eslint": "8.56.10", "@types/express": "4.17.21", "@types/node": "18.x.x", "@types/node-forge": "1.3.11", "@types/prompts": "2.4.9", "@types/uuid": "9.0.8", jest: "29.7.0", nock: "13.5.4", "ts-jest": "29.1.2" }, peerDependencies: { "@typescript-eslint/eslint-plugin": "6.15.0", "@typescript-eslint/parser": "6.15.0", commander: "11.1.0", esbuild: "0.19.10", eslint: "8.56.0", "node-forge": "1.3.1", prettier: "3.1.1", prompts: "2.4.2", typescript: "5.3.3", uuid: "9.0.1" } };
53
53
 
54
54
  // src/lib/k8s.ts
55
55
  var import_kubernetes_fluent_client = require("kubernetes-fluent-client");
@@ -106,7 +106,12 @@ var peprStoreCRD = {
106
106
  };
107
107
 
108
108
  // src/lib/helpers.ts
109
+ var import_kubernetes_fluent_client3 = require("kubernetes-fluent-client");
110
+
111
+ // src/sdk/sdk.ts
109
112
  var import_kubernetes_fluent_client2 = require("kubernetes-fluent-client");
113
+
114
+ // src/lib/helpers.ts
110
115
  var ValidationError = class extends Error {
111
116
  };
112
117
  function validateHash(expectedHash) {
@@ -146,7 +151,7 @@ var hash = process.argv[2];
146
151
  var startup = async () => {
147
152
  try {
148
153
  logger_default.info("Applying the Pepr Store CRD if it doesn't exist");
149
- await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.CustomResourceDefinition).Apply(peprStoreCRD, { force: true });
154
+ await (0, import_kubernetes_fluent_client4.K8s)(import_kubernetes_fluent_client4.kind.CustomResourceDefinition).Apply(peprStoreCRD, { force: true });
150
155
  validateHash(hash);
151
156
  runModule(hash);
152
157
  } catch (err) {
@@ -2,6 +2,7 @@ import { KubernetesObject } from "kubernetes-fluent-client";
2
2
  import { Binding, CapabilityExport } from "./types";
3
3
  export declare class ValidationError extends Error {
4
4
  }
5
+ export declare function validateCapabilityNames(capabilities: CapabilityExport[] | undefined): void;
5
6
  export declare function validateHash(expectedHash: string): void;
6
7
  type RBACMap = {
7
8
  [key: string]: {
@@ -1 +1 @@
1
- {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/lib/helpers.ts"],"names":[],"mappings":"AAIA,OAAO,EAAO,gBAAgB,EAAQ,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEpD,qBAAa,eAAgB,SAAQ,KAAK;CAAG;AAE7C,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAOvD;AAED,KAAK,OAAO,GAAG;IACb,CAAC,GAAG,EAAE,MAAM,GAAG;QACb,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH,CAAC;AAGF,wBAAgB,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CA2BnH;AAED;;IAEI;AACJ,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EACzB,GAAG,EAAE,OAAO,CAAC,gBAAgB,CAAC,EAC9B,oBAAoB,EAAE,MAAM,EAAE,GAC7B,MAAM,CAiER;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,QAI/D;AAED,wBAAgB,aAAa,CAAC,YAAY,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAyBvE;AAED,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,MAAM,iBAU5D;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,CAMpE;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,CAMlE;AAED,wBAAgB,wBAAwB,CAAC,gBAAgB,EAAE,MAAM,EAAE,EAAE,iBAAiB,EAAE,MAAM,EAAE,WAE/F;AAED,wBAAgB,8BAA8B,CAAC,iBAAiB,EAAE,MAAM,EAAE,EAAE,oBAAoB,EAAE,MAAM,EAAE,WAKzG;AAED,wBAAgB,2BAA2B,CACzC,iBAAiB,EAAE,MAAM,EAAE,EAC3B,iBAAiB,EAAE,MAAM,EAAE,EAC3B,oBAAoB,EAAE,MAAM,EAAE,UAoB/B;AAGD,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,gBAAgB,EAAE,iBAAiB,CAAC,EAAE,MAAM,EAAE,QActG;AAID,wBAAsB,qBAAqB,CAAC,SAAS,EAAE,MAAM,oBAsB5D;AAGD,wBAAsB,yBAAyB,CAAC,SAAS,GAAE,MAAsB,6BAWhF;AAGD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAMpD;AAGD,eAAO,MAAM,YAAY,UAAW,MAAM,YAAY,OAAO,KAAG,MAW/D,CAAC;AAGF,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,UAelC;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,UAK1E"}
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../src/lib/helpers.ts"],"names":[],"mappings":"AAIA,OAAO,EAAO,gBAAgB,EAAQ,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAGpD,qBAAa,eAAgB,SAAQ,KAAK;CAAG;AAE7C,wBAAgB,uBAAuB,CAAC,YAAY,EAAE,gBAAgB,EAAE,GAAG,SAAS,GAAG,IAAI,CAQ1F;AAED,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAOvD;AAED,KAAK,OAAO,GAAG;IACb,CAAC,GAAG,EAAE,MAAM,GAAG;QACb,KAAK,EAAE,MAAM,EAAE,CAAC;QAChB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH,CAAC;AAGF,wBAAgB,YAAY,CAAC,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CA2BnH;AAED;;IAEI;AACJ,wBAAgB,mBAAmB,CACjC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC,EACzB,GAAG,EAAE,OAAO,CAAC,gBAAgB,CAAC,EAC9B,oBAAoB,EAAE,MAAM,EAAE,GAC7B,MAAM,CAiER;AAED,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,MAAM,QAI/D;AAED,wBAAgB,aAAa,CAAC,YAAY,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAyBvE;AAED,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,MAAM,iBAU5D;AAED,wBAAgB,eAAe,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,CAMpE;AAED,wBAAgB,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,OAAO,CAMlE;AAED,wBAAgB,wBAAwB,CAAC,gBAAgB,EAAE,MAAM,EAAE,EAAE,iBAAiB,EAAE,MAAM,EAAE,WAE/F;AAED,wBAAgB,8BAA8B,CAAC,iBAAiB,EAAE,MAAM,EAAE,EAAE,oBAAoB,EAAE,MAAM,EAAE,WAKzG;AAED,wBAAgB,2BAA2B,CACzC,iBAAiB,EAAE,MAAM,EAAE,EAC3B,iBAAiB,EAAE,MAAM,EAAE,EAC3B,oBAAoB,EAAE,MAAM,EAAE,UAoB/B;AAGD,wBAAgB,4BAA4B,CAAC,UAAU,EAAE,gBAAgB,EAAE,iBAAiB,CAAC,EAAE,MAAM,EAAE,QActG;AAID,wBAAsB,qBAAqB,CAAC,SAAS,EAAE,MAAM,oBAsB5D;AAGD,wBAAsB,yBAAyB,CAAC,SAAS,GAAE,MAAsB,6BAWhF;AAGD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAMpD;AAGD,eAAO,MAAM,YAAY,UAAW,MAAM,YAAY,OAAO,KAAG,MAW/D,CAAC;AAGF,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,UAelC;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,UAK1E"}
@@ -1 +1 @@
1
- {"version":3,"file":"watch-processor.d.ts","sourceRoot":"","sources":["../../src/lib/watch-processor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAO,gBAAgB,EAAY,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEvF,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAqB1C;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,UAAU,EAAE,QAMpD;AAkFD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,MAAW,EAAE,GAAG,CAAC,EAAE,gBAAgB,QAMtF"}
1
+ {"version":3,"file":"watch-processor.d.ts","sourceRoot":"","sources":["../../src/lib/watch-processor.ts"],"names":[],"mappings":"AAEA,OAAO,EAAO,gBAAgB,EAAY,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAEvF,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAyB1C;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,YAAY,EAAE,UAAU,EAAE,QAMpD;AAoFD,wBAAgB,QAAQ,CAAC,IAAI,EAAE,UAAU,EAAE,OAAO,GAAE,MAAW,EAAE,GAAG,CAAC,EAAE,gBAAgB,QAMtF"}