@highstate/k8s 0.9.4 → 0.9.6

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 (63) hide show
  1. package/dist/chunk-DQSCJM5S.js +183 -0
  2. package/dist/chunk-DQSCJM5S.js.map +1 -0
  3. package/dist/chunk-FKNHHKOL.js +260 -0
  4. package/dist/chunk-FKNHHKOL.js.map +1 -0
  5. package/dist/chunk-HW3NS3MC.js +347 -0
  6. package/dist/chunk-HW3NS3MC.js.map +1 -0
  7. package/dist/chunk-OQ7UXASD.js +193 -0
  8. package/dist/chunk-OQ7UXASD.js.map +1 -0
  9. package/dist/chunk-QGHMLKTW.js +1123 -0
  10. package/dist/chunk-QGHMLKTW.js.map +1 -0
  11. package/dist/chunk-UNVSWG6D.js +214 -0
  12. package/dist/chunk-UNVSWG6D.js.map +1 -0
  13. package/dist/deployment-ZP3ASKPT.js +10 -0
  14. package/dist/deployment-ZP3ASKPT.js.map +1 -0
  15. package/dist/highstate.manifest.json +8 -6
  16. package/dist/index.js +291 -954
  17. package/dist/index.js.map +1 -1
  18. package/dist/stateful-set-2AH7RAF7.js +10 -0
  19. package/dist/stateful-set-2AH7RAF7.js.map +1 -0
  20. package/dist/units/access-point/index.js +6 -1
  21. package/dist/units/access-point/index.js.map +1 -1
  22. package/dist/units/cert-manager/index.js +19 -24
  23. package/dist/units/cert-manager/index.js.map +1 -1
  24. package/dist/units/cluster-dns/index.js +36 -0
  25. package/dist/units/cluster-dns/index.js.map +1 -0
  26. package/dist/units/cluster-patch/index.js +34 -0
  27. package/dist/units/cluster-patch/index.js.map +1 -0
  28. package/dist/units/dns01-issuer/index.js +2 -2
  29. package/dist/units/dns01-issuer/index.js.map +1 -1
  30. package/dist/units/existing-cluster/index.js +22 -14
  31. package/dist/units/existing-cluster/index.js.map +1 -1
  32. package/dist/units/gateway-api/index.js +1 -1
  33. package/package.json +12 -10
  34. package/src/access-point.ts +44 -39
  35. package/src/container.ts +54 -5
  36. package/src/cron-job.ts +14 -30
  37. package/src/deployment.ts +170 -127
  38. package/src/gateway/http-route.ts +7 -5
  39. package/src/helm.ts +57 -8
  40. package/src/index.ts +11 -4
  41. package/src/job.ts +14 -32
  42. package/src/namespace.ts +241 -0
  43. package/src/network-policy.ts +371 -87
  44. package/src/network.ts +41 -0
  45. package/src/pvc.ts +43 -25
  46. package/src/scripting/bundle.ts +125 -22
  47. package/src/scripting/container.ts +16 -11
  48. package/src/scripting/environment.ts +56 -6
  49. package/src/secret.ts +195 -0
  50. package/src/service.ts +209 -89
  51. package/src/shared.ts +42 -51
  52. package/src/stateful-set.ts +193 -88
  53. package/src/units/access-point/index.ts +8 -1
  54. package/src/units/cert-manager/index.ts +15 -20
  55. package/src/units/cluster-dns/index.ts +37 -0
  56. package/src/units/cluster-patch/index.ts +35 -0
  57. package/src/units/dns01-issuer/index.ts +1 -1
  58. package/src/units/existing-cluster/index.ts +24 -14
  59. package/src/workload.ts +342 -44
  60. package/dist/chunk-K4WKJ4L5.js +0 -455
  61. package/dist/chunk-K4WKJ4L5.js.map +0 -1
  62. package/dist/chunk-T5Z2M4JE.js +0 -103
  63. package/dist/chunk-T5Z2M4JE.js.map +0 -1
package/dist/index.js CHANGED
@@ -1,861 +1,66 @@
1
+ import {
2
+ StatefulSet
3
+ } from "./chunk-OQ7UXASD.js";
4
+ import {
5
+ Deployment
6
+ } from "./chunk-DQSCJM5S.js";
7
+ import {
8
+ ExposableWorkload,
9
+ NetworkPolicy,
10
+ PersistentVolumeClaim,
11
+ Secret,
12
+ Workload,
13
+ getWorkloadComponents
14
+ } from "./chunk-QGHMLKTW.js";
1
15
  import {
2
16
  Chart,
3
- HttpRoute,
4
17
  RenderedChart,
5
- Service,
6
18
  getChartService,
7
19
  getChartServiceOutput,
20
+ resolveHelmChart
21
+ } from "./chunk-UNVSWG6D.js";
22
+ import {
23
+ HttpRoute,
24
+ Service,
25
+ getServiceMetadata,
26
+ hasServiceMetadata,
27
+ isFromCluster,
8
28
  mapContainerPortToServicePort,
9
29
  mapServiceToLabelSelector,
10
- resolveHelmChart
11
- } from "./chunk-K4WKJ4L5.js";
30
+ withServiceMetadata
31
+ } from "./chunk-HW3NS3MC.js";
12
32
  import {
13
33
  createK8sTerminal,
14
34
  detectExternalIps
15
35
  } from "./chunk-QLQ3QVGT.js";
