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.
- package/CODE_OF_CONDUCT.md +133 -0
- package/README.md +1 -0
- package/dist/cli.js +68 -36
- package/dist/controller.js +8 -3
- package/dist/lib/helpers.d.ts +1 -0
- package/dist/lib/helpers.d.ts.map +1 -1
- package/dist/lib/watch-processor.d.ts.map +1 -1
- package/dist/lib.js +88 -83
- package/dist/lib.js.map +4 -4
- package/package.json +6 -6
- package/src/lib/helpers.ts +11 -0
- package/src/lib/watch-processor.ts +8 -2
|
@@ -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
|
[](https://npmjs.com/package/pepr)
|
|
7
7
|
[](https://npmjs.com/package/pepr)
|
|
8
8
|
[](https://securityscorecards.dev/viewer/?uri=github.com/defenseunicorns/pepr)
|
|
9
|
+
[](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
|
|
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,
|
|
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
|
|
858
|
-
var PeprStore = class extends
|
|
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,
|
|
884
|
+
(0, import_kubernetes_fluent_client3.RegisterKind)(PeprStore, peprStoreGVK);
|
|
866
885
|
|
|
867
886
|
// src/lib/assets/store.ts
|
|
868
|
-
var { group, version, kind:
|
|
869
|
-
var singular =
|
|
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:
|
|
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:
|
|
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 =
|
|
956
|
+
const resource = kind7.plural || `${kind7.kind.toLowerCase()}s`;
|
|
938
957
|
const ruleObject = {
|
|
939
|
-
apiGroups: [
|
|
940
|
-
apiVersions: [
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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,
|
|
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.
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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,
|
|
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"] || "";
|
package/dist/controller.js
CHANGED
|
@@ -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
|
|
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.
|
|
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,
|
|
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) {
|
package/dist/lib/helpers.d.ts
CHANGED
|
@@ -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;
|
|
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;
|
|
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"}
|