pepr 0.32.7 → 0.34.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.
Files changed (143) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +2 -1
  3. package/dist/cli/banner.d.ts +2 -0
  4. package/dist/cli/banner.d.ts.map +1 -0
  5. package/dist/cli/build.d.ts +19 -0
  6. package/dist/cli/build.d.ts.map +1 -0
  7. package/dist/cli/deploy.d.ts +3 -0
  8. package/dist/cli/deploy.d.ts.map +1 -0
  9. package/dist/cli/dev.d.ts +3 -0
  10. package/dist/cli/dev.d.ts.map +1 -0
  11. package/dist/cli/format.d.ts +9 -0
  12. package/dist/cli/format.d.ts.map +1 -0
  13. package/dist/cli/init/index.d.ts +3 -0
  14. package/dist/cli/init/index.d.ts.map +1 -0
  15. package/dist/cli/init/templates.d.ts +196 -0
  16. package/dist/cli/init/templates.d.ts.map +1 -0
  17. package/dist/cli/init/utils.d.ts +21 -0
  18. package/dist/cli/init/utils.d.ts.map +1 -0
  19. package/dist/cli/init/utils.test.d.ts +2 -0
  20. package/dist/cli/init/utils.test.d.ts.map +1 -0
  21. package/dist/cli/init/walkthrough.d.ts +8 -0
  22. package/dist/cli/init/walkthrough.d.ts.map +1 -0
  23. package/dist/cli/init/walkthrough.test.d.ts +2 -0
  24. package/dist/cli/init/walkthrough.test.d.ts.map +1 -0
  25. package/dist/cli/kfc.d.ts +3 -0
  26. package/dist/cli/kfc.d.ts.map +1 -0
  27. package/dist/cli/monitor.d.ts +3 -0
  28. package/dist/cli/monitor.d.ts.map +1 -0
  29. package/dist/cli/root.d.ts +5 -0
  30. package/dist/cli/root.d.ts.map +1 -0
  31. package/dist/cli/update.d.ts +3 -0
  32. package/dist/cli/update.d.ts.map +1 -0
  33. package/dist/cli/uuid.d.ts +3 -0
  34. package/dist/cli/uuid.d.ts.map +1 -0
  35. package/dist/cli.js +66 -25
  36. package/dist/controller.js +1 -1
  37. package/dist/fixtures/loader.d.ts +5 -0
  38. package/dist/fixtures/loader.d.ts.map +1 -0
  39. package/dist/lib/assets/helm.d.ts +1 -0
  40. package/dist/lib/assets/helm.d.ts.map +1 -1
  41. package/dist/lib/assets/helm.test.d.ts +2 -0
  42. package/dist/lib/assets/helm.test.d.ts.map +1 -0
  43. package/dist/lib/assets/index.d.ts.map +1 -1
  44. package/dist/lib/assets/pods.d.ts +3 -0
  45. package/dist/lib/assets/pods.d.ts.map +1 -1
  46. package/dist/lib/assets/pods.test.d.ts +2 -0
  47. package/dist/lib/assets/pods.test.d.ts.map +1 -0
  48. package/dist/lib/assets/yaml.d.ts.map +1 -1
  49. package/dist/lib/controller/store.d.ts.map +1 -1
  50. package/dist/lib/errors.test.d.ts +2 -0
  51. package/dist/lib/errors.test.d.ts.map +1 -0
  52. package/dist/lib/filter.test.d.ts +2 -0
  53. package/dist/lib/filter.test.d.ts.map +1 -0
  54. package/dist/lib/helpers.test.d.ts +2 -0
  55. package/dist/lib/helpers.test.d.ts.map +1 -0
  56. package/dist/lib/included-files.test.d.ts +2 -0
  57. package/dist/lib/included-files.test.d.ts.map +1 -0
  58. package/dist/lib/logger.test.d.ts +2 -0
  59. package/dist/lib/logger.test.d.ts.map +1 -0
  60. package/dist/lib/metrics.d.ts +18 -0
  61. package/dist/lib/metrics.d.ts.map +1 -1
  62. package/dist/lib/metrics.test.d.ts +2 -0
  63. package/dist/lib/metrics.test.d.ts.map +1 -0
  64. package/dist/lib/module.test.d.ts +2 -0
  65. package/dist/lib/module.test.d.ts.map +1 -0
  66. package/dist/lib/mutate-request.test.d.ts +2 -0
  67. package/dist/lib/mutate-request.test.d.ts.map +1 -0
  68. package/dist/lib/queue.test.d.ts +2 -0
  69. package/dist/lib/queue.test.d.ts.map +1 -0
  70. package/dist/lib/schedule.test.d.ts +15 -0
  71. package/dist/lib/schedule.test.d.ts.map +1 -0
  72. package/dist/lib/storage.d.ts +2 -0
  73. package/dist/lib/storage.d.ts.map +1 -1
  74. package/dist/lib/storage.test.d.ts +2 -0
  75. package/dist/lib/storage.test.d.ts.map +1 -0
  76. package/dist/lib/tls.test.d.ts +2 -0
  77. package/dist/lib/tls.test.d.ts.map +1 -0
  78. package/dist/lib/utils.test.d.ts +2 -0
  79. package/dist/lib/utils.test.d.ts.map +1 -0
  80. package/dist/lib/validate-request.test.d.ts +2 -0
  81. package/dist/lib/validate-request.test.d.ts.map +1 -0
  82. package/dist/lib/watch-processor.d.ts.map +1 -1
  83. package/dist/lib/watch-processor.test.d.ts +2 -0
  84. package/dist/lib/watch-processor.test.d.ts.map +1 -0
  85. package/dist/lib.js +142 -20
  86. package/dist/lib.js.map +3 -3
  87. package/dist/sdk/sdk.test.d.ts +2 -0
  88. package/dist/sdk/sdk.test.d.ts.map +1 -0
  89. package/package.json +26 -17
  90. package/src/cli/banner.ts +63 -0
  91. package/src/cli/build.ts +370 -0
  92. package/src/cli/deploy.ts +105 -0
  93. package/src/cli/dev.ts +118 -0
  94. package/src/cli/format.ts +83 -0
  95. package/src/cli/init/index.ts +99 -0
  96. package/src/cli/init/templates.ts +124 -0
  97. package/src/cli/init/utils.test.ts +28 -0
  98. package/src/cli/init/utils.ts +55 -0
  99. package/src/cli/init/walkthrough.test.ts +21 -0
  100. package/src/cli/init/walkthrough.ts +96 -0
  101. package/src/cli/kfc.ts +45 -0
  102. package/src/cli/monitor.ts +101 -0
  103. package/src/cli/root.ts +12 -0
  104. package/src/cli/update.ts +95 -0
  105. package/src/cli/uuid.ts +44 -0
  106. package/src/fixtures/data/create-pod.json +271 -0
  107. package/src/fixtures/data/delete-pod.json +271 -0
  108. package/src/fixtures/loader.ts +18 -0
  109. package/src/lib/.prettierrc +14 -0
  110. package/src/lib/assets/helm.test.ts +64 -0
  111. package/src/lib/assets/helm.ts +35 -0
  112. package/src/lib/assets/index.ts +5 -1
  113. package/src/lib/assets/pods.test.ts +553 -0
  114. package/src/lib/assets/pods.ts +14 -6
  115. package/src/lib/assets/yaml.ts +15 -18
  116. package/src/lib/controller/index.ts +2 -2
  117. package/src/lib/controller/store.ts +88 -2
  118. package/src/lib/errors.test.ts +85 -0
  119. package/src/lib/filter.test.ts +384 -0
  120. package/src/lib/helpers.test.ts +1192 -0
  121. package/src/lib/included-files.test.ts +22 -0
  122. package/src/lib/logger.test.ts +18 -0
  123. package/src/lib/metrics.test.ts +132 -0
  124. package/src/lib/metrics.ts +68 -6
  125. package/src/lib/module.test.ts +126 -0
  126. package/src/lib/mutate-request.test.ts +188 -0
  127. package/src/lib/queue.test.ts +58 -0
  128. package/src/lib/schedule.test.ts +217 -0
  129. package/src/lib/storage.test.ts +203 -0
  130. package/src/lib/storage.ts +22 -9
  131. package/src/lib/tls.test.ts +18 -0
  132. package/src/lib/utils.test.ts +69 -0
  133. package/src/lib/validate-request.test.ts +124 -0
  134. package/src/lib/watch-processor.test.ts +322 -0
  135. package/src/lib/watch-processor.ts +20 -4
  136. package/src/sdk/sdk.test.ts +243 -0
  137. package/src/templates/.eslintrc.json +6 -0
  138. package/.prettierignore +0 -1
  139. package/CODE_OF_CONDUCT.md +0 -133
  140. package/SECURITY.md +0 -18
  141. package/SUPPORT.md +0 -16
  142. package/codecov.yaml +0 -19
  143. package/commitlint.config.js +0 -1