16
36
  import {
37
+ Namespace,
17
38
  commonExtraArgs,
18
- createNamespace,
19
39
  getAppDisplayName,
20
40
  getAppName,
21
- getNamespace,
22
41
  getProvider,
23
42
  mapMetadata,
24
43
  mapNamespaceLikeToNamespaceName,
25
44
  mapNamespaceNameToSelector,
26
- mapSelectorLikeToSelector,
27
- resourceIdToString,
28
- verifyProvider
29
- } from "./chunk-T5Z2M4JE.js";
30
-
31
- // src/deployment.ts
32
- import {
33
- output as output4,
34
- ComponentResource as ComponentResource3,
35
- interpolate
36
- } from "@highstate/pulumi";
37
- import { apps } from "@pulumi/kubernetes";
38
- import { omit as omit3 } from "remeda";
39
- import { deepmerge as deepmerge2 } from "deepmerge-ts";
40
- import { trimIndentation } from "@highstate/contract";
41
-
42
- // src/container.ts
43
- import { core as core2 } from "@pulumi/kubernetes";
44
- import { normalize, output as output2 } from "@highstate/pulumi";
45
- import { concat, map, omit as omit2 } from "remeda";
46
-
47
- // src/pvc.ts
48
- import { core } from "@pulumi/kubernetes";
49
- import {
50
- ComponentResource,
51
- output
52
- } from "@highstate/pulumi";
53
- import { deepmerge } from "deepmerge-ts";
54
- import { omit } from "remeda";
55
- var extraPersistentVolumeClaimArgs = [...commonExtraArgs, "size", "cluster"];
56
- var PersistentVolumeClaim = class extends ComponentResource {
57
- constructor(type, name, args, opts, clusterInfo, metadata, spec, status) {
58
- super(type, name, args, opts);
59
- this.clusterInfo = clusterInfo;
60
- this.metadata = metadata;
61
- this.spec = spec;
62
- this.status = status;
63
- }
64
- /**
65
- * The Highstate service entity.
66
- */
67
- get entity() {
68
- return output({
69
- type: "k8s.persistent-volume-claim",
70
- clusterInfo: this.clusterInfo,
71
- metadata: this.metadata
72
- });
73
- }
74
- static create(name, args, opts) {
75
- return new CreatedPersistentVolumeClaim(name, args, opts);
76
- }
77
- static of(name, entity, opts) {
78
- return new ExternalPersistentVolumeClaim(
79
- name,
80
- output(entity).metadata,
81
- output(entity).clusterInfo,
82
- opts
83
- );
84
- }
85
- };
86
- var CreatedPersistentVolumeClaim = class extends PersistentVolumeClaim {
87
- constructor(name, args, opts) {
88
- const pvc = output(args).apply((args2) => {
89
- return new core.v1.PersistentVolumeClaim(
90
- name,
91
- {
92
- metadata: mapMetadata(args2, name),
93
- spec: deepmerge(
94
- {
95
- accessModes: ["ReadWriteOnce"],
96
- resources: {
97
- requests: {
98
- storage: args2.size ?? "100Mi"
99
- }
100
- }
101
- },
102
- omit(args2, extraPersistentVolumeClaimArgs)
103
- )
104
- },
105
- opts
106
- );
107
- });
108
- super(
109
- "k8s:PersistentVolumeClaim",
110
- name,
111
- args,
112
- opts,
113
- output(args.cluster).info,
114
- pvc.metadata,
115
- pvc.spec,
116
- pvc.status
117
- );
118
- }
119
- };
120
- var ExternalPersistentVolumeClaim = class extends PersistentVolumeClaim {
121
- constructor(name, id, clusterInfo, opts) {
122
- const pvc = output(id).apply(async (id2) => {
123
- await verifyProvider(opts.provider, this.clusterInfo);
124
- return core.v1.PersistentVolumeClaim.get(
125
- //
126
- name,
127
- resourceIdToString(id2),
128
- { parent: this, provider: opts.provider }
129
- );
130
- });
131
- super(
132
- "highstate:k8s:ExternalPersistentVolumeClaim",
133
- name,
134
- { id, clusterInfo },
135
- opts,
136
- output(clusterInfo),
137
- pvc.metadata,
138
- pvc.spec,
139
- pvc.status
140
- );
141
- }
142
- };
143
-
144
- // src/container.ts
145
- var containerExtraArgs = [
146
- "port",
147
- "volumeMount",
148
- "volume",
149
- "environment",
150
- "environmentSource",
151
- "environmentSources"
152
- ];
153
- function mapContainerToRaw(container, fallbackName) {
154
- const containerName = container.name ?? fallbackName;
155
- return {
156
- ...omit2(container, containerExtraArgs),
157
- name: containerName,
158
- ports: normalize(container.port, container.ports),
159
- volumeMounts: map(normalize(container.volumeMount, container.volumeMounts), mapVolumeMount),
160
- env: concat(
161
- container.environment ? mapContainerEnvironment(container.environment) : [],
162
- container.env ?? []
163
- ),
164
- envFrom: concat(
165
- map(
166
- normalize(container.environmentSource, container.environmentSources),
167
- mapEnvironmentSource
168
- ),
169
- container.envFrom ?? []
170
- )
171
- };
172
- }
173
- function mapContainerEnvironment(environment) {
174
- const envVars = [];
175
- for (const [name, value] of Object.entries(environment)) {
176
- if (!value) {
177
- continue;
178
- }
179
- if (typeof value === "string") {
180
- envVars.push({ name, value });
181
- continue;
182
- }
183
- if ("secret" in value) {
184
- envVars.push({
185
- name,
186
- valueFrom: {
187
- secretKeyRef: {
188
- name: value.secret.metadata.name,
189
- key: value.key
190
- }
191
- }
192
- });
193
- continue;
194
- }
195
- if ("configMap" in value) {
196
- envVars.push({
197
- name,
198
- valueFrom: {
199
- configMapKeyRef: {
200
- name: value.configMap.metadata.name,
201
- key: value.key
202
- }
203
- }
204
- });
205
- continue;
206
- }
207
- envVars.push({ name, valueFrom: value });
208
- }
209
- return envVars;
210
- }
211
- function mapVolumeMount(volumeMount) {
212
- if ("volume" in volumeMount) {
213
- return omit2(
214
- {
215
- ...volumeMount,
216
- name: output2(volumeMount.volume).apply(mapWorkloadVolume).apply((volume) => output2(volume.name))
217
- },
218
- ["volume"]
219
- );
220
- }
221
- return {
222
- ...volumeMount,
223
- name: volumeMount.name
224
- };
225
- }
226
- function mapEnvironmentSource(envFrom) {
227
- if (envFrom instanceof core2.v1.ConfigMap) {
228
- return {
229
- configMapRef: {
230
- name: envFrom.metadata.name
231
- }
232
- };
233
- }
234
- if (envFrom instanceof core2.v1.Secret) {
235
- return {
236
- secretRef: {
237
- name: envFrom.metadata.name
238
- }
239
- };
240
- }
241
- return envFrom;
242
- }
243
- function mapWorkloadVolume(volume) {
244
- if (volume instanceof PersistentVolumeClaim) {
245
- return {
246
- name: volume.metadata.name,
247
- persistentVolumeClaim: {
248
- claimName: volume.metadata.name
249
- }
250
- };
251
- }
252
- if (volume instanceof core2.v1.PersistentVolumeClaim) {
253
- return {
254
- name: volume.metadata.name,
255
- persistentVolumeClaim: {
256
- claimName: volume.metadata.name
257
- }
258
- };
259
- }
260
- if (volume instanceof core2.v1.ConfigMap) {
261
- return {
262
- name: volume.metadata.name,
263
- configMap: {
264
- name: volume.metadata.name
265
- }
266
- };
267
- }
268
- if (volume instanceof core2.v1.Secret) {
269
- return {
270
- name: volume.metadata.name,
271
- secret: {
272
- secretName: volume.metadata.name
273
- }
274
- };
275
- }
276
- return volume;
277
- }
278
-
279
- // src/workload.ts
280
- import { normalize as normalize2 } from "@highstate/pulumi";
281
- import { ComponentResource as ComponentResource2, output as output3 } from "@pulumi/pulumi";
282
- import { uniqueBy } from "remeda";
283
- var workloadExtraArgs = [...commonExtraArgs, "container", "containers"];
284
- var publicWorkloadExtraArgs = [...workloadExtraArgs, "service", "httpRoute"];
285
- function getWorkloadComponents(name, args) {
286
- const labels = {
287
- "app.kubernetes.io/name": name
288
- };
289
- const containers = output3(args).apply((args2) => normalize2(args2.container, args2.containers));
290
- const volumes = containers.apply((containers2) => {
291
- const containerVolumes = containers2.flatMap((container) => normalize2(container.volume, container.volumes)).map(mapWorkloadVolume);
292
- const containerVolumeMounts = containers2.flatMap((container) => {
293
- return normalize2(container.volumeMount, container.volumeMounts).map((volumeMount) => {
294
- return "volume" in volumeMount ? volumeMount.volume : void 0;
295
- }).filter(Boolean);
296
- }).map(mapWorkloadVolume);
297
- return uniqueBy([...containerVolumes, ...containerVolumeMounts], (volume) => volume.name);
298
- });
299
- return { labels, containers, volumes };
300
- }
301
- function getPublicWorkloadComponents(name, args, parent, opts) {
302
- const { labels, containers, volumes } = getWorkloadComponents(name, args);
303
- const service = output3({ args, containers }).apply(({ args: args2, containers: containers2 }) => {
304
- if (!args2.service && !args2.httpRoute) {
305
- return void 0;
306
- }
307
- if (args2.patch?.service) {
308
- return Service.of(name, args2.patch.service, { parent: parent(), ...opts });
309
- }
310
- if (args2.patch) {
311
- return void 0;
312
- }
313
- const ports = containers2.flatMap((container) => normalize2(container.port, container.ports));
314
- return Service.create(
315
- name,
316
- {
317
- ...args2.service,
318
- selector: labels,
319
- cluster: args2.cluster,
320
- namespace: args2.namespace,
321
- ports: (
322
- // allow to completely override the ports
323
- !args2.service?.port && !args2.service?.ports ? ports.map(mapContainerPortToServicePort) : args2.service?.ports
324
- )
325
- },
326
- { parent: parent(), ...opts }
327
- );
328
- });
329
- const httpRoute = output3({
330
- args,
331
- service
332
- }).apply(({ args: args2, service: service2 }) => {
333
- if (!args2.httpRoute || !service2) {
334
- return void 0;
335
- }
336
- if (args2.patch) {
337
- return void 0;
338
- }
339
- return new HttpRoute(
340
- name,
341
- {
342
- ...args2.httpRoute,
343
- rule: {
344
- backend: service2
345
- }
346
- },
347
- { parent: parent(), ...opts }
348
- );
349
- });
350
- return { labels, containers, volumes, service, httpRoute };
351
- }
352
-
353
- // src/deployment.ts
354
- var Deployment = class extends ComponentResource3 {
355
- constructor(type, name, args, opts, cluster, metadata, spec, status, _service, _httpRoute, resources) {
356
- super(type, name, args, opts);
357
- this.args = args;
358
- this.cluster = cluster;
359
- this.metadata = metadata;
360
- this.spec = spec;
361
- this.status = status;
362
- this._service = _service;
363
- this._httpRoute = _httpRoute;
364
- this.resources = resources;
365
- }
366
- /**
367
- * The Highstate deployment entity.
368
- */
369
- get entity() {
370
- return output4({
371
- type: "k8s.deployment",
372
- clusterInfo: this.cluster.info,
373
- metadata: this.metadata,
374
- spec: this.spec,
375
- service: this._service.apply((service) => service?.entity)
376
- });
377
- }
378
- get optionalService() {
379
- return this._service;
380
- }
381
- /**
382
- * The service associated with the deployment.
383
- */
384
- get service() {
385
- return this._service.apply((service) => {
386
- if (!service) {
387
- throw new Error("The service is not available.");
388
- }
389
- return service;
390
- });
391
- }
392
- /**
393
- * The HTTP route associated with the deployment.
394
- */
395
- get httpRoute() {
396
- return this._httpRoute.apply((httpRoute) => {
397
- if (!httpRoute) {
398
- throw new Error("The HTTP route is not available.");
399
- }
400
- return httpRoute;
401
- });
402
- }
403
- /**
404
- * The instance terminal to interact with the deployment.
405
- */
406
- get terminal() {
407
- return output4({
408
- name: this.metadata.name,
409
- title: this.metadata.name,
410
- image: "ghcr.io/exeteres/highstate/terminal-kubectl",
411
- command: ["script", "-q", "-c", "/enter-container.sh", "/dev/null"],
412
- files: {
413
- "/kubeconfig": this.cluster.kubeconfig,
414
- "/enter-container.sh": {
415
- mode: 493,
416
- content: interpolate`
417
- #!/bin/bash
418
-
419
- exec kubectl exec -it -n ${this.metadata.namespace} deployment/${this.metadata.name} -- ${this.args.terminalShell ?? "bash"}
420
- `.apply(trimIndentation)
421
- }
422
- },
423
- env: {
424
- KUBECONFIG: "/kubeconfig"
425
- }
426
- });
427
- }
428
- static create(name, args, opts) {
429
- return new CreatedDeployment(name, args, opts);
430
- }
431
- };
432
- var CreatedDeployment = class extends Deployment {
433
- constructor(name, args, opts) {
434
- const { labels, containers, volumes, service, httpRoute } = getPublicWorkloadComponents(
435
- name,
436
- args,
437
- () => this,
438
- opts
439
- );
440
- const deployment = output4({ args, containers, volumes }).apply(
441
- async ({ args: args2, containers: containers2, volumes: volumes2 }) => {
442
- await verifyProvider(opts.provider, args2.cluster.info);
443
- return new (args2.patch ? apps.v1.DeploymentPatch : apps.v1.Deployment)(
444
- name,
445
- {
446
- metadata: mapMetadata(args2.patch?.metadata ?? args2, name),
447
- spec: deepmerge2(
448
- {
449
- template: {
450
- metadata: !args2.patch ? { labels } : void 0,
451
- spec: {
452
- containers: containers2.map((container) => mapContainerToRaw(container, name)),
453
- volumes: volumes2
454
- }
455
- },
456
- selector: !args2.patch ? { matchLabels: labels } : void 0
457
- },
458
- omit3(args2, publicWorkloadExtraArgs)
459
- )
460
- },
461
- { parent: this, ...opts }
462
- );
463
- }
464
- );
465
- super(
466
- "highstate:k8s:Deployment",
467
- name,
468
- args,
469
- opts,
470
- output4(args.cluster),
471
- deployment.metadata,
472
- deployment.spec,
473
- deployment.status,
474
- service,
475
- httpRoute,
476
- [deployment]
477
- );
478
- }
479
- };
480
-
481
- // src/stateful-set.ts
482
- import {
483
- output as output5,
484
- ComponentResource as ComponentResource4
485
- } from "@highstate/pulumi";
486
- import { apps as apps2 } from "@pulumi/kubernetes";
487
- import { omit as omit4 } from "remeda";
488
- import { deepmerge as deepmerge3 } from "deepmerge-ts";
489
- var StatefulSet = class extends ComponentResource4 {
490
- constructor(type, name, args, opts, clusterInfo, metadata, spec, status, _service, _httpRoute) {
491
- super(type, name, args, opts);
492
- this.clusterInfo = clusterInfo;
493
- this.metadata = metadata;
494
- this.spec = spec;
495
- this.status = status;
496
- this._service = _service;
497
- this._httpRoute = _httpRoute;
498
- }
499
- /**
500
- * The Highstate stateful set entity.
501
- */
502
- get entity() {
503
- return output5({
504
- type: "k8s.stateful-set",
505
- clusterInfo: this.clusterInfo,
506
- metadata: this.metadata,
507
- service: this.service.entity
508
- });
509
- }
510
- get optionalService() {
511
- return this._service;
512
- }
513
- /**
514
- * The service associated with the stateful set.
515
- */
516
- get service() {
517
- return this._service.apply((service) => {
518
- if (!service) {
519
- throw new Error("The service is not available.");
520
- }
521
- return service;
522
- });
523
- }
524
- /**
525
- * The HTTP route associated with the stateful set.
526
- */
527
- get httpRoute() {
528
- return this._httpRoute.apply((httpRoute) => {
529
- if (!httpRoute) {
530
- throw new Error("The HTTP route is not available.");
531
- }
532
- return httpRoute;
533
- });
534
- }
535
- static create(name, args, opts) {
536
- return new CreatedStatefulSet(name, args, opts);
537
- }
538
- };
539
- var CreatedStatefulSet = class extends StatefulSet {
540
- constructor(name, args, opts) {
541
- const { containers, volumes, labels, service, httpRoute } = getPublicWorkloadComponents(
542
- name,
543
- args,
544
- () => this,
545
- opts
546
- );
547
- const statefulSet = output5({ args, containers, volumes, service }).apply(
548
- async ({ args: args2, containers: containers2, volumes: volumes2, service: service2 }) => {
549
- await verifyProvider(opts.provider, args2.cluster?.info);
550
- return new (args2.patch ? apps2.v1.StatefulSetPatch : apps2.v1.StatefulSet)(
551
- name,
552
- {
553
- metadata: mapMetadata(args2.patch?.metadata ?? args2, name),
554
- spec: deepmerge3(
555
- {
556
- serviceName: service2?.metadata.name || name,
557
- template: {
558
- metadata: !args2.patch ? { labels } : void 0,
559
- spec: {
560
- containers: containers2.map((container) => mapContainerToRaw(container, name)),
561
- volumes: volumes2
562
- }
563
- },
564
- selector: !args2.patch ? { matchLabels: labels } : void 0
565
- },
566
- omit4(args2, publicWorkloadExtraArgs)
567
- )
568
- },
569
- { parent: this, ...opts }
570
- );
571
- }
572
- );
573
- super(
574
- "highstate:k8s:StatefulSet",
575
- name,
576
- args,
577
- opts,
578
- output5(args.cluster).info,
579
- statefulSet.metadata,
580
- statefulSet.spec,
581
- statefulSet.status,
582
- service,
583
- httpRoute
584
- );
585
- }
586
- };
587
-
588
- // src/network-policy.ts
589
- import { networking } from "@pulumi/kubernetes";
590
- import {
591
- ComponentResource as ComponentResource5,
592
- normalize as normalize3,
593
- output as output6
594
- } from "@highstate/pulumi";
595
- import { capitalize, flat, merge, mergeDeep } from "remeda";
596
- import { parseDomain, ParseResultType } from "parse-domain";
597
- import "@highstate/library";
598
- var NetworkPolicy = class _NetworkPolicy extends ComponentResource5 {
599
- /**
600
- * The underlying network policy resource.
601
- */
602
- networkPolicy;
603
- constructor(name, args, opts) {
604
- super("k8s:network-policy", name, args, opts);
605
- const normalizedArgs = output6(args).apply((args2) => {
606
- const ingressRules = normalize3(args2.ingressRule, args2.ingressRules);
607
- const egressRules = normalize3(args2.egressRule, args2.egressRules);
608
- const endpoints = normalize3(args2.egressRule?.toEndpoint, args2.egressRule?.toEndpoints);
609
- const parsedEndpoints = endpoints.map((endpoint) => parseDomain(endpoint));
610
- const cidrsFromEndpoints = parsedEndpoints.filter((result) => result.type === ParseResultType.Ip).map((result) => _NetworkPolicy.mapCidrFromEndpoint(result));
611
- const fqdnsFromEndpoints = parsedEndpoints.filter((result) => result.type !== ParseResultType.Invalid).map((result) => result.hostname);
612
- const extraEgressRules = [];
613
- if (args2.allowKubeDns) {
614
- extraEgressRules.push({
615
- namespaces: ["kube-system"],
616
- selectors: [{ matchLabels: { "k8s-app": "kube-dns" } }],
617
- ports: [{ port: 53, protocol: "UDP" }],
618
- all: false,
619
- cidrs: [],
620
- fqdns: [],
621
- services: []
622
- });
623
- }
624
- return {
625
- ...args2,
626
- podSelector: args2.selector ? mapSelectorLikeToSelector(args2.selector) : {},
627
- isolateEgress: args2.isolateEgress ?? false,
628
- isolateIngress: args2.isolateIngress ?? false,
629
- allowKubeApiServer: args2.allowKubeApiServer ?? false,
630
- ingressRules: ingressRules.map((rule) => ({
631
- all: rule.fromAll ?? false,
632
- cidrs: normalize3(rule.fromCidr, rule.fromCidrs),
633
- fqdns: [],
634
- services: normalize3(rule.fromService, rule.fromServices),
635
- namespaces: normalize3(rule.fromNamespace, rule.fromNamespaces),
636
- selectors: normalize3(rule.fromSelector, rule.fromSelectors),
637
- ports: normalize3(rule.toPort, rule.toPorts)
638
- })),
639
- egressRules: egressRules.map((rule) => {
640
- return {
641
- all: rule.toAll ?? false,
642
- cidrs: normalize3(rule.toCidr, rule.toCidrs).concat(cidrsFromEndpoints),
643
- fqdns: normalize3(rule.toFqdn, rule.toFqdns).concat(fqdnsFromEndpoints),
644
- services: normalize3(rule.toService, rule.toServices),
645
- namespaces: normalize3(rule.toNamespace, rule.toNamespaces),
646
- selectors: normalize3(rule.toSelector, rule.toSelectors),
647
- ports: normalize3(rule.toPort, rule.toPorts)
648
- };
649
- }).concat(extraEgressRules)
650
- };
651
- });
652
- this.networkPolicy = normalizedArgs.apply((args2) => {
653
- return output6(
654
- this.create(name, args2, { ...opts, parent: this })
655
- );
656
- });
657
- this.registerOutputs({ networkPolicy: this.networkPolicy });
658
- }
659
- static mapCidrFromEndpoint(result) {
660
- if (result.ipVersion === 4) {
661
- return `${result.hostname}/32`;
662
- }
663
- return `${result.hostname}/128`;
664
- }
665
- static supportedCNIs = ["cilium"];
666
- static create(name, args, opts) {
667
- return output6(args).apply(async (args2) => {
668
- const cni = args2.cluster.info.cni;
669
- if (!cni || !_NetworkPolicy.supportedCNIs.includes(cni)) {
670
- return new NativeNetworkPolicy(name, args2, opts);
671
- }
672
- const implName = `${capitalize(cni)}NetworkPolicy`;
673
- const implModule = await import(`@highstate/${cni}`);
674
- const implClass = implModule[implName];
675
- if (!implClass) {
676
- throw new Error(`No implementation found for ${cni}`);
677
- }
678
- return new implClass(name, args2, opts);
679
- });
680
- }
681
- static allowInsideNamespace(namespace, cluster, opts) {
682
- return _NetworkPolicy.create(
683
- "allow-inside-namespace",
684
- {
685
- namespace,
686
- cluster,
687
- description: "Allow all traffic inside the namespace.",
688
- selector: {},
689
- ingressRule: { fromNamespace: namespace },
690
- egressRule: { toNamespace: namespace }
691
- },
692
- opts
693
- );
694
- }
695
- static allowKubeApiServer(namespace, cluster, opts) {
696
- return _NetworkPolicy.create(
697
- "allow-kube-api-server",
698
- {
699
- namespace,
700
- cluster,
701
- description: "Allow all traffic to the Kubernetes API server from the namespace.",
702
- allowKubeApiServer: true
703
- },
704
- opts
705
- );
706
- }
707
- static allowKubeDns(namespace, cluster, opts) {
708
- return _NetworkPolicy.create(
709
- "allow-kube-dns",
710
- {
711
- namespace,
712
- cluster,
713
- description: "Allow all traffic to the Kubernetes DNS server from the namespace.",
714
- allowKubeDns: true
715
- },
716
- opts
717
- );
718
- }
719
- static allowAllEgress(namespace, cluster, opts) {
720
- return _NetworkPolicy.create(
721
- "allow-all-egress",
722
- {
723
- namespace,
724
- cluster,
725
- description: "Allow all egress traffic from the namespace.",
726
- egressRule: { toAll: true }
727
- },
728
- opts
729
- );
730
- }
731
- };
732
- var NativeNetworkPolicy = class _NativeNetworkPolicy extends NetworkPolicy {
733
- create(name, args, opts) {
734
- const ingress = _NativeNetworkPolicy.createIngressRules(args);
735
- const egress = _NativeNetworkPolicy.createEgressRules(args);
736
- const policyTypes = [];
737
- if (ingress.length > 0 || args.isolateIngress) {
738
- policyTypes.push("Ingress");
739
- }
740
- if (egress.length > 0 || args.isolateEgress) {
741
- policyTypes.push("Egress");
742
- }
743
- return new networking.v1.NetworkPolicy(
744
- name,
745
- {
746
- metadata: mergeDeep(mapMetadata(args, name), {
747
- annotations: args.description ? { "kubernetes.io/description": args.description } : void 0
748
- }),
749
- spec: {
750
- podSelector: args.podSelector,
751
- ingress,
752
- egress,
753
- policyTypes
754
- }
755
- },
756
- opts
757
- );
758
- }
759
- static fallbackIpBlock = {
760
- cidr: "0.0.0.0/0",
761
- except: ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
762
- };
763
- static createIngressRules(args) {
764
- return args.ingressRules.map((rule) => ({
765
- from: rule.all ? void 0 : _NativeNetworkPolicy.createRulePeers(rule),
766
- ports: _NativeNetworkPolicy.mapPorts(rule.ports)
767
- }));
768
- }
769
- static createEgressRules(args) {
770
- const needFallback = args.egressRules.some((rule) => rule.fqdns.length > 0);
771
- if (needFallback) {
772
- return [{ to: [{ ipBlock: _NativeNetworkPolicy.fallbackIpBlock }] }];
773
- }
774
- const extraRules = [];
775
- if (args.allowKubeApiServer) {
776
- const apiServerIp = args.cluster.info.kubeApiServerIp ?? "10.96.0.1";
777
- const apiServerPort = args.cluster.info.kubeApiServerPort ?? 443;
778
- extraRules.push({
779
- to: [{ ipBlock: { cidr: `${apiServerIp}/32` } }],
780
- ports: [{ port: apiServerPort, protocol: "TCP" }]
781
- });
782
- }
783
- return args.egressRules.map((rule) => {
784
- return {
785
- to: rule.all ? void 0 : _NativeNetworkPolicy.createRulePeers(rule),
786
- ports: _NativeNetworkPolicy.mapPorts(rule.ports)
787
- };
788
- }).concat(extraRules);
789
- }
790
- static createRulePeers(args) {
791
- return [
792
- ..._NativeNetworkPolicy.createCidrPeers(args),
793
- ..._NativeNetworkPolicy.createServicePeers(args),
794
- ..._NativeNetworkPolicy.createSelectorPeers(args)
795
- ];
796
- }
797
- static createCidrPeers(args) {
798
- return args.cidrs.map((cidr) => ({ ipBlock: { cidr } }));
799
- }
800
- static createServicePeers(args) {
801
- return args.services.map((service) => {
802
- const selector = mapServiceToLabelSelector(service);
803
- return {
804
- namespaceSelector: mapNamespaceNameToSelector(service.metadata.namespace),
805
- podSelector: selector
806
- };
807
- });
808
- }
809
- static createSelectorPeers(args) {
810
- const selectorPeers = args.selectors.map((selector) => ({
811
- podSelector: mapSelectorLikeToSelector(selector)
812
- }));
813
- const namespacePeers = args.namespaces.map(_NativeNetworkPolicy.createNamespacePeer);
814
- if (namespacePeers.length === 0) {
815
- return selectorPeers;
816
- }
817
- if (selectorPeers.length === 0) {
818
- return namespacePeers;
819
- }
820
- return flat(
821
- selectorPeers.map((selectorPeer) => {
822
- return namespacePeers.map((namespacePeer) => merge(selectorPeer, namespacePeer));
823
- })
824
- );
825
- }
826
- static createNamespacePeer(namespace) {
827
- const namespaceName = mapNamespaceLikeToNamespaceName(namespace);
828
- const namespaceSelector = mapNamespaceNameToSelector(namespaceName);
829
- return { namespaceSelector };
830
- }
831
- static mapPorts(ports) {
832
- return ports.map((port) => {
833
- if ("port" in port) {
834
- return {
835
- port: port.port,
836
- protocol: port.protocol ?? "TCP"
837
- };
838
- }
839
- return {
840
- port: port.range[0],
841
- endPort: port.range[1],
842
- protocol: port.protocol ?? "TCP"
843
- };
844
- });
845
- }
846
- };
45
+ mapSelectorLikeToSelector
46
+ } from "./chunk-FKNHHKOL.js";
847
47
 
