pepr 0.45.1 → 0.46.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/README.md +8 -0
- package/dist/cli/build.d.ts.map +1 -1
- package/dist/cli/build.helpers.d.ts +1 -1
- package/dist/cli/init/templates.d.ts +4 -0
- package/dist/cli/init/templates.d.ts.map +1 -1
- package/dist/cli.js +31 -37
- package/dist/controller.js +1 -1
- package/dist/lib/assets/assets.d.ts +1 -1
- package/dist/lib/assets/assets.d.ts.map +1 -1
- package/dist/lib/assets/networking.d.ts +1 -1
- package/dist/lib/assets/networking.d.ts.map +1 -1
- package/dist/lib/assets/yaml/overridesFile.d.ts +2 -2
- package/dist/lib/assets/yaml/overridesFile.d.ts.map +1 -1
- package/dist/lib.js +15 -15
- package/dist/lib.js.map +2 -2
- package/package.json +7 -2
- package/src/cli/build.helpers.ts +1 -1
- package/src/cli/build.ts +2 -10
- package/src/cli/dev.ts +1 -1
- package/src/lib/assets/assets.ts +6 -6
- package/src/lib/assets/deploy.ts +4 -4
- package/src/lib/assets/destroy.ts +1 -1
- package/src/lib/assets/helm.ts +4 -4
- package/src/lib/assets/index.ts +1 -1
- package/src/lib/assets/networking.ts +3 -3
- package/src/lib/assets/pods.ts +4 -4
- package/src/lib/assets/webhooks.ts +5 -5
- package/src/lib/assets/yaml/generateAllYaml.ts +3 -3
- package/src/lib/assets/yaml/overridesFile.ts +3 -3
- package/src/lib/controller/index.ts +18 -18
- package/src/lib/telemetry/metrics.ts +1 -1
package/README.md
CHANGED
|
@@ -9,6 +9,14 @@
|
|
|
9
9
|
[](https://codecov.io/github/defenseunicorns/pepr)
|
|
10
10
|
[](code_of_conduct.md)
|
|
11
11
|
|
|
12
|
+
## What happened to Pepr's stars?
|
|
13
|
+
|
|
14
|
+
In February 2025, an accidental change to the repository's visibility reset the star count. The visibility issue was quickly resolved, but the stars were unfortunately lost.
|
|
15
|
+
|
|
16
|
+
Pepr had over 200 stars, demonstrating its recognition and value within the Kubernetes community. We're working to rebuild that recognition.
|
|
17
|
+
|
|
18
|
+
If you've previously starred Pepr, or if you find it a useful project, we would greatly appreciate it if you could re-star the repository. We really appreciate your support! :star:
|
|
19
|
+
|
|
12
20
|
## **_Type safe Kubernetes middleware for humans_**
|
|
13
21
|
|
|
14
22
|
<!-- markdownlint-disable MD033 - Image-styling is unsupported on GitHub-flavored markdown -->
|
package/dist/cli/build.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAmB,MAAM,SAAS,CAAC;AAKnF,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAIjC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAc5C,MAAM,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC,YAAY,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AACjF,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,YAAY,EACV,MAAM,GACN,SAAS,GACT,gBAAgB,GAChB,cAAc,GACd,cAAc,GACd,KAAK,GACL,MAAM,GACN,UAAU,CACb,GAAG;IACF,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,MAAM,gBAAgB,CAAC,GAAG;IACpE,IAAI,EAAE,gBAAgB,GAAG;QACvB,aAAa,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,GAAG,EAAE,UAAU,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,GAAG,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,UAAU,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,CAAC,OAAO,WAAW,OAAO,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/cli/build.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,WAAW,EAAmB,MAAM,SAAS,CAAC;AAKnF,OAAO,EAAE,OAAO,EAAE,MAAM,QAAQ,CAAC;AAIjC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAc5C,MAAM,MAAM,QAAQ,GAAG,CAAC,IAAI,EAAE,WAAW,CAAC,YAAY,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AACjF,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,YAAY,EACV,MAAM,GACN,SAAS,GACT,gBAAgB,GAChB,cAAc,GACd,cAAc,GACd,KAAK,GACL,MAAM,GACN,UAAU,CACb,GAAG;IACF,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,UAAU,GAAG,IAAI,CAAC,YAAY,EAAE,MAAM,gBAAgB,CAAC,GAAG;IACpE,IAAI,EAAE,gBAAgB,GAAG;QACvB,aAAa,EAAE,MAAM,EAAE,CAAC;KACzB,CAAC;IACF,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,gBAAgB,GAAG;IACtB,GAAG,EAAE,UAAU,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,KAAK,iBAAiB,GAAG;IACvB,GAAG,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,UAAU,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,CAAC,OAAO,WAAW,OAAO,EAAE,OAAO,GAAG,IAAI,CA6H/C;AAWD,wBAAsB,UAAU,CAAC,UAAU,SAAS,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAuC/E;AAED,wBAAsB,WAAW,CAC/B,QAAQ,CAAC,EAAE,QAAQ,EACnB,UAAU,SAAS,EACnB,KAAK,UAAO,GACX,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,CAwEnC;AA6CD,wBAAsB,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CASjD"}
|
|
@@ -42,7 +42,7 @@ export declare function handleCustomOutputDir(outputDir: string): Promise<string
|
|
|
42
42
|
* Check if the image is from Iron Bank and return the correct image
|
|
43
43
|
* @param registry The registry of the image
|
|
44
44
|
* @param image The image to check
|
|
45
|
-
* @param peprVersion The version of the
|
|
45
|
+
* @param peprVersion The version of the Pepr controller
|
|
46
46
|
* @returns The image string
|
|
47
47
|
* @example
|
|
48
48
|
*/
|
|
@@ -52,6 +52,7 @@ export declare const dependencies: {
|
|
|
52
52
|
prebuild: string;
|
|
53
53
|
build: string;
|
|
54
54
|
"build:image": string;
|
|
55
|
+
"build:image:unicorn": string;
|
|
55
56
|
"set:version": string;
|
|
56
57
|
test: string;
|
|
57
58
|
"test:unit": string;
|
|
@@ -59,9 +60,12 @@ export declare const dependencies: {
|
|
|
59
60
|
"test:integration:prep": string;
|
|
60
61
|
"test:integration:run": string;
|
|
61
62
|
"test:journey": string;
|
|
63
|
+
"test:journey:unicorn": string;
|
|
62
64
|
"test:journey-wasm": string;
|
|
65
|
+
"test:journey-wasm:unicorn": string;
|
|
63
66
|
"test:journey:k3d": string;
|
|
64
67
|
"test:journey:image": string;
|
|
68
|
+
"test:journey:image:unicorn": string;
|
|
65
69
|
"test:journey:run": string;
|
|
66
70
|
"test:journey:run-wasm": string;
|
|
67
71
|
"test:journey:upgrade": string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../../src/cli/init/templates.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,YAAY,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAIrE,eAAO,MAAQ,YAAY;;;;;;;;;;;;;GAAE,eAAe;;;;;;;;;;;;;;;;;;;GAAE,gBAAgB;;;;;;;;;;;;GAAE,OAAO
|
|
1
|
+
{"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../../../src/cli/init/templates.ts"],"names":[],"mappings":"AAaA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AACvC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,EAAE,YAAY,IAAI,UAAU,EAAE,MAAM,yBAAyB,CAAC;AAIrE,eAAO,MAAQ,YAAY;;;;;;;;;;;;;GAAE,eAAe;;;;;;;;;;;;;;;;;;;GAAE,gBAAgB;;;;;;;;;;;;GAAE,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;GAAE,OAAO,QAAgB,CAAC;AAEjG,KAAK,eAAe,GAAG;IACrB,IAAI,EAAE;QACJ,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,EAAE,CAAC;QACnB,OAAO,EAAE;YAAE,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;QAC1B,IAAI,EAAE;YACJ,IAAI,EAAE,MAAM,CAAC;YACb,OAAO,EAAE,OAAO,CAAC;YACjB,cAAc,EAAE,MAAM,CAAC;YACvB,YAAY,EAAE,YAAY,CAAC;YAC3B,YAAY,EAAE;gBAAE,UAAU,EAAE,MAAM,EAAE,CAAA;aAAE,CAAC;YACvC,aAAa,EAAE,MAAM,EAAE,CAAC;YACxB,GAAG,EAAE,MAAM,CAAC;YACZ,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC;YACpB,QAAQ,CAAC,EAAE,QAAQ,CAAC;SACrB,CAAC;QACF,OAAO,EAAE;YAAE,WAAW,EAAE,MAAM,CAAA;SAAE,CAAC;QACjC,YAAY,EAAE;YAAE,IAAI,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;QAC/C,eAAe,EAAE;YAAE,UAAU,EAAE,MAAM,CAAA;SAAE,CAAC;KACzC,CAAC;IACF,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,wBAAgB,UAAU,CAAC,IAAI,EAAE,WAAW,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,eAAe,CAqDtF;AAED,wBAAgB,SAAS,IAAI;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAK1D;AAED,eAAO,MAAM,MAAM;;;CAGlB,CAAC;AAEF,eAAO,MAAM,SAAS;;;CAGrB,CAAC;AAEF,eAAO,MAAM,SAAS;;;CAGrB,CAAC;AAEF,eAAO,MAAM,WAAW;;;CAGvB,CAAC;AAEF,eAAO,MAAM,OAAO;;;;;;;;;CAGnB,CAAC;AAEF,eAAO,MAAM,YAAY;;;;;;;;CAGxB,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;;;;;;;CAGpB,CAAC;AAEF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;;;CAGpB,CAAC;AAEF,eAAO,MAAM,MAAM;;;;;;;;;;;;;;;;;;;;CAGlB,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -368,8 +368,8 @@ function admissionDeployTemplate(buildTimestamp) {
|
|
|
368
368
|
- name: tls-certs
|
|
369
369
|
mountPath: /etc/certs
|
|
370
370
|
readOnly: true
|
|
371
|
-
- name: api-
|
|
372
|
-
mountPath: /app/api-
|
|
371
|
+
- name: api-path
|
|
372
|
+
mountPath: /app/api-path
|
|
373
373
|
readOnly: true
|
|
374
374
|
- name: module
|
|
375
375
|
mountPath: /app/load
|
|
@@ -381,9 +381,9 @@ function admissionDeployTemplate(buildTimestamp) {
|
|
|
381
381
|
- name: tls-certs
|
|
382
382
|
secret:
|
|
383
383
|
secretName: {{ .Values.uuid }}-tls
|
|
384
|
-
- name: api-
|
|
384
|
+
- name: api-path
|
|
385
385
|
secret:
|
|
386
|
-
secretName: {{ .Values.uuid }}-api-
|
|
386
|
+
secretName: {{ .Values.uuid }}-api-path
|
|
387
387
|
- name: module
|
|
388
388
|
secret:
|
|
389
389
|
secretName: {{ .Values.uuid }}-module
|
|
@@ -888,8 +888,8 @@ function getDeployment(assets, hash, buildTimestamp, imagePullSecret) {
|
|
|
888
888
|
readOnly: true
|
|
889
889
|
},
|
|
890
890
|
{
|
|
891
|
-
name: "api-
|
|
892
|
-
mountPath: "/app/api-
|
|
891
|
+
name: "api-path",
|
|
892
|
+
mountPath: "/app/api-path",
|
|
893
893
|
readOnly: true
|
|
894
894
|
},
|
|
895
895
|
{
|
|
@@ -908,9 +908,9 @@ function getDeployment(assets, hash, buildTimestamp, imagePullSecret) {
|
|
|
908
908
|
}
|
|
909
909
|
},
|
|
910
910
|
{
|
|
911
|
-
name: "api-
|
|
911
|
+
name: "api-path",
|
|
912
912
|
secret: {
|
|
913
|
-
secretName: `${name2}-api-
|
|
913
|
+
secretName: `${name2}-api-path`
|
|
914
914
|
}
|
|
915
915
|
},
|
|
916
916
|
{
|
|
@@ -1074,14 +1074,14 @@ function storeRoleBinding(name2) {
|
|
|
1074
1074
|
|
|
1075
1075
|
// src/lib/assets/yaml/overridesFile.ts
|
|
1076
1076
|
var import_fs2 = require("fs");
|
|
1077
|
-
async function overridesFile({ hash, name: name2, image, config,
|
|
1077
|
+
async function overridesFile({ hash, name: name2, image, config, apiPath, capabilities }, path, imagePullSecrets) {
|
|
1078
1078
|
const rbacOverrides = clusterRole(name2, capabilities, config.rbacMode, config.rbac).rules;
|
|
1079
1079
|
const overrides = {
|
|
1080
1080
|
imagePullSecrets,
|
|
1081
1081
|
additionalIgnoredNamespaces: [],
|
|
1082
1082
|
rbac: rbacOverrides,
|
|
1083
1083
|
secrets: {
|
|
1084
|
-
|
|
1084
|
+
apiPath: Buffer.from(apiPath).toString("base64")
|
|
1085
1085
|
},
|
|
1086
1086
|
hash,
|
|
1087
1087
|
namespace: {
|
|
@@ -1295,7 +1295,7 @@ function helmLayout(basePath, unique) {
|
|
|
1295
1295
|
watcherDeploymentYaml: `${helm.dirs.tmpls}/watcher-deployment.yaml`,
|
|
1296
1296
|
watcherServiceMonitorYaml: `${helm.dirs.tmpls}/watcher-service-monitor.yaml`,
|
|
1297
1297
|
tlsSecretYaml: `${helm.dirs.tmpls}/tls-secret.yaml`,
|
|
1298
|
-
|
|
1298
|
+
apiPathSecretYaml: `${helm.dirs.tmpls}/api-path-secret.yaml`,
|
|
1299
1299
|
moduleSecretYaml: `${helm.dirs.tmpls}/module-secret.yaml`,
|
|
1300
1300
|
storeRoleYaml: `${helm.dirs.tmpls}/store-role.yaml`,
|
|
1301
1301
|
storeRoleBindingYaml: `${helm.dirs.tmpls}/store-role-binding.yaml`,
|
|
@@ -1335,17 +1335,17 @@ function loadCapabilities(path) {
|
|
|
1335
1335
|
var import_fs3 = require("fs");
|
|
1336
1336
|
|
|
1337
1337
|
// src/lib/assets/networking.ts
|
|
1338
|
-
function
|
|
1338
|
+
function apiPathSecret(name2, apiPath) {
|
|
1339
1339
|
return {
|
|
1340
1340
|
apiVersion: "v1",
|
|
1341
1341
|
kind: "Secret",
|
|
1342
1342
|
metadata: {
|
|
1343
|
-
name: `${name2}-api-
|
|
1343
|
+
name: `${name2}-api-path`,
|
|
1344
1344
|
namespace: "pepr-system"
|
|
1345
1345
|
},
|
|
1346
1346
|
type: "Opaque",
|
|
1347
1347
|
data: {
|
|
1348
|
-
value: Buffer.from(
|
|
1348
|
+
value: Buffer.from(apiPath).toString("base64")
|
|
1349
1349
|
}
|
|
1350
1350
|
};
|
|
1351
1351
|
}
|
|
@@ -1419,7 +1419,7 @@ function watcherService(name2) {
|
|
|
1419
1419
|
var Assets = class {
|
|
1420
1420
|
name;
|
|
1421
1421
|
tls;
|
|
1422
|
-
|
|
1422
|
+
apiPath;
|
|
1423
1423
|
config;
|
|
1424
1424
|
path;
|
|
1425
1425
|
alwaysIgnore;
|
|
@@ -1438,7 +1438,7 @@ var Assets = class {
|
|
|
1438
1438
|
this.alwaysIgnore = config.alwaysIgnore;
|
|
1439
1439
|
this.image = `ghcr.io/defenseunicorns/pepr/controller:v${config.peprVersion}`;
|
|
1440
1440
|
this.tls = genTLS(host || `${this.name}.pepr-system.svc`);
|
|
1441
|
-
this.
|
|
1441
|
+
this.apiPath = import_crypto.default.randomBytes(32).toString("hex");
|
|
1442
1442
|
}
|
|
1443
1443
|
async deploy(deployFunction, force, webhookTimeout) {
|
|
1444
1444
|
this.capabilities = await loadCapabilities(this.path);
|
|
@@ -1486,7 +1486,7 @@ var Assets = class {
|
|
|
1486
1486
|
[helm.files.watcherServiceYaml, () => toYaml(watcherService(this.name))],
|
|
1487
1487
|
[helm.files.admissionServiceYaml, () => toYaml(service(this.name))],
|
|
1488
1488
|
[helm.files.tlsSecretYaml, () => toYaml(tlsSecret(this.name, this.tls))],
|
|
1489
|
-
[helm.files.
|
|
1489
|
+
[helm.files.apiPathSecretYaml, () => toYaml(apiPathSecret(this.name, this.apiPath))],
|
|
1490
1490
|
[helm.files.storeRoleYaml, () => toYaml(storeRole(this.name))],
|
|
1491
1491
|
[helm.files.storeRoleBindingYaml, () => toYaml(storeRoleBinding(this.name))],
|
|
1492
1492
|
[helm.files.clusterRoleYaml, () => dedent(clusterRoleTemplate())],
|
|
@@ -1500,7 +1500,7 @@ var Assets = class {
|
|
|
1500
1500
|
name: this.name,
|
|
1501
1501
|
image: this.image,
|
|
1502
1502
|
config: this.config,
|
|
1503
|
-
|
|
1503
|
+
apiPath: this.apiPath,
|
|
1504
1504
|
capabilities: this.capabilities
|
|
1505
1505
|
};
|
|
1506
1506
|
await overridesFile(overrideData, helm.files.valuesYaml, this.imagePullSecrets);
|
|
@@ -1784,7 +1784,7 @@ var gitIgnore = "# Ignore node_modules and Pepr build artifacts\nnode_modules\nd
|
|
|
1784
1784
|
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';
|
|
1785
1785
|
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';
|
|
1786
1786
|
var helloPeprTS = 'import {\n Capability,\n K8s,\n Log,\n PeprMutateRequest,\n RegisterKind,\n a,\n fetch,\n fetchStatus,\n kind,\n} from "pepr";\nimport { MockAgent, setGlobalDispatcher } from "undici";\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://icanhazdadjoke.com/");\n * const joke = await fetch("https://icanhazdadjoke.com/") as TheChuckNorrisJoke;\n * ```\n *\n * Alternatively, you can drop the type completely:\n *\n * ```ts\n * fetch("https://icanhazdadjoke.com")\n * ```\n */\ninterface TheChuckNorrisJoke {\n id: string;\n joke: string;\n status: number;\n}\n\nWhen(a.ConfigMap)\n .IsCreatedOrUpdated()\n .WithLabel("chuck-norris")\n .Mutate(cm => cm.SetLabel("got-jokes", "true"))\n .Watch(async cm => {\n const jokeURL = "https://icanhazdadjoke.com";\n\n const mockAgent: MockAgent = new MockAgent();\n setGlobalDispatcher(mockAgent);\n const mockClient = mockAgent.get(jokeURL);\n mockClient.intercept({ path: "/", method: "GET" }).reply(\n 200,\n {\n id: "R7UfaahVfFd",\n joke: "Funny joke goes here.",\n status: 200,\n },\n {\n headers: {\n "Content-Type": "application/json; charset=utf-8",\n },\n },\n );\n\n // Try/catch is not needed as a response object will always be returned\n const response = await fetch<TheChuckNorrisJoke>(jokeURL, {\n headers: {\n Accept: "application/json",\n },\n });\n\n // Instead, check the `response.ok` field\n if (response.ok) {\n const { joke } = response.data;\n // Add Joke to the Store\n await Store.setItemAndWait(jokeURL, joke);\n // Add the Chuck Norris joke to the configmap\n try {\n await K8s(kind.ConfigMap).Apply({\n metadata: {\n name: cm.metadata.name,\n namespace: cm.metadata.namespace,\n },\n data: {\n "chuck-says": Store.getItem(jokeURL),\n },\n });\n } catch (error) {\n Log.error(error, "Failed to apply ConfigMap using server-side apply.", {\n cm,\n });\n }\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';
|
|
1787
|
-
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" }, files: ["/dist", "/src", "!src/**/*.test.ts", "!dist/**/*.test.d.ts*"], version: "0.
|
|
1787
|
+
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" }, files: ["/dist", "/src", "!src/**/*.test.ts", "!dist/**/*.test.d.ts*"], version: "0.46.0", main: "dist/lib.js", types: "dist/lib.d.ts", scripts: { ci: "npm ci", "gen-data-json": "node hack/build-template-data.js", prebuild: "rm -fr dist/* && npm run gen-data-json", build: "tsc && node build.mjs && npm pack", "build:image": "npm run build && docker buildx build --output type=docker --tag pepr:dev .", "build:image:unicorn": "npm run build && docker buildx build -f Dockerfile.unicorn --output type=docker --tag pepr:dev .", "set:version": "node scripts/set-version.js", test: "npm run test:unit && npm run test:journey && npm run test:journey-wasm", "test:unit": "npm run gen-data-json && jest src --coverage --detectOpenHandles --coverageDirectory=./coverage --testPathIgnorePatterns='cosign.e2e.test.ts'", "test:integration": "npm run test:integration:prep && npm run test:integration:run", "test:integration:prep": "./integration/prep.sh", "test:integration:run": "jest --maxWorkers=4 integration", "test:journey": "npm run test:journey:k3d && npm run build && npm run test:journey:image && npm run test:journey:run", "test:journey:unicorn": "npm run test:journey:k3d && npm run build && npm run test:journey:image:unicorn && npm run test:journey:run", "test:journey-wasm": "npm run test:journey:k3d && npm run build && npm run test:journey:image && npm run test:journey:run-wasm", "test:journey-wasm:unicorn": "npm run test:journey:k3d && npm run build && npm run test:journey:image:unicorn && 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:image": "docker buildx build --output type=docker --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev", "test:journey:image:unicorn": "docker buildx build -f Dockerfile.unicorn --output type=docker --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev", "test:journey:run": "jest --detectOpenHandles journey/entrypoint.test.ts && 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", prepare: `if [ "$NODE_ENV" != 'production' ]; then husky; fi` }, dependencies: { "@types/ramda": "0.30.2", express: "4.21.2", "fast-json-patch": "3.1.1", "follow-redirects": "1.15.9", "http-status-codes": "^2.3.0", "json-pointer": "^0.6.2", "kubernetes-fluent-client": "3.4.0", pino: "9.6.0", "pino-pretty": "13.0.0", "prom-client": "15.1.3", ramda: "0.30.1", sigstore: "3.1.0" }, devDependencies: { "@commitlint/cli": "19.7.1", "@commitlint/config-conventional": "19.7.1", "@fast-check/jest": "^2.0.1", "@jest/globals": "29.7.0", "@types/eslint": "9.6.1", "@types/express": "5.0.0", "@types/follow-redirects": "1.14.4", "@types/json-pointer": "^1.0.34", "@types/node": "22.x.x", "@types/node-forge": "1.3.11", "@types/uuid": "10.0.0", "fast-check": "^3.19.0", husky: "^9.1.6", jest: "29.7.0", "js-yaml": "^4.1.0", shellcheck: "^3.0.0", "ts-jest": "29.2.5", undici: "^7.0.1" }, overrides: { glob: "^9.0.0", "jsonpath-plus": "^10.3.0" }, peerDependencies: { "@types/prompts": "2.4.9", "@typescript-eslint/eslint-plugin": "8.23.0", "@typescript-eslint/parser": "8.23.0", commander: "13.1.0", esbuild: "0.25.0", eslint: "8.57.0", "node-forge": "1.3.1", prettier: "3.4.2", prompts: "2.4.2", typescript: "5.7.3", uuid: "11.0.5" } };
|
|
1788
1788
|
|
|
1789
1789
|
// src/cli/init/utils.ts
|
|
1790
1790
|
var import_fs4 = require("fs");
|
|
@@ -2041,7 +2041,7 @@ async function generateWebhookRules(assets, isMutateWebhook) {
|
|
|
2041
2041
|
}
|
|
2042
2042
|
async function webhookConfigGenerator(assets, mutateOrValidate, timeoutSeconds = 10) {
|
|
2043
2043
|
const ignore = [];
|
|
2044
|
-
const { name: name2, tls, config,
|
|
2044
|
+
const { name: name2, tls, config, apiPath, host } = assets;
|
|
2045
2045
|
const ignoreNS = (0, import_ramda.concat)(peprIgnoreNamespaces, resolveIgnoreNamespaces(config?.alwaysIgnore?.namespaces));
|
|
2046
2046
|
if (ignoreNS) {
|
|
2047
2047
|
ignore.push({
|
|
@@ -2053,14 +2053,14 @@ async function webhookConfigGenerator(assets, mutateOrValidate, timeoutSeconds =
|
|
|
2053
2053
|
const clientConfig = {
|
|
2054
2054
|
caBundle: tls.ca
|
|
2055
2055
|
};
|
|
2056
|
-
const
|
|
2056
|
+
const fullApiPath = `/${mutateOrValidate}/${apiPath}`;
|
|
2057
2057
|
if (host) {
|
|
2058
|
-
clientConfig.url = `https://${host}:3000${
|
|
2058
|
+
clientConfig.url = `https://${host}:3000${fullApiPath}`;
|
|
2059
2059
|
} else {
|
|
2060
2060
|
clientConfig.service = {
|
|
2061
2061
|
name: name2,
|
|
2062
2062
|
namespace: "pepr-system",
|
|
2063
|
-
path:
|
|
2063
|
+
path: fullApiPath
|
|
2064
2064
|
};
|
|
2065
2065
|
}
|
|
2066
2066
|
const isMutate = mutateOrValidate === "mutate" /* MUTATE */;
|
|
@@ -2093,7 +2093,7 @@ async function webhookConfigGenerator(assets, mutateOrValidate, timeoutSeconds =
|
|
|
2093
2093
|
|
|
2094
2094
|
// src/lib/assets/yaml/generateAllYaml.ts
|
|
2095
2095
|
async function generateAllYaml(assets, deployments) {
|
|
2096
|
-
const { name: name2, tls,
|
|
2096
|
+
const { name: name2, tls, apiPath, path, config } = assets;
|
|
2097
2097
|
const code = await import_fs7.promises.readFile(path);
|
|
2098
2098
|
const hash = import_crypto2.default.createHash("sha256").update(code).digest("hex");
|
|
2099
2099
|
const resources = [
|
|
@@ -2101,7 +2101,7 @@ async function generateAllYaml(assets, deployments) {
|
|
|
2101
2101
|
clusterRole(name2, assets.capabilities, config.rbacMode, config.rbac),
|
|
2102
2102
|
clusterRoleBinding(name2),
|
|
2103
2103
|
serviceAccount(name2),
|
|
2104
|
-
|
|
2104
|
+
apiPathSecret(name2, apiPath),
|
|
2105
2105
|
tlsSecret(name2, tls),
|
|
2106
2106
|
deployments.default,
|
|
2107
2107
|
service(name2),
|
|
@@ -2259,21 +2259,16 @@ function build_default(program2) {
|
|
|
2259
2259
|
new import_commander.Option(
|
|
2260
2260
|
"-i, --custom-image <custom-image>",
|
|
2261
2261
|
"Specify a custom image (including version) for Admission and Watch Deployments. Example: 'docker.io/username/custom-pepr-controller:v1.0.0'"
|
|
2262
|
-
).conflicts(["
|
|
2262
|
+
).conflicts(["registryInfo", "registry"])
|
|
2263
2263
|
).addOption(
|
|
2264
2264
|
new import_commander.Option(
|
|
2265
2265
|
"-r, --registry-info [<registry>/<username>]",
|
|
2266
2266
|
"Provide the image registry and username for building and pushing a custom WASM container. Requires authentication. Builds and pushes 'registry/username/custom-pepr-controller:<current-version>'."
|
|
2267
|
-
).conflicts(["customImage", "
|
|
2267
|
+
).conflicts(["customImage", "registry"])
|
|
2268
2268
|
).option("-o, --output-dir <output directory>", "Define where to place build output").option(
|
|
2269
2269
|
"--timeout <timeout>",
|
|
2270
2270
|
"How long the API server should wait for a webhook to respond before treating the call as a failure",
|
|
2271
2271
|
parseTimeout
|
|
2272
|
-
).addOption(
|
|
2273
|
-
new import_commander.Option(
|
|
2274
|
-
"-v, --version <version>",
|
|
2275
|
-
"DEPRECATED: The version of the Pepr image to use in the deployment manifests. Example: '0.27.3'."
|
|
2276
|
-
).conflicts(["customImage", "registryInfo"])
|
|
2277
2272
|
).option(
|
|
2278
2273
|
"--withPullSecret <imagePullSecret>",
|
|
2279
2274
|
"Image Pull Secret: Use image pull secret for controller Deployment.",
|
|
@@ -2318,7 +2313,6 @@ function build_default(program2) {
|
|
|
2318
2313
|
console.info(`\u2705 Module built successfully at ${path}`);
|
|
2319
2314
|
return;
|
|
2320
2315
|
}
|
|
2321
|
-
if (opts.version) cfg.pepr.peprVersion = opts.version;
|
|
2322
2316
|
const assets = new Assets(
|
|
2323
2317
|
{
|
|
2324
2318
|
...cfg.pepr,
|
|
@@ -2616,9 +2610,9 @@ async function setupController(assets, code, hash, force) {
|
|
|
2616
2610
|
logger_default.info("Applying TLS secret");
|
|
2617
2611
|
const tls = tlsSecret(name2, assets.tls);
|
|
2618
2612
|
await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.Secret).Apply(tls, { force });
|
|
2619
|
-
logger_default.info("Applying API
|
|
2620
|
-
const
|
|
2621
|
-
await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.Secret).Apply(
|
|
2613
|
+
logger_default.info("Applying API path secret");
|
|
2614
|
+
const apiPath = apiPathSecret(name2, assets.apiPath);
|
|
2615
|
+
await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.Secret).Apply(apiPath, { force });
|
|
2622
2616
|
logger_default.info("Applying deployment");
|
|
2623
2617
|
const dep = getDeployment(assets, hash, assets.buildTimestamp);
|
|
2624
2618
|
await (0, import_kubernetes_fluent_client3.K8s)(import_kubernetes_fluent_client3.kind.Deployment).Apply(dep, { force });
|
|
@@ -2816,7 +2810,7 @@ function dev_default(program2) {
|
|
|
2816
2810
|
...process.env,
|
|
2817
2811
|
LOG_LEVEL: "debug",
|
|
2818
2812
|
PEPR_MODE: "dev",
|
|
2819
|
-
|
|
2813
|
+
PEPR_API_PATH: webhook.apiPath,
|
|
2820
2814
|
PEPR_PRETTY_LOGS: "true",
|
|
2821
2815
|
SSL_KEY_PATH: "insecure-tls.key",
|
|
2822
2816
|
SSL_CERT_PATH: "insecure-tls.crt"
|
package/dist/controller.js
CHANGED
|
@@ -51,7 +51,7 @@ if (process.env.LOG_LEVEL) {
|
|
|
51
51
|
var logger_default = Log;
|
|
52
52
|
|
|
53
53
|
// src/templates/data.json
|
|
54
|
-
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" }, files: ["/dist", "/src", "!src/**/*.test.ts", "!dist/**/*.test.d.ts*"], version: "0.
|
|
54
|
+
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" }, files: ["/dist", "/src", "!src/**/*.test.ts", "!dist/**/*.test.d.ts*"], version: "0.46.0", main: "dist/lib.js", types: "dist/lib.d.ts", scripts: { ci: "npm ci", "gen-data-json": "node hack/build-template-data.js", prebuild: "rm -fr dist/* && npm run gen-data-json", build: "tsc && node build.mjs && npm pack", "build:image": "npm run build && docker buildx build --output type=docker --tag pepr:dev .", "build:image:unicorn": "npm run build && docker buildx build -f Dockerfile.unicorn --output type=docker --tag pepr:dev .", "set:version": "node scripts/set-version.js", test: "npm run test:unit && npm run test:journey && npm run test:journey-wasm", "test:unit": "npm run gen-data-json && jest src --coverage --detectOpenHandles --coverageDirectory=./coverage --testPathIgnorePatterns='cosign.e2e.test.ts'", "test:integration": "npm run test:integration:prep && npm run test:integration:run", "test:integration:prep": "./integration/prep.sh", "test:integration:run": "jest --maxWorkers=4 integration", "test:journey": "npm run test:journey:k3d && npm run build && npm run test:journey:image && npm run test:journey:run", "test:journey:unicorn": "npm run test:journey:k3d && npm run build && npm run test:journey:image:unicorn && npm run test:journey:run", "test:journey-wasm": "npm run test:journey:k3d && npm run build && npm run test:journey:image && npm run test:journey:run-wasm", "test:journey-wasm:unicorn": "npm run test:journey:k3d && npm run build && npm run test:journey:image:unicorn && 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:image": "docker buildx build --output type=docker --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev", "test:journey:image:unicorn": "docker buildx build -f Dockerfile.unicorn --output type=docker --tag pepr:dev . && k3d image import pepr:dev -c pepr-dev", "test:journey:run": "jest --detectOpenHandles journey/entrypoint.test.ts && 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", prepare: `if [ "$NODE_ENV" != 'production' ]; then husky; fi` }, dependencies: { "@types/ramda": "0.30.2", express: "4.21.2", "fast-json-patch": "3.1.1", "follow-redirects": "1.15.9", "http-status-codes": "^2.3.0", "json-pointer": "^0.6.2", "kubernetes-fluent-client": "3.4.0", pino: "9.6.0", "pino-pretty": "13.0.0", "prom-client": "15.1.3", ramda: "0.30.1", sigstore: "3.1.0" }, devDependencies: { "@commitlint/cli": "19.7.1", "@commitlint/config-conventional": "19.7.1", "@fast-check/jest": "^2.0.1", "@jest/globals": "29.7.0", "@types/eslint": "9.6.1", "@types/express": "5.0.0", "@types/follow-redirects": "1.14.4", "@types/json-pointer": "^1.0.34", "@types/node": "22.x.x", "@types/node-forge": "1.3.11", "@types/uuid": "10.0.0", "fast-check": "^3.19.0", husky: "^9.1.6", jest: "29.7.0", "js-yaml": "^4.1.0", shellcheck: "^3.0.0", "ts-jest": "29.2.5", undici: "^7.0.1" }, overrides: { glob: "^9.0.0", "jsonpath-plus": "^10.3.0" }, peerDependencies: { "@types/prompts": "2.4.9", "@typescript-eslint/eslint-plugin": "8.23.0", "@typescript-eslint/parser": "8.23.0", commander: "13.1.0", esbuild: "0.25.0", eslint: "8.57.0", "node-forge": "1.3.1", prettier: "3.4.2", prompts: "2.4.2", typescript: "5.7.3", uuid: "11.0.5" } };
|
|
55
55
|
|
|
56
56
|
// src/lib/k8s.ts
|
|
57
57
|
var import_kubernetes_fluent_client = require("kubernetes-fluent-client");
|
|
@@ -7,7 +7,7 @@ import { WebhookType } from "../enums";
|
|
|
7
7
|
export declare class Assets {
|
|
8
8
|
readonly name: string;
|
|
9
9
|
readonly tls: TLSOut;
|
|
10
|
-
readonly
|
|
10
|
+
readonly apiPath: string;
|
|
11
11
|
readonly config: ModuleConfig;
|
|
12
12
|
readonly path: string;
|
|
13
13
|
readonly alwaysIgnore: WebhookIgnore;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../src/lib/assets/assets.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AASvC,OAAO,EACL,YAAY,EACZ,8BAA8B,EAC9B,gCAAgC,EACjC,MAAM,kCAAkC,CAAC;AAU1C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,qBAAa,MAAM;IACjB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"assets.d.ts","sourceRoot":"","sources":["../../../src/lib/assets/assets.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACxC,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,QAAQ,CAAC;AASvC,OAAO,EACL,YAAY,EACZ,8BAA8B,EAC9B,gCAAgC,EACjC,MAAM,kCAAkC,CAAC;AAU1C,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAEvC,qBAAa,MAAM;IACjB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,YAAY,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,YAAY,EAAG,aAAa,CAAC;IACtC,QAAQ,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;IACpC,YAAY,EAAG,gBAAgB,EAAE,CAAC;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;gBAEX,MAAM,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM;IAiBnF,MAAM,CACV,cAAc,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,EACzF,KAAK,EAAE,OAAO,EACd,cAAc,CAAC,EAAE,MAAM,GACtB,OAAO,CAAC,IAAI,CAAC;IAQhB,QAAQ,sBACa,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,QAAQ,KAAK,MAAM,QACnF,MAAM,KACX,MAAM,CAA+C;IAExD,aAAa,sBACQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,QAAQ,KAAK,MAAM,QACnF,MAAM,KACX,MAAM,CAA4C;IAErD,OAAO,2BACmB,CACtB,MAAM,EAAE,MAAM,EACd,WAAW,EAAE;QAAE,OAAO,EAAE,YAAY,CAAC;QAAC,KAAK,EAAE,YAAY,GAAG,IAAI,CAAA;KAAE,KAC/D,OAAO,CAAC,MAAM,CAAC,oBACF,MAAM,KACvB,OAAO,CAAC,MAAM,CAAC,CAiBhB;IAEF,iBAAiB,oBACE,8BAA8B,GAAG,gCAAgC,GAAG,IAAI,iBAC1E,8BAA8B,GAAG,gCAAgC,GAAG,IAAI,QACjF,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,KAC3C,OAAO,CAAC,IAAI,CAAC,CAad;IAEF,iBAAiB,6BACW,CACxB,MAAM,EAAE,MAAM,EACd,gBAAgB,EAAE,WAAW,EAC7B,cAAc,EAAE,MAAM,GAAG,SAAS,KAC/B,OAAO,CAAC,8BAA8B,GAAG,gCAAgC,GAAG,IAAI,CAAC,YAC5E,MAAM,KACf,OAAO,CAAC,IAAI,CAAC,CAuDd;CACH"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { kind } from "kubernetes-fluent-client";
|
|
2
2
|
import { TLSOut } from "../tls";
|
|
3
|
-
export declare function
|
|
3
|
+
export declare function apiPathSecret(name: string, apiPath: string): kind.Secret;
|
|
4
4
|
export declare function tlsSecret(name: string, tls: TLSOut): kind.Secret;
|
|
5
5
|
export declare function service(name: string): kind.Service;
|
|
6
6
|
export declare function watcherService(name: string): kind.Service;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"networking.d.ts","sourceRoot":"","sources":["../../../src/lib/assets/networking.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAEhD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,wBAAgB,
|
|
1
|
+
{"version":3,"file":"networking.d.ts","sourceRoot":"","sources":["../../../src/lib/assets/networking.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAEhD,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAEhC,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC,MAAM,CAaxE;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,MAAM,CAchE;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,OAAO,CAwBlD;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC,OAAO,CAwBzD"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { ModuleConfig } from "../../types";
|
|
2
2
|
import { CapabilityExport } from "../../types";
|
|
3
3
|
type ChartOverrides = {
|
|
4
|
-
|
|
4
|
+
apiPath: string;
|
|
5
5
|
capabilities: CapabilityExport[];
|
|
6
6
|
config: ModuleConfig;
|
|
7
7
|
hash: string;
|
|
8
8
|
name: string;
|
|
9
9
|
image: string;
|
|
10
10
|
};
|
|
11
|
-
export declare function overridesFile({ hash, name, image, config,
|
|
11
|
+
export declare function overridesFile({ hash, name, image, config, apiPath, capabilities }: ChartOverrides, path: string, imagePullSecrets: string[]): Promise<void>;
|
|
12
12
|
export {};
|
|
13
13
|
//# sourceMappingURL=overridesFile.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overridesFile.d.ts","sourceRoot":"","sources":["../../../../src/lib/assets/yaml/overridesFile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAK/C,KAAK,cAAc,GAAG;IACpB,
|
|
1
|
+
{"version":3,"file":"overridesFile.d.ts","sourceRoot":"","sources":["../../../../src/lib/assets/yaml/overridesFile.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAK/C,KAAK,cAAc,GAAG;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,gBAAgB,EAAE,CAAC;IACjC,MAAM,EAAE,YAAY,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAGF,wBAAsB,aAAa,CACjC,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,cAAc,EACpE,IAAI,EAAE,MAAM,EACZ,gBAAgB,EAAE,MAAM,EAAE,GACzB,OAAO,CAAC,IAAI,CAAC,CA2Jf"}
|
package/dist/lib.js
CHANGED
|
@@ -746,7 +746,7 @@ var MetricsCollector = class {
|
|
|
746
746
|
this.#registry = new import_prom_client.Registry();
|
|
747
747
|
this.#prefix = prefix;
|
|
748
748
|
this.addCounter(this.#metricNames.errors, "Mutation/Validate errors encountered");
|
|
749
|
-
this.addCounter(this.#metricNames.alerts, "Mutation/Validate bad api
|
|
749
|
+
this.addCounter(this.#metricNames.alerts, "Mutation/Validate bad api path received");
|
|
750
750
|
this.addSummary(this.#metricNames.mutate, "Mutation operation summary");
|
|
751
751
|
this.addSummary(this.#metricNames.validate, "Validation operation summary");
|
|
752
752
|
this.addGauge(this.#metricNames.cacheMiss, "Number of cache misses per window", ["window"]);
|
|
@@ -1825,8 +1825,8 @@ var Controller = class _Controller {
|
|
|
1825
1825
|
#running = false;
|
|
1826
1826
|
// Metrics collector
|
|
1827
1827
|
#metricsCollector = metricsCollector;
|
|
1828
|
-
// The
|
|
1829
|
-
#
|
|
1828
|
+
// The path used to authenticate requests
|
|
1829
|
+
#path = "";
|
|
1830
1830
|
// The express app instance
|
|
1831
1831
|
#app = (0, import_express.default)();
|
|
1832
1832
|
// Initialized with the constructor
|
|
@@ -1869,10 +1869,10 @@ var Controller = class _Controller {
|
|
|
1869
1869
|
cert: import_fs.default.readFileSync(process.env.SSL_CERT_PATH || "/etc/certs/tls.crt")
|
|
1870
1870
|
};
|
|
1871
1871
|
if (!isWatchMode()) {
|
|
1872
|
-
this.#
|
|
1873
|
-
logger_default.info(`Using API
|
|
1874
|
-
if (!this.#
|
|
1875
|
-
throw new Error("API
|
|
1872
|
+
this.#path = process.env.PEPR_API_PATH || import_fs.default.readFileSync("/app/api-path/value").toString().trim();
|
|
1873
|
+
logger_default.info(`Using API path: ${this.#path}`);
|
|
1874
|
+
if (!this.#path) {
|
|
1875
|
+
throw new Error("API path not found");
|
|
1876
1876
|
}
|
|
1877
1877
|
}
|
|
1878
1878
|
const server = import_https.default.createServer(options, this.#app).listen(port);
|
|
@@ -1905,22 +1905,22 @@ var Controller = class _Controller {
|
|
|
1905
1905
|
if (isWatchMode()) {
|
|
1906
1906
|
return;
|
|
1907
1907
|
}
|
|
1908
|
-
this.#app.use(["/mutate/:
|
|
1909
|
-
this.#app.post("/mutate/:
|
|
1910
|
-
this.#app.post("/validate/:
|
|
1908
|
+
this.#app.use(["/mutate/:path", "/validate/:path"], this.#validatepath);
|
|
1909
|
+
this.#app.post("/mutate/:path", this.#admissionReq("Mutate"));
|
|
1910
|
+
this.#app.post("/validate/:path", this.#admissionReq("Validate"));
|
|
1911
1911
|
};
|
|
1912
1912
|
/**
|
|
1913
|
-
* Validate the
|
|
1913
|
+
* Validate the path in the request path
|
|
1914
1914
|
*
|
|
1915
1915
|
* @param req The incoming request
|
|
1916
1916
|
* @param res The outgoing response
|
|
1917
1917
|
* @param next The next middleware function
|
|
1918
1918
|
* @returns
|
|
1919
1919
|
*/
|
|
1920
|
-
#
|
|
1921
|
-
const {
|
|
1922
|
-
if (
|
|
1923
|
-
const err = `Unauthorized: invalid
|
|
1920
|
+
#validatepath = (req, res, next) => {
|
|
1921
|
+
const { path } = req.params;
|
|
1922
|
+
if (path !== this.#path) {
|
|
1923
|
+
const err = `Unauthorized: invalid path '${path.replace(/[^\w]/g, "_")}'`;
|
|
1924
1924
|
logger_default.info(err);
|
|
1925
1925
|
res.status(401).send(err);
|
|
1926
1926
|
this.#metricsCollector.alert();
|