@@ -105,6 +105,10 @@ export function watcherDeployTemplate(buildTimestamp: string) {
105
105
  {{- toYaml .Values.watcher.resources | nindent 12 }}
106
106
  env:
107
107
  {{- toYaml .Values.watcher.env | nindent 12 }}
108
+ - name: PEPR_WATCH_MODE
109
+ value: "true"
110
+ envFrom:
111
+ {{- toYaml .Values.watcher.envFrom | nindent 12 }}
108
112
  securityContext:
109
113
  {{- toYaml .Values.watcher.containerSecurityContext | nindent 12 }}
110
114
  volumeMounts:
@@ -187,6 +191,10 @@ export function admissionDeployTemplate(buildTimestamp: string) {
187
191
  {{- toYaml .Values.admission.resources | nindent 12 }}
188
192
  env:
189
193
  {{- toYaml .Values.admission.env | nindent 12 }}
194
+ - name: PEPR_WATCH_MODE
195
+ value: "false"
196
+ envFrom:
197
+ {{- toYaml .Values.admission.envFrom | nindent 12 }}
190
198
  securityContext:
191
199
  {{- toYaml .Values.admission.containerSecurityContext | nindent 12 }}
192
200
  volumeMounts:
@@ -217,3 +225,30 @@ export function admissionDeployTemplate(buildTimestamp: string) {
217
225
  {{- end }}
218
226
  `;
219
227
  }
228
+
229
+ export function serviceMonitorTemplate(name: string) {
230
+ return `
231
+ {{- if .Values.${name}.serviceMonitor.enabled }}
232
+ apiVersion: monitoring.coreos.com/v1
233
+ kind: ServiceMonitor
234
+ metadata:
235
+ name: ${name}
236
+ annotations:
237
+ {{- toYaml .Values.${name}.serviceMonitor.annotations | nindent 4 }}
238
+ labels:
239
+ {{- toYaml .Values.${name}.serviceMonitor.labels | nindent 4 }}
240
+ spec:
241
+ selector:
242
+ matchLabels:
243
+ pepr.dev/controller: ${name}
244
+ namespaceSelector:
245
+ matchNames:
246
+ - pepr-system
247
+ endpoints:
248
+ - targetPort: 3000
249
+ scheme: https
250
+ tlsConfig:
251
+ insecureSkipVerify: true
252
+ {{- end }}
253
+ `;
254
+ }
@@ -13,7 +13,7 @@ import { allYaml, zarfYaml, overridesFile, zarfYamlChart } from "./yaml";
13
13
  import { namespaceComplianceValidator, replaceString } from "../helpers";
14
14
  import { createDirectoryIfNotExists, dedent } from "../helpers";
15
15
  import { resolve } from "path";
16
- import { chartYaml, nsTemplate, admissionDeployTemplate, watcherDeployTemplate } from "./helm";
16
+ import { chartYaml, nsTemplate, admissionDeployTemplate, watcherDeployTemplate, serviceMonitorTemplate } from "./helm";
17
17
  import { promises as fs } from "fs";
18
18
  import { webhookConfig } from "./webhooks";
19
19
  import { apiTokenSecret, service, tlsSecret, watcherService } from "./networking";
@@ -82,7 +82,9 @@ export class Assets {
82
82
  const mutationWebhookPath = resolve(CHAR_TEMPLATES_DIR, `mutation-webhook.yaml`);
83
83
  const validationWebhookPath = resolve(CHAR_TEMPLATES_DIR, `validation-webhook.yaml`);
84
84
  const admissionDeployPath = resolve(CHAR_TEMPLATES_DIR, `admission-deployment.yaml`);
85
+ const admissionServiceMonitorPath = resolve(CHAR_TEMPLATES_DIR, `admission-service-monitor.yaml`);
85
86
  const watcherDeployPath = resolve(CHAR_TEMPLATES_DIR, `watcher-deployment.yaml`);
87
+ const watcherServiceMonitorPath = resolve(CHAR_TEMPLATES_DIR, `watcher-service-monitor.yaml`);
86
88
  const tlsSecretPath = resolve(CHAR_TEMPLATES_DIR, `tls-secret.yaml`);
87
89
  const apiTokenSecretPath = resolve(CHAR_TEMPLATES_DIR, `api-token-secret.yaml`);
88
90
  const moduleSecretPath = resolve(CHAR_TEMPLATES_DIR, `module-secret.yaml`);
@@ -134,6 +136,7 @@ export class Assets {
134
136
 
135
137
  if (validateWebhook || mutateWebhook) {
136
138
  await fs.writeFile(admissionDeployPath, dedent(admissionDeployTemplate(this.buildTimestamp)));
139
+ await fs.writeFile(admissionServiceMonitorPath, dedent(serviceMonitorTemplate("admission")));
137
140
  }
138
141
 
139
142
  if (mutateWebhook) {
@@ -166,6 +169,7 @@ export class Assets {
166
169
 
167
170
  if (watchDeployment) {
168
171
  await fs.writeFile(watcherDeployPath, dedent(watcherDeployTemplate(this.buildTimestamp)));
172
+ await fs.writeFile(watcherServiceMonitorPath, dedent(serviceMonitorTemplate("watcher")));
169
173
  }
170
174
  } catch (err) {
171
175
  console.error(`Error generating helm chart: ${err.message}`);
@@ -0,0 +1,553 @@
1
+ import { namespace, watcher, deployment, moduleSecret, genEnv } from "./pods";
2
+ import { expect, describe, test, jest, afterEach } from "@jest/globals";
3
+ import { Assets } from ".";
4
+ import { ModuleConfig } from "../module";
5
+ import { gzipSync } from "zlib";
6
+
7
+ jest.mock("zlib");
8
+
9
+ const assets: Assets = JSON.parse(`{
10
+ "config": {
11
+ "uuid": "static-test",
12
+ "onError": "ignore",
13
+ "webhookTimeout": 10,
14
+ "customLabels": {
15
+ "namespace": {
16
+ "pepr.dev": ""
17
+ }
18
+ },
19
+ "alwaysIgnore": {
20
+ "namespaces": []
21
+ },
22
+ "includedFiles": [],
23
+ "env": {
24
+ "MY_CUSTOM_VAR": "example-value",
25
+ "ZARF_VAR": "###ZARF_VAR_THING###"
26
+ },
27
+ "peprVersion": "0.0.0-development",
28
+ "appVersion": "0.0.1",
29
+ "description": "A test module for Pepr"
30
+ },
31
+ "path": "/Users/cmwylie19/pepr/pepr-test-module/dist/pepr-static-test.js",
32
+ "name": "pepr-static-test",
33
+ "tls": {
34
+ "ca": "",
35
+ "key": "",
36
+ "crt": "",
37
+ "pem": {
38
+ "ca": "",
39
+ "crt": "",
40
+ "key": ""
41
+ }
42
+ },
43
+ "apiToken": "db5eb6d40e3744fcc2d7863c8f56ce24aaa94ff32cf22918700bdb9369e6d426",
44
+ "alwaysIgnore": {
45
+ "namespaces": []
46
+ },
47
+ "capabilities": [
48
+ {
49
+ "name": "hello-pepr",
50
+ "description": "A simple example capability to show how things work.",
51
+ "namespaces": [
52
+ "pepr-demo",
53
+ "pepr-demo-2"
54
+ ],
55
+ "bindings": [
56
+ {
57
+ "kind": {
58
+ "kind": "Namespace",
59
+ "version": "v1",
60
+ "group": ""
61
+ },
62
+ "event": "CREATE",
63
+ "filters": {
64
+ "name": "",
65
+ "namespaces": [],
66
+ "labels": {},
67
+ "annotations": {}
68
+ },
69
+ "isMutate": true
70
+ },
71
+ {
72
+ "kind": {
73
+ "kind": "Namespace",
74
+ "version": "v1",
75
+ "group": ""
76
+ },
77
+ "event": "CREATE",
78
+ "filters": {
79
+ "name": "pepr-demo-2",
80
+ "namespaces": [],
81
+ "labels": {},
82
+ "annotations": {}
83
+ },
84
+ "isWatch": true
85
+ },
86
+ {
87
+ "kind": {
88
+ "kind": "ConfigMap",
89
+ "version": "v1",
90
+ "group": ""
91
+ },
92
+ "event": "CREATE",
93
+ "filters": {
94
+ "name": "example-1",
95
+ "namespaces": [],
96
+ "labels": {},
97
+ "annotations": {}
98
+ },
99
+ "isMutate": true
100
+ },
101
+ {
102
+ "kind": {
103
+ "kind": "ConfigMap",
104
+ "version": "v1",
105
+ "group": ""
106
+ },
107
+ "event": "CREATE",
108
+ "filters": {
109
+ "name": "example-2",
110
+ "namespaces": [],
111
+ "labels": {},
112
+ "annotations": {}
113
+ },
114
+ "isMutate": true
115
+ },
116
+ {
117
+ "kind": {
118
+ "kind": "ConfigMap",
119
+ "version": "v1",
120
+ "group": ""
121
+ },
122
+ "event": "CREATE",
123
+ "filters": {
124
+ "name": "example-2",
125
+ "namespaces": [],
126
+ "labels": {},
127
+ "annotations": {}
128
+ },
129
+ "isValidate": true
130
+ },
131
+ {
132
+ "kind": {
133
+ "kind": "ConfigMap",
134
+ "version": "v1",
135
+ "group": ""
136
+ },
137
+ "event": "CREATE",
138
+ "filters": {
139
+ "name": "example-2",
140
+ "namespaces": [],
141
+ "labels": {},
142
+ "annotations": {}
143
+ },
144
+ "isWatch": true
145
+ },
146
+ {
147
+ "kind": {
148
+ "kind": "ConfigMap",
149
+ "version": "v1",
150
+ "group": ""
151
+ },
152
+ "event": "CREATE",
153
+ "filters": {
154
+ "name": "",
155
+ "namespaces": [],
156
+ "labels": {},
157
+ "annotations": {}
158
+ },
159
+ "isValidate": true
160
+ },
161
+ {
162
+ "kind": {
163
+ "kind": "ConfigMap",
164
+ "version": "v1",
165
+ "group": ""
166
+ },
167
+ "event": "CREATEORUPDATE",
168
+ "filters": {
169
+ "name": "",
170
+ "namespaces": [],
171
+ "labels": {
172
+ "change": "by-label"
173
+ },
174
+ "annotations": {}
175
+ },
176
+ "isMutate": true
177
+ },
178
+ {
179
+ "kind": {
180
+ "kind": "ConfigMap",
181
+ "version": "v1",
182
+ "group": ""
183
+ },
184
+ "event": "DELETE",
185
+ "filters": {
186
+ "name": "",
187
+ "namespaces": [],
188
+ "labels": {
189
+ "change": "by-label"
190
+ },
191
+ "annotations": {}
192
+ },
193
+ "isValidate": true
194
+ },
195
+ {
196
+ "kind": {
197
+ "kind": "ConfigMap",
198
+ "version": "v1",
199
+ "group": ""
200
+ },
201
+ "event": "CREATE",
202
+ "filters": {
203
+ "name": "example-4",
204
+ "namespaces": [],
205
+ "labels": {},
206
+ "annotations": {}
207
+ },
208
+ "isMutate": true
209
+ },
210
+ {
211
+ "kind": {
212
+ "kind": "ConfigMap",
213
+ "version": "v1",
214
+ "group": ""
215
+ },
216
+ "event": "CREATE",
217
+ "filters": {
218
+ "name": "example-4a",
219
+ "namespaces": [
220
+ "pepr-demo-2"
221
+ ],
222
+ "labels": {},
223
+ "annotations": {}
224
+ },
225
+ "isMutate": true
226
+ },
227
+ {
228
+ "kind": {
229
+ "kind": "ConfigMap",
230
+ "version": "v1",
231
+ "group": ""
232
+ },
233
+ "event": "CREATE",
234
+ "filters": {
235
+ "name": "",
236
+ "namespaces": [],
237
+ "labels": {
238
+ "chuck-norris": ""
239
+ },
240
+ "annotations": {}
241
+ },
242
+ "isMutate": true
243
+ },
244
+ {
245
+ "kind": {
246
+ "kind": "Secret",
247
+ "version": "v1",
248
+ "group": ""
249
+ },
250
+ "event": "CREATE",
251
+ "filters": {
252
+ "name": "secret-1",
253
+ "namespaces": [],
254
+ "labels": {},
255
+ "annotations": {}
256
+ },
257
+ "isMutate": true
258
+ },
259
+ {
260
+ "kind": {
261
+ "group": "pepr.dev",
262
+ "version": "v1",
263
+ "kind": "Unicorn"
264
+ },
265
+ "event": "CREATE",
266
+ "filters": {
267
+ "name": "example-1",
268
+ "namespaces": [],
269
+ "labels": {},
270
+ "annotations": {}
271
+ },
272
+ "isMutate": true
273
+ },
274
+ {
275
+ "kind": {
276
+ "group": "pepr.dev",
277
+ "version": "v1",
278
+ "kind": "Unicorn"
279
+ },
280
+ "event": "CREATE",
281
+ "filters": {
282
+ "name": "example-2",
283
+ "namespaces": [],
284
+ "labels": {},
285
+ "annotations": {}
286
+ },
287
+ "isMutate": true
288
+ }
289
+ ],
290
+ "hasSchedule": false
291
+ }
292
+ ],
293
+ "image": "ghcr.io/defenseunicorns/pepr/controller:v0.0.0-development",
294
+ "buildTimestamp": "1721936569867",
295
+ "hash": "e303205079a4445946f6eacde9ec4800534653f85aca6f84539d0f7158a22569"
296
+ }`);
297
+ describe("namespace function", () => {
298
+ test("should create a namespace object without labels if none are provided", () => {
299
+ const result = namespace();
300
+ expect(result).toEqual({
301
+ apiVersion: "v1",
302
+ kind: "Namespace",
303
+ metadata: {
304
+ name: "pepr-system",
305
+ },
306
+ });
307
+ const result1 = namespace({ one: "two" });
308
+ expect(result1).toEqual({
309
+ apiVersion: "v1",
310
+ kind: "Namespace",
311
+ metadata: {
312
+ name: "pepr-system",
313
+ labels: {
314
+ one: "two",
315
+ },
316
+ },
317
+ });
318
+ });
319
+
320
+ test("should create a namespace object with empty labels if an empty object is provided", () => {
321
+ const result = namespace({});
322
+ expect(result.metadata.labels).toEqual({});
323
+ });
324
+
325
+ test("should create a namespace object with provided labels", () => {
326
+ const labels = { "pepr.dev/controller": "admission", "istio-injection": "enabled" };
327
+ const result = namespace(labels);
328
+ expect(result.metadata.labels).toEqual(labels);
329
+ });
330
+ });
331
+
332
+ describe("watcher function", () => {
333
+ test("watcher with bindings", () => {
334
+ const result = watcher(assets, "test-hash", "test-timestamp");
335
+
336
+ expect(result).toBeTruthy();
337
+ expect(result!.metadata!.name).toBe("pepr-static-test-watcher");
338
+ });
339
+
340
+ test("watcher without bindings", () => {
341
+ assets.capabilities = [];
342
+ const result = watcher(assets, "test-hash", "test-timestamp");
343
+
344
+ expect(result).toBeNull();
345
+ });
346
+ });
347
+ describe("deployment function", () => {
348
+ test("deployment", () => {
349
+ const result = deployment(assets, "test-hash", "test-timestamp");
350
+
351
+ expect(result).toBeTruthy();
352
+ expect(result!.metadata!.name).toBe("pepr-static-test");
353
+ });
354
+ });
355
+ describe("moduleSecret function", () => {
356
+ afterEach(() => {
357
+ jest.resetAllMocks();
358
+ });
359
+
360
+ test("moduleSecret within limit", () => {
361
+ const name = "test";
362
+ const data = Buffer.from("test data");
363
+ const hash = "test-hash";
364
+ const compressedData = Buffer.from("compressed data").toString("base64");
365
+
366
+ // Mock the return value of gzipSync
367
+ (gzipSync as jest.Mock).mockReturnValue(Buffer.from(compressedData));
368
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
369
+ jest.spyOn(require("../helpers"), "secretOverLimit").mockReturnValue(false);
370
+
371
+ const result = moduleSecret(name, data, hash);
372
+
373
+ expect(result).toEqual({
374
+ apiVersion: "v1",
375
+ kind: "Secret",
376
+ metadata: {
377
+ name: "test-module",
378
+ namespace: "pepr-system",
379
+ },
380
+ type: "Opaque",
381
+ data: {
382
+ [`module-${hash}.js.gz`]: "WTI5dGNISmxjM05sWkNCa1lYUmg=",
383
+ },
384
+ });
385
+ });
386
+
387
+ test("moduleSecret over limit", () => {
388
+ const name = "test";
389
+ const data = Buffer.from("test data");
390
+ const hash = "test-hash";
391
+
392
+ // Mock the return value of gzipSync
393
+ (gzipSync as jest.Mock).mockReturnValue(data);
394
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
395
+ jest.spyOn(require("../helpers"), "secretOverLimit").mockReturnValue(true);
396
+
397
+ const consoleErrorMock = jest.spyOn(console, "error").mockImplementation(() => {});
398
+ const processExitMock = jest.spyOn(process, "exit").mockImplementation(() => {
399
+ throw new Error("process.exit");
400
+ });
401
+
402
+ expect(() => moduleSecret(name, data, hash)).toThrow("process.exit");
403
+
404
+ expect(consoleErrorMock).toHaveBeenCalledWith(
405
+ "Uncaught Exception:",
406
+ new Error(`Module secret for ${name} is over the 1MB limit`),
407
+ );
408
+
409
+ consoleErrorMock.mockRestore();
410
+ processExitMock.mockRestore();
411
+ });
412
+ });
413
+
414
+ describe("genEnv", () => {
415
+ test("generates default environment variables without watch mode", () => {
416
+ const config: ModuleConfig = {
417
+ uuid: "12345",
418
+ alwaysIgnore: {
419
+ namespaces: [],
420
+ },
421
+ };
422
+
423
+ const expectedEnv = [
424
+ { name: "PEPR_WATCH_MODE", value: "false" },
425
+ { name: "PEPR_PRETTY_LOG", value: "false" },
426
+ { name: "LOG_LEVEL", value: "info" },
427
+ ];
428
+
429
+ const result = genEnv(config);
430
+
431
+ expect(result).toEqual(expectedEnv);
432
+ });
433
+
434
+ test("generates default environment variables with watch mode", () => {
435
+ const config: ModuleConfig = {
436
+ uuid: "12345",
437
+ alwaysIgnore: {
438
+ namespaces: [],
439
+ },
440
+ };
441
+
442
+ const expectedEnv = [
443
+ { name: "PEPR_WATCH_MODE", value: "true" },
444
+ { name: "PEPR_PRETTY_LOG", value: "false" },
445
+ { name: "LOG_LEVEL", value: "info" },
446
+ ];
447
+
448
+ const result = genEnv(config, true);
449
+
450
+ expect(result).toEqual(expectedEnv);
451
+ });
452
+
453
+ test("overrides default environment variables with config.env", () => {
454
+ const config: ModuleConfig = {
455
+ uuid: "12345",
456
+ logLevel: "debug",
457
+ env: {
458
+ CUSTOM_ENV_VAR: "custom_value",
459
+ },
460
+ alwaysIgnore: {
461
+ namespaces: [],
462
+ },
463
+ };
464
+
465
+ const expectedEnv = [
466
+ { name: "PEPR_WATCH_MODE", value: "false" },
467
+ { name: "PEPR_PRETTY_LOG", value: "false" },
468
+ { name: "LOG_LEVEL", value: "debug" },
469
+ { name: "CUSTOM_ENV_VAR", value: "custom_value" },
470
+ ];
471
+
472
+ const result = genEnv(config);
473
+
474
+ expect(result).toEqual(expectedEnv);
475
+ });
476
+
477
+ test("handles empty config.env correctly", () => {
478
+ const config: ModuleConfig = {
479
+ uuid: "12345",
480
+ logLevel: "error",
481
+ env: {},
482
+ alwaysIgnore: {
483
+ namespaces: [],
484
+ },
485
+ };
486
+
487
+ const expectedEnv = [
488
+ { name: "PEPR_WATCH_MODE", value: "false" },
489
+ { name: "PEPR_PRETTY_LOG", value: "false" },
490
+ { name: "LOG_LEVEL", value: "error" },
491
+ ];
492
+
493
+ const result = genEnv(config);
494
+
495
+ expect(result).toEqual(expectedEnv);
496
+ });
497
+
498
+ test("should not be able to override PEPR_WATCH_MODE in package.json pepr env", () => {
499
+ const config: ModuleConfig = {
500
+ uuid: "12345",
501
+ logLevel: "error",
502
+ env: {
503
+ PEPR_WATCH_MODE: "false",
504
+ },
505
+ alwaysIgnore: {
506
+ namespaces: [],
507
+ },
508
+ };
509
+
510
+ const result = genEnv(config, true);
511
+ const watchMode = result.filter(env => env.name === "PEPR_WATCH_MODE")[0];
512
+ expect(watchMode.value).toEqual("true");
513
+ });
514
+
515
+ test("handles no config.env correctly", () => {
516
+ const config: ModuleConfig = {
517
+ uuid: "12345",
518
+ logLevel: "error",
519
+ alwaysIgnore: {
520
+ namespaces: [],
521
+ },
522
+ };
523
+
524
+ const expectedEnv = [
525
+ { name: "PEPR_WATCH_MODE", value: "false" },
526
+ { name: "PEPR_PRETTY_LOG", value: "false" },
527
+ { name: "LOG_LEVEL", value: "error" },
528
+ ];
529
+
530
+ const result = genEnv(config);
531
+
532
+ expect(result).toEqual(expectedEnv);
533
+ });
534
+
535
+ test("handles ignoreWatchMode for helm chart", () => {
536
+ const config: ModuleConfig = {
537
+ uuid: "12345",
538
+ logLevel: "error",
539
+ alwaysIgnore: {
540
+ namespaces: [],
541
+ },
542
+ };
543
+
544
+ const expectedEnv = [
545
+ { name: "PEPR_PRETTY_LOG", value: "false" },
546
+ { name: "LOG_LEVEL", value: "error" },
547
+ ];
548
+
549
+ const result = genEnv(config, false, true);
550
+
551
+ expect(result).toEqual(expectedEnv);
552
+ });
553
+ });
@@ -357,14 +357,22 @@ export function moduleSecret(name: string, data: Buffer, hash: string): kind.Sec
357
357
  }
358
358
  }
359
359
 
360
- function genEnv(config: ModuleConfig, watchMode = false): V1EnvVar[] {
361
- const def = {
362
- PEPR_WATCH_MODE: watchMode ? "true" : "false",
360
+ export function genEnv(config: ModuleConfig, watchMode = false, ignoreWatchMode = false): V1EnvVar[] {
361
+ const noWatchDef = {
363
362
  PEPR_PRETTY_LOG: "false",
364
363
  LOG_LEVEL: config.logLevel || "info",
365
364
  };
366
- const cfg = config.env || {};
367
- const env = Object.entries({ ...def, ...cfg }).map(([name, value]) => ({ name, value }));
368
365
 
369
- return env;
366
+ const def = {
367
+ PEPR_WATCH_MODE: watchMode ? "true" : "false",
368
+ ...noWatchDef,
369
+ };
370
+
371
+ if (config.env && config.env["PEPR_WATCH_MODE"]) {
372
+ delete config.env["PEPR_WATCH_MODE"];
373
+ }
374
+ const cfg = config.env || {};
375
+ return ignoreWatchMode
376
+ ? Object.entries({ ...noWatchDef, ...cfg }).map(([name, value]) => ({ name, value }))
377
+ : Object.entries({ ...def, ...cfg }).map(([name, value]) => ({ name, value }));
370
378
  }