848
48
  // src/access-point.ts
849
- import { DnsRecord } from "@highstate/common";
49
+ import { DnsRecordSet, filterEndpoints, l3EndpointToString } from "@highstate/common";
850
50
  import { gateway } from "@highstate/gateway-api";
851
51
  import {
852
- normalize as normalize4,
853
- output as output7,
52
+ normalize,
53
+ output,
854
54
  toPromise
855
55
  } from "@highstate/pulumi";
856
56
  function useAccessPoint(args) {
857
- const result = output7({ args, namespaceName: output7(args.namespace).metadata.name }).apply(
57
+ const result = output({ args, namespaceName: output(args.namespace).metadata.name }).apply(
858
58
  ({ args: args2, namespaceName }) => {
59
+ if (args2.accessPoint.clusterId !== args2.cluster.id) {
60
+ throw new Error(
61
+ "The provided Kubernetes cluster is different from the one where the access point is deployed."
62
+ );
63
+ }
859
64
  const gateway2 = createGateway({
860
65
  ...args2,
861
66
  annotations: {
@@ -863,36 +68,36 @@ function useAccessPoint(args) {
863
68
  },
864
69
  gateway: args2.accessPoint.gateway
865
70
  });
866
- const dnsRecords = normalize4(args2.fqdn, args2.fqdns).flatMap((fqdn) => {
867
- return DnsRecord.createSet(fqdn, {
71
+ const dnsRecordSets = normalize(args2.fqdn, args2.fqdns).flatMap((fqdn) => {
72
+ return DnsRecordSet.create(fqdn, {
868
73
  providers: args2.accessPoint.dnsProviders,
869
- type: "A",
870
- value: args2.accessPoint.gateway.ip
74
+ values: filterEndpoints(
75
+ args2.accessPoint.gateway.endpoints.filter((endpoint) => endpoint.type !== "hostname")
76
+ )
871
77
  });
872
78
  });
873
- const networkPolicies = [];
874
- if (args2.accessPoint.gateway.service) {
875
- const displayName = getAppDisplayName(args2.accessPoint.gateway.service.metadata);
79
+ const networkPolicies = [
80
+ NetworkPolicy.create(
81
+ `allow-ingress-from-${l3EndpointToString(args2.accessPoint.gateway.endpoints[0])}`,
82
+ {
83
+ namespace: args2.namespace,
84
+ cluster: args2.cluster,
85
+ description: `Allow ingress traffic from the gateway at "${l3EndpointToString(args2.accessPoint.gateway.endpoints[0])}".`,
86
+ ingressRule: {
87
+ fromEndpoints: args2.accessPoint.gateway.endpoints
88
+ }
89
+ },
90
+ { provider: args2.provider }
91
+ )
92
+ ];
93
+ if (isFromCluster(args2.accessPoint.gateway.endpoints[0], args2.cluster)) {
876
94
  networkPolicies.push(
877
- NetworkPolicy.create(
878
- `allow-ingress-from-${getAppName(args2.accessPoint.gateway.service.metadata)}`,
879
- {
880
- namespace: args2.namespace,
881
- cluster: args2.cluster,
882
- description: `Allow ingress traffic from the gateway "${displayName}".`,
883
- ingressRule: {
884
- fromNamespace: args2.accessPoint.gateway.service.metadata.namespace,
885
- fromSelector: args2.accessPoint.gateway.service.spec.selector
886
- }
887
- },
888
- { provider: args2.provider }
889
- ),
890
95
  NetworkPolicy.create(
891
96
  `allow-egress-to-${namespaceName}`,
892
97
  {
893
- namespace: args2.accessPoint.gateway.service.metadata.namespace,
98
+ namespace: args2.accessPoint.gateway.endpoints[0].metadata.k8sService.namespace,
894
99
  cluster: args2.cluster,
895
- selector: args2.accessPoint.gateway.service.spec.selector,
100
+ selector: args2.accessPoint.gateway.endpoints[0].metadata.k8sService.selector,
896
101
  description: `Allow egress traffic to the namespace "${namespaceName}".`,
897
102
  egressRule: {
898
103
  toNamespace: args2.namespace
@@ -902,28 +107,28 @@ function useAccessPoint(args) {
902
107
  )
903
108
  );
904
109
  }
905
- return output7({
110
+ return output({
906
111
  gateway: gateway2,
907
- dnsRecords: output7(dnsRecords).apply((records) => records.flat()),
112
+ dnsRecordSets,
908
113
  networkPolicies
909
114
  });
910
115
  }
911
116
  );
912
117
  return toPromise(result);
913
118
  }
914
- function useStandardAcessPoint(appName, namespace, args, inputs, provider) {
915
- return useAccessPoint({
916
- name: appName,
119
+ async function useStandardAcessPoint(namespace, args, inputs) {
120
+ return await useAccessPoint({
121
+ name: args.appName,
917
122
  namespace,
918
123
  fqdn: args.fqdn,
919
124
  accessPoint: inputs.accessPoint,
920
125
  cluster: inputs.k8sCluster,
921
- provider
126
+ provider: await getProvider(inputs.k8sCluster)
922
127
  });
923
128
  }
924
129
  function createGateway(args) {
925
- return output7(args).apply((args2) => {
926
- if (args2.cluster.info.id !== args2.gateway.clusterInfo.id) {
130
+ return output(args).apply((args2) => {
131
+ if (args2.cluster.id !== args2.gateway.clusterId) {
927
132
  throw new Error(
928
133
  "The provided Kubernetes cluster is different from the one where the gateway controller is deployed."
929
134
  );
@@ -937,12 +142,12 @@ function createGateway(args) {
937
142
  annotations: args2.annotations
938
143
  },
939
144
  spec: {
940
- gatewayClassName: output7(args2.gateway).gatewayClassName,
941
- listeners: normalize4(args2.fqdn, args2.fqdns).map((fqdn) => {
145
+ gatewayClassName: output(args2.gateway).gatewayClassName,
146
+ listeners: normalize(args2.fqdn, args2.fqdns).map((fqdn) => {
942
147
  const normalizedName = fqdn.replace(/\*/g, "wildcard");
943
148
  return {
944
149
  name: `https-${normalizedName}`,
945
- port: output7(args2.gateway).httpsListenerPort,
150
+ port: output(args2.gateway).httpsListenerPort,
946
151
  protocol: "HTTPS",
947
152
  hostname: fqdn,
948
153
  tls: {
@@ -959,15 +164,18 @@ function createGateway(args) {
959
164
  }
960
165
 
961
166
  // src/scripting/bundle.ts
962
- import { core as core3 } from "@pulumi/kubernetes";
963
- import { apply, normalize as normalize5 } from "@highstate/pulumi";
167
+ import { core } from "@pulumi/kubernetes";
168
+ import { apply, normalize as normalize2 } from "@highstate/pulumi";
964
169
  import {
965
- ComponentResource as ComponentResource6,
966
- output as output8
170
+ ComponentResource,
171
+ output as output2
967
172
  } from "@pulumi/pulumi";
968
- import { pipe } from "remeda";
969
- import { deepmerge as deepmerge4 } from "deepmerge-ts";
970
- import { text, trimIndentation as trimIndentation2 } from "@highstate/contract";
173
+ import { mapValues, omitBy, pipe } from "remeda";
174
+ import { deepmerge } from "deepmerge-ts";
175
+ import { readPackageJSON } from "pkg-types";
176
+ import { text, trimIndentation } from "@highstate/contract";
177
+ import { parseL34Endpoint } from "@highstate/common";
178
+ import { serializeFunction } from "@pulumi/pulumi/runtime/index.js";
971
179
 
972
180
  // src/scripting/environment.ts
973
181
  var emptyDistributionEnvironment = {
@@ -976,18 +184,41 @@ var emptyDistributionEnvironment = {
976
184
  packages: []
977
185
  };
978
186
  var emptyScriptEnvironment = {
979
- alpine: emptyDistributionEnvironment,
980
- ubuntu: emptyDistributionEnvironment,
187
+ alpine: {
188
+ ...emptyDistributionEnvironment,
189
+ image: "alpine@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c",
190
+ allowedEndpoints: [
191
+ //
192
+ "tcp://dl-cdn.alpinelinux.org:443",
193
+ "tcp://dl-cdn.alpinelinux.org:80"
194
+ ]
195
+ },
196
+ ubuntu: {
197
+ ...emptyDistributionEnvironment,
198
+ image: "ubuntu@sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782",
199
+ allowedEndpoints: [
200
+ //
201
+ "tcp://archive.ubuntu.com:80",
202
+ "tcp://archive.ubuntu.com:443",
203
+ "tcp://security.ubuntu.com:80",
204
+ "tcp://security.ubuntu.com:443"
205
+ ]
206
+ },
981
207
  setupScripts: {},
982
208
  cleanupScripts: {},
983
- scripts: {},
209
+ files: {},
984
210
  volumes: [],
985
211
  volumeMounts: [],
986
- environment: {}
212
+ environment: {},
213
+ allowedEndpoints: []
214
+ };
215
+ var functionScriptImages = {
216
+ alpine: "oven/bun@sha256:6b14922b0885c3890cdb0b396090af1da486ba941df5ee94391eef64f7113c61",
217
+ ubuntu: "oven/bun@sha256:66b431441dc4c36d7e8164bfc61e6348ec1d7ce2862fc3a29f5dc9856e8205e4"
987
218
  };
988
219
 
989
220
  // src/scripting/bundle.ts
990
- var ScriptBundle = class extends ComponentResource6 {
221
+ var ScriptBundle = class extends ComponentResource {
991
222
  /**
992
223
  * The config map containing the scripts.
993
224
  */
@@ -1004,21 +235,49 @@ var ScriptBundle = class extends ComponentResource6 {
1004
235
  * The environment variables that should be defined in the container.
1005
236
  */
1006
237
  environment;
238
+ /**
239
+ * The image to use for the scripts.
240
+ */
241
+ image;
1007
242
  /**
1008
243
  * The distribution to use for the scripts.
1009
244
  */
1010
245
  distribution;
246
+ /**
247
+ * The list of endpoints that the script is allowed to access.
248
+ */
249
+ allowedEndpoints;
1011
250
  constructor(name, args, opts) {
1012
251
  super("highstate:k8s:ScriptBundle", name, args, opts);
1013
252
  const scriptEnvironment = pipe(
1014
- output8(args),
1015
- apply((args2) => normalize5(args2.environment, args2.environments)),
1016
- apply((args2) => deepmerge4(emptyScriptEnvironment, ...args2))
253
+ output2(args),
254
+ apply((args2) => normalize2(args2.environment, args2.environments)),
255
+ apply((args2) => deepmerge(emptyScriptEnvironment, ...args2))
1017
256
  );
257
+ const hasFunctionScripts = scriptEnvironment.apply((scriptEnvironment2) => {
258
+ return Object.values(scriptEnvironment2.files).some((file) => typeof file === "function");
259
+ });
1018
260
  this.distribution = args.distribution;
1019
261
  this.environment = scriptEnvironment.environment;
1020
- this.configMap = output8({ scriptEnvironment, args }).apply(({ scriptEnvironment: scriptEnvironment2, args: args2 }) => {
1021
- return new core3.v1.ConfigMap(
262
+ this.image = hasFunctionScripts.apply(
263
+ (hasFunctionScripts2) => output2(
264
+ hasFunctionScripts2 ? functionScriptImages[args.distribution] : scriptEnvironment[args.distribution].image
265
+ )
266
+ );
267
+ this.allowedEndpoints = output2({ scriptEnvironment, hasFunctionScripts }).apply(
268
+ ({ scriptEnvironment: scriptEnvironment2, hasFunctionScripts: hasFunctionScripts2 }) => {
269
+ const allowedEndpoints = [
270
+ ...scriptEnvironment2.allowedEndpoints,
271
+ ...scriptEnvironment2[args.distribution].allowedEndpoints
272
+ ];
273
+ if (hasFunctionScripts2) {
274
+ allowedEndpoints.push("tcp://registry.npmjs.org:443");
275
+ }
276
+ return allowedEndpoints.map(parseL34Endpoint);
277
+ }
278
+ );
279
+ this.configMap = output2({ scriptEnvironment, args }).apply(({ scriptEnvironment: scriptEnvironment2, args: args2 }) => {
280
+ return new core.v1.ConfigMap(
1022
281
  name,
1023
282
  {
1024
283
  metadata: mapMetadata(args2, name),
@@ -1027,40 +286,92 @@ var ScriptBundle = class extends ComponentResource6 {
1027
286
  { ...opts, parent: this }
1028
287
  );
1029
288
  });
1030
- this.volumes = scriptEnvironment.volumes.apply((volumes) => {
1031
- return [
1032
- ...volumes,
1033
- {
1034
- name: this.configMap.metadata.name,
1035
- configMap: {
289
+ this.volumes = output2({ hasFunctionScripts, volumes: scriptEnvironment.volumes }).apply(
290
+ ({ hasFunctionScripts: hasFunctionScripts2, volumes }) => {
291
+ return [
292
+ ...volumes,
293
+ {
1036
294
  name: this.configMap.metadata.name,
1037
- defaultMode: 360
1038
- // read and execute permissions
1039
- }
1040
- }
1041
- ];
1042
- });
1043
- this.volumeMounts = scriptEnvironment.volumeMounts.apply((volumeMounts) => {
295
+ configMap: {
296
+ name: this.configMap.metadata.name,
297
+ defaultMode: 360
298
+ // read and execute permissions
299
+ }
300
+ },
301
+ ...hasFunctionScripts2 ? [{ name: "node-modules", emptyDir: {} }] : []
302
+ ];
303
+ }
304
+ );
305
+ this.volumeMounts = output2({
306
+ hasFunctionScripts,
307
+ volumeMounts: scriptEnvironment.volumeMounts
308
+ }).apply(({ hasFunctionScripts: hasFunctionScripts2, volumeMounts }) => {
1044
309
  return [
1045
310
  ...volumeMounts,
1046
311
  {
1047
312
  volume: this.configMap,
1048
313
  mountPath: "/scripts"
1049
- }
314
+ },
315
+ ...hasFunctionScripts2 ? [{ name: "node-modules", mountPath: "/scripts/node_modules" }] : []
1050
316
  ];
1051
317
  });
1052
318
  this.registerOutputs({
1053
319
  configMap: this.configMap,
1054
320
  volumes: this.volumes,
1055
321
  volumeMounts: this.volumeMounts,
1056
- environment: this.environment
322
+ environment: this.environment,
323
+ distribution: this.distribution,
324
+ allowedEndpoints: this.allowedEndpoints,
325
+ image: this.image
1057
326
  });
1058
327
  }
1059
328
  };
1060
- function createScriptData(distribution, environment) {
329
+ function stripWorkspacePrefix(value) {
330
+ if (value.startsWith("workspace:")) {
331
+ return value.replace("workspace:", "");
332
+ }
333
+ return value;
334
+ }
335
+ async function createScriptData(distribution, environment) {
1061
336
  const scriptData = {};
1062
337
  const actions = [];
1063
338
  const distributionEnvironment = environment[distribution];
339
+ const setupScripts = { ...environment.setupScripts };
340
+ let hasFunctionScripts = false;
341
+ for (const key in environment.files) {
342
+ if (typeof environment.files[key] === "function") {
343
+ const serialized = await serializeFunction(environment.files[key]);
344
+ scriptData[key] = text`
345
+ #!/usr/local/bin/bun
346
+
347
+ ${serialized.text}
348
+
349
+ exports.${serialized.exportName}()
350
+ `;
351
+ hasFunctionScripts = true;
352
+ } else {
353
+ scriptData[key] = environment.files[key];
354
+ }
355
+ }
356
+ if (hasFunctionScripts) {
357
+ const packageJson = await readPackageJSON();
358
+ packageJson.dependencies = omitBy(
359
+ mapValues(packageJson.dependencies ?? {}, stripWorkspacePrefix),
360
+ (_, key) => key.startsWith("@highstate/")
361
+ );
362
+ packageJson.devDependencies = omitBy(
363
+ mapValues(packageJson.devDependencies ?? {}, stripWorkspacePrefix),
364
+ (_, key) => key.startsWith("@highstate/")
365
+ );
366
+ scriptData["package.json"] = JSON.stringify(packageJson, null, 2);
367
+ setupScripts["resolve-dependencies.sh"] = text`
368
+ #!/usr/local/bin/bun
369
+ set -e
370
+
371
+ cd /scripts
372
+ bun install --production
373
+ `;
374
+ }
1064
375
  if (distributionEnvironment.preInstallPackages.length > 0) {
1065
376
  scriptData["pre-install-packages.sh"] = getInstallPackagesScript(
1066
377
  distribution,
@@ -1093,9 +404,9 @@ function createScriptData(distribution, environment) {
1093
404
  echo "+ Packages installed successfully"
1094
405
  `);
1095
406
  }
1096
- if (Object.keys(environment.setupScripts).length > 0) {
1097
- for (const key in environment.setupScripts) {
1098
- scriptData[`setup-${key}`] = environment.setupScripts[key];
407
+ if (Object.keys(setupScripts).length > 0) {
408
+ for (const key in setupScripts) {
409
+ scriptData[`setup-${key}`] = setupScripts[key];
1099
410
  actions.push(`
1100
411
  echo "+ Running setup script '${key}'..."
1101
412
  /scripts/setup-${key}
@@ -1122,10 +433,7 @@ function createScriptData(distribution, environment) {
1122
433
  trap cleanup SIGTERM
1123
434
  `);
1124
435
  }
1125
- for (const key in environment.scripts) {
1126
- scriptData[key] = environment.scripts[key];
1127
- }
1128
- scriptData["entrypoint.sh"] = trimIndentation2(`
436
+ scriptData["entrypoint.sh"] = trimIndentation(`
1129
437
  #!/bin/sh
1130
438
  set -e
1131
439
 
@@ -1162,139 +470,168 @@ function getInstallPackagesScript(distribution, packages) {
1162
470
  }
1163
471
 
1164
472
  // src/scripting/container.ts
1165
- import { output as output9 } from "@pulumi/pulumi";
1166
- import { merge as merge2 } from "remeda";
473
+ import { merge } from "remeda";
474
+ import { output as output3 } from "@pulumi/pulumi";
1167
475
  function createScriptContainer(options) {
1168
- return output9(options).apply((options2) => {
1169
- const image = options2.bundle.distribution === "alpine" ? "alpine@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c" : "ubuntu@sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782";
476
+ const bundle = output3(options.bundle);
477
+ return output3({
478
+ options,
479
+ image: bundle.image,
480
+ volumeMounts: bundle.volumeMounts,
481
+ volumes: bundle.volumes,
482
+ environment: bundle.environment,
483
+ allowedEndpoints: bundle.allowedEndpoints
484
+ }).apply(({ options: options2, image, volumeMounts, volumes, environment, allowedEndpoints }) => {
1170
485
  return {
1171
486
  image,
1172
487
  command: ["/scripts/entrypoint.sh", `/scripts/${options2.main}`],
1173
488
  ...options2,
1174
- volumeMounts: merge2(options2.bundle.volumeMounts, options2.volumeMounts),
1175
- volumes: merge2(options2.bundle.volumes, options2.volumes),
1176
- environment: merge2(options2.bundle.environment, options2.environment)
489
+ volumeMounts: [...volumeMounts, ...options2.volumeMounts ?? []],
490
+ volumes: [...volumes, ...options2.volumes ?? []],
491
+ environment: merge(environment, options2.environment),
492
+ allowedEndpoints: [...allowedEndpoints, ...options2.allowedEndpoints ?? []]
1177
493
  };
1178
494
  });
1179
495
  }
1180
496
 
1181
497
  // src/job.ts
1182
498
  import { batch } from "@pulumi/kubernetes";
1183
- import {
1184
- ComponentResource as ComponentResource7,
1185
- normalize as normalize6,
1186
- output as output10
1187
- } from "@highstate/pulumi";
1188
- import { mergeDeep as mergeDeep2, omit as omit5 } from "remeda";
499
+ import { ComponentResource as ComponentResource2, output as output4 } from "@highstate/pulumi";
500
+ import { mergeDeep, omit } from "remeda";
1189
501
  var jobExtraArgs = [...commonExtraArgs, "container", "containers"];
1190
- var Job = class extends ComponentResource7 {
502
+ var Job = class extends ComponentResource2 {
1191
503
  /**
1192
504
  * The underlying Kubernetes job.
1193
505
  */
1194
506
  job;
1195
507
  constructor(name, args, opts) {
1196
508
  super("highstate:k8s:Job", name, args, opts);
1197
- this.job = output10(args).apply((args2) => {
1198
- const containers = normalize6(args2.container, args2.containers);
509
+ const { podTemplate } = getWorkloadComponents(name, args, () => this, opts);
510
+ this.job = output4({ args, podTemplate }).apply(async ({ args: args2, podTemplate: podTemplate2 }) => {
1199
511
  return new batch.v1.Job(
1200
512
  name,
1201
513
  {
1202
514
  metadata: mapMetadata(args2, name),
1203
- spec: mergeDeep2(
515
+ spec: mergeDeep(
1204
516
  {
1205
- template: {
1206
- spec: {
1207
- containers: containers.map((container) => mapContainerToRaw(container, name)),
1208
- volumes: containers.flatMap((container) => normalize6(container.volume, container.volumes)).map(mapWorkloadVolume),
1209
- restartPolicy: "Never"
1210
- }
1211
- }
517
+ template: podTemplate2
1212
518
  },
1213
- omit5(args2, jobExtraArgs)
519
+ omit(args2, jobExtraArgs)
1214
520
  )
1215
521
  },
1216
- { parent: this, ...opts }
522
+ {
523
+ ...opts,
524
+ parent: this,
525
+ provider: await getProvider(args2.cluster)
526
+ }
1217
527
  );
1218
528
  });
1219
- this.registerOutputs({ job: this.job });
1220
529
  }
1221
530
  };
1222
531
 
1223
532
  // src/cron-job.ts
1224
533
  import { batch as batch2 } from "@pulumi/kubernetes";
1225
- import {
1226
- ComponentResource as ComponentResource8,
1227
- normalize as normalize7,
1228
- output as output11
1229
- } from "@highstate/pulumi";
1230
- import { mergeDeep as mergeDeep3, omit as omit6 } from "remeda";
534
+ import { ComponentResource as ComponentResource3, output as output5 } from "@highstate/pulumi";
535
+ import { mergeDeep as mergeDeep2, omit as omit2 } from "remeda";
1231
536
  var cronJobExtraArgs = [...commonExtraArgs, "container", "containers"];
1232
- var CronJob = class extends ComponentResource8 {
537
+ var CronJob = class extends ComponentResource3 {
1233
538
  /**
1234
539
  * The underlying Kubernetes job.
1235
540
  */
1236
541
  cronJob;
1237
542
  constructor(name, args, opts) {
1238
543
  super("highstate:k8s:CronJob", name, args, opts);
1239
- this.cronJob = output11(args).apply((args2) => {
1240
- const containers = normalize7(args2.container, args2.containers);
544
+ const { podTemplate } = getWorkloadComponents(name, args, () => this, opts);
545
+ this.cronJob = output5({ args, podTemplate }).apply(async ({ args: args2, podTemplate: podTemplate2 }) => {
1241
546
  return new batch2.v1.CronJob(
1242
547
  name,
1243
548
  {
1244
549
  metadata: mapMetadata(args2, name),
1245
- spec: mergeDeep3(
550
+ spec: mergeDeep2(
1246
551
  {
1247
552
  jobTemplate: {
1248
553
  spec: {
1249
- template: {
1250
- spec: {
1251
- containers: containers.map((container) => mapContainerToRaw(container, name)),
1252
- volumes: containers.flatMap((container) => normalize7(container.volume, container.volumes)).map(mapWorkloadVolume)
1253
- }
1254
- }
554
+ template: podTemplate2
1255
555
  }
1256
556
  },
1257
557
  schedule: args2.schedule
1258
558
  },
1259
- omit6(args2, cronJobExtraArgs)
559
+ omit2(args2, cronJobExtraArgs)
1260
560
  )
1261
561
  },
1262
- { parent: this, ...opts }
562
+ {
563
+ ...opts,
564
+ parent: this,
565
+ provider: await getProvider(args2.cluster)
566
+ }
1263
567
  );
1264
568
  });
1265
- this.registerOutputs({ cronJob: this.cronJob });
1266
569
  }
1267
570
  };
571
+
572
+ // src/network.ts
573
+ import { filterEndpoints as filterEndpoints2 } from "@highstate/common";
574
+ function getBestEndpoint(endpoints, cluster) {
575
+ if (!endpoints.length) {
576
+ return void 0;
577
+ }
578
+ if (endpoints.length === 1) {
579
+ return endpoints[0];
580
+ }
581
+ if (!cluster) {
582
+ return filterEndpoints2(endpoints)[0];
583
+ }
584
+ const clusterEndpoint = endpoints.find((endpoint) => isFromCluster(endpoint, cluster));
585
+ if (clusterEndpoint) {
586
+ return clusterEndpoint;
587
+ }
588
+ return filterEndpoints2(endpoints)[0];
589
+ }
590
+ function requireBestEndpoint(endpoints, cluster) {
591
+ const endpoint = getBestEndpoint(endpoints, cluster);
592
+ if (!endpoint) {
593
+ throw new Error(`No best endpoint found for cluster "${cluster.name}" (${cluster.id})`);
594
+ }
595
+ return endpoint;
596
+ }
1268
597
  export {
1269
598
  Chart,
1270
599
  CronJob,
1271
600
  Deployment,
601
+ ExposableWorkload,
1272
602
  HttpRoute,
1273
603
  Job,
604
+ Namespace,
1274
605
  NetworkPolicy,
1275
606
  PersistentVolumeClaim,
1276
607
  RenderedChart,
1277
608
  ScriptBundle,
609
+ Secret,
1278
610
  Service,
1279
611
  StatefulSet,
612
+ Workload,
1280
613
  createK8sTerminal,
1281
- createNamespace,
1282
- getProvider as createProvider,
1283
614
  createScriptContainer,
1284
615
  detectExternalIps,
1285
616
  getAppDisplayName,
1286
617
  getAppName,
618
+ getBestEndpoint,
1287
619
  getChartService,
1288
620
  getChartServiceOutput,
1289
- getNamespace,
621
+ getProvider,
622
+ getServiceMetadata,
623
+ hasServiceMetadata,
624
+ isFromCluster,
1290
625
  mapContainerPortToServicePort,
1291
626
  mapMetadata,
1292
627
  mapNamespaceLikeToNamespaceName,
1293
628
  mapNamespaceNameToSelector,
1294
629
  mapSelectorLikeToSelector,
1295
630
  mapServiceToLabelSelector,
631
+ requireBestEndpoint,
1296
632
  resolveHelmChart,
1297
633
  useAccessPoint,
1298
- useStandardAcessPoint
634
+ useStandardAcessPoint,
635
+ withServiceMetadata
1299
636
  };
1300
637
  //# sourceMappingURL=index.js.map