@highstate/k8s 0.7.0 → 0.7.1

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/dist/index.js CHANGED
@@ -1,14 +1,16 @@
1
- import { m as mapMetadata, c as commonExtraArgs, a as mapSelectorLikeToSelector, b as mapNamespaceNameToSelector, d as mapNamespaceLikeToNamespaceName } from './shared-r5jBysdR.js';
2
- export { f as createNamespace, e as createProvider } from './shared-r5jBysdR.js';
3
- import { normalize, output, ComponentResource, toPromise, apply } from '@highstate/pulumi';
1
+ import { m as mapMetadata, c as commonExtraArgs, v as verifyProvider, r as resourceIdToString, a as mapSelectorLikeToSelector, b as mapNamespaceNameToSelector, d as mapNamespaceLikeToNamespaceName, g as getAppDisplayName, e as getAppName } from './shared-Clzbl5K-.js';
2
+ export { h as createNamespace, f as createProvider, i as getNamespace } from './shared-Clzbl5K-.js';
3
+ import { ComponentResource, output, normalize, toPromise, apply } from '@highstate/pulumi';
4
4
  import { core, apps, networking, batch } from '@pulumi/kubernetes';
5
- import { concat, map, omit, mergeDeep, capitalize, flat, merge, pipe } from 'remeda';
6
- import { S as Service, m as mapContainerPortToServicePort, H as HttpRoute, a as mapServiceToLabelSelector } from './helm-BV9UE-B8.js';
7
- export { C as Chart, R as RenderedChart, c as getChartService, b as getChartServiceOutput, g as getServiceHost, r as resolveHelmChart } from './helm-BV9UE-B8.js';
5
+ import { omit, concat, map, uniqueBy, capitalize, mergeDeep, flat, merge, pipe } from 'remeda';
6
+ import { deepmerge } from 'deepmerge-ts';
7
+ import { output as output$1, ComponentResource as ComponentResource$1 } from '@pulumi/pulumi';
8
+ import { S as Service, m as mapContainerPortToServicePort, H as HttpRoute, a as mapServiceToLabelSelector } from './helm-wPTgVV1N.js';
9
+ export { C as Chart, R as RenderedChart, b as getChartService, g as getChartServiceOutput, r as resolveHelmChart } from './helm-wPTgVV1N.js';
10
+ import { parseDomain, ParseResultType } from 'parse-domain';
11
+ import '@highstate/library';
8
12
  import { DnsRecord } from '@highstate/common';
9
13
  import { gateway } from '@highstate/gateway-api';
10
- import { ComponentResource as ComponentResource$1, output as output$1 } from '@pulumi/pulumi';
11
- import { deepmerge } from 'deepmerge-ts';
12
14
  import { trimIndentation, text } from '@highstate/contract';
13
15
  import 'path';
14
16
  import 'node:fs/promises';
@@ -17,6 +19,95 @@ import 'crypto-hash';
17
19
  import '@pulumi/command';
18
20
  import 'glob';
19
21
 
22
+ const extraPersistentVolumeClaimArgs = [...commonExtraArgs, "size", "cluster"];
23
+ class PersistentVolumeClaim extends ComponentResource {
24
+ constructor(type, name, args, opts, clusterInfo, metadata, spec, status) {
25
+ super(type, name, args, opts);
26
+ this.clusterInfo = clusterInfo;
27
+ this.metadata = metadata;
28
+ this.spec = spec;
29
+ this.status = status;
30
+ }
31
+ /**
32
+ * The Highstate service entity.
33
+ */
34
+ get entity() {
35
+ return output({
36
+ type: "k8s.persistent-volume-claim",
37
+ clusterInfo: this.clusterInfo,
38
+ metadata: this.metadata
39
+ });
40
+ }
41
+ static create(name, args, opts) {
42
+ return new CreatedPersistentVolumeClaim(name, args, opts);
43
+ }
44
+ static of(name, entity, opts) {
45
+ return new ExternalPersistentVolumeClaim(
46
+ name,
47
+ output(entity).metadata,
48
+ output(entity).clusterInfo,
49
+ opts
50
+ );
51
+ }
52
+ }
53
+ class CreatedPersistentVolumeClaim extends PersistentVolumeClaim {
54
+ constructor(name, args, opts) {
55
+ const pvc = output(args).apply((args2) => {
56
+ return new core.v1.PersistentVolumeClaim(
57
+ name,
58
+ {
59
+ metadata: mapMetadata(args2, name),
60
+ spec: deepmerge(
61
+ {
62
+ accessModes: ["ReadWriteOnce"],
63
+ resources: {
64
+ requests: {
65
+ storage: args2.size ?? "100Mi"
66
+ }
67
+ }
68
+ },
69
+ omit(args2, extraPersistentVolumeClaimArgs)
70
+ )
71
+ },
72
+ opts
73
+ );
74
+ });
75
+ super(
76
+ "k8s:PersistentVolumeClaim",
77
+ name,
78
+ args,
79
+ opts,
80
+ output(args.cluster).info,
81
+ pvc.metadata,
82
+ pvc.spec,
83
+ pvc.status
84
+ );
85
+ }
86
+ }
87
+ class ExternalPersistentVolumeClaim extends PersistentVolumeClaim {
88
+ constructor(name, id, clusterInfo, opts) {
89
+ const pvc = output(id).apply(async (id2) => {
90
+ await verifyProvider(opts.provider, this.clusterInfo);
91
+ return core.v1.PersistentVolumeClaim.get(
92
+ //
93
+ name,
94
+ resourceIdToString(id2),
95
+ { parent: this, provider: opts.provider }
96
+ );
97
+ });
98
+ super(
99
+ "highstate:k8s:ExternalPersistentVolumeClaim",
100
+ name,
101
+ { id, clusterInfo },
102
+ opts,
103
+ output(clusterInfo),
104
+ pvc.metadata,
105
+ pvc.spec,
106
+ pvc.status
107
+ );
108
+ }
109
+ }
110
+
20
111
  const containerExtraArgs = [
21
112
  "port",
22
113
  "volumeMount",
@@ -25,10 +116,11 @@ const containerExtraArgs = [
25
116
  "environmentSource",
26
117
  "environmentSources"
27
118
  ];
28
- function mapContainerToRaw(fallbackName, container) {
119
+ function mapContainerToRaw(container, fallbackName) {
120
+ const containerName = container.name ?? fallbackName;
29
121
  return {
30
122
  ...omit(container, containerExtraArgs),
31
- name: container.name ?? fallbackName,
123
+ name: containerName,
32
124
  ports: normalize(container.port, container.ports),
33
125
  volumeMounts: map(normalize(container.volumeMount, container.volumeMounts), mapVolumeMount),
34
126
  env: concat(
@@ -92,7 +184,10 @@ function mapVolumeMount(volumeMount) {
92
184
  ["volume"]
93
185
  );
94
186
  }
95
- return volumeMount;
187
+ return {
188
+ ...volumeMount,
189
+ name: volumeMount.name
190
+ };
96
191
  }
97
192
  function mapEnvironmentSource(envFrom) {
98
193
  if (envFrom instanceof core.v1.ConfigMap) {
@@ -112,6 +207,14 @@ function mapEnvironmentSource(envFrom) {
112
207
  return envFrom;
113
208
  }
114
209
  function mapWorkloadVolume(volume) {
210
+ if (volume instanceof PersistentVolumeClaim) {
211
+ return {
212
+ name: volume.metadata.name,
213
+ persistentVolumeClaim: {
214
+ claimName: volume.metadata.name
215
+ }
216
+ };
217
+ }
115
218
  if (volume instanceof core.v1.PersistentVolumeClaim) {
116
219
  return {
117
220
  name: volume.metadata.name,
@@ -139,177 +242,272 @@ function mapWorkloadVolume(volume) {
139
242
  return volume;
140
243
  }
141
244
 
142
- const deploymentExtraArgs = [
143
- ...commonExtraArgs,
144
- "container",
145
- "containers",
146
- "service",
147
- "httpRoute"
148
- ];
245
+ const workloadExtraArgs = [...commonExtraArgs, "container", "containers"];
246
+ const publicWorkloadExtraArgs = [...workloadExtraArgs, "service", "httpRoute"];
247
+ function getWorkloadComponents(name, args) {
248
+ const labels = {
249
+ "app.kubernetes.io/name": name
250
+ };
251
+ const containers = output$1(args).apply((args2) => normalize(args2.container, args2.containers));
252
+ const volumes = containers.apply((containers2) => {
253
+ const containerVolumes = containers2.flatMap((container) => normalize(container.volume, container.volumes)).map(mapWorkloadVolume);
254
+ const containerVolumeMounts = containers2.flatMap((container) => {
255
+ return normalize(container.volumeMount, container.volumeMounts).map((volumeMount) => {
256
+ return "volume" in volumeMount ? volumeMount.volume : void 0;
257
+ }).filter(Boolean);
258
+ }).map(mapWorkloadVolume);
259
+ return uniqueBy([...containerVolumes, ...containerVolumeMounts], (volume) => volume.name);
260
+ });
261
+ return { labels, containers, volumes };
262
+ }
263
+ function getPublicWorkloadComponents(name, args, parent, opts) {
264
+ const { labels, containers, volumes } = getWorkloadComponents(name, args);
265
+ const service = output$1({ args, containers }).apply(({ args: args2, containers: containers2 }) => {
266
+ if (!args2.service && !args2.httpRoute) {
267
+ return void 0;
268
+ }
269
+ if (args2.patch?.service) {
270
+ return Service.of(name, args2.patch.service, { parent: parent(), ...opts });
271
+ }
272
+ if (args2.patch) {
273
+ return void 0;
274
+ }
275
+ const ports = containers2.flatMap((container) => normalize(container.port, container.ports));
276
+ return Service.create(
277
+ name,
278
+ {
279
+ ...args2.service,
280
+ selector: labels,
281
+ cluster: args2.cluster,
282
+ namespace: args2.namespace,
283
+ ports: (
284
+ // allow to completely override the ports
285
+ !args2.service?.port && !args2.service?.ports ? ports.map(mapContainerPortToServicePort) : args2.service?.ports
286
+ )
287
+ },
288
+ { parent: parent(), ...opts }
289
+ );
290
+ });
291
+ const httpRoute = output$1({
292
+ args,
293
+ service
294
+ }).apply(({ args: args2, service: service2 }) => {
295
+ if (!args2.httpRoute || !service2) {
296
+ return void 0;
297
+ }
298
+ if (args2.patch) {
299
+ return void 0;
300
+ }
301
+ return new HttpRoute(
302
+ name,
303
+ {
304
+ ...args2.httpRoute,
305
+ rule: {
306
+ backend: service2
307
+ }
308
+ },
309
+ { parent: parent(), ...opts }
310
+ );
311
+ });
312
+ return { labels, containers, volumes, service, httpRoute };
313
+ }
314
+
149
315
  class Deployment extends ComponentResource {
316
+ constructor(type, name, args, opts, clusterInfo, metadata, spec, status, _service, _httpRoute, resources) {
317
+ super(type, name, args, opts);
318
+ this.clusterInfo = clusterInfo;
319
+ this.metadata = metadata;
320
+ this.spec = spec;
321
+ this.status = status;
322
+ this._service = _service;
323
+ this._httpRoute = _httpRoute;
324
+ this.resources = resources;
325
+ }
150
326
  /**
151
- * The underlying Kubernetes deployment.
327
+ * The Highstate deployment entity.
152
328
  */
153
- deployment;
329
+ get entity() {
330
+ return output({
331
+ type: "k8s.deployment",
332
+ clusterInfo: this.clusterInfo,
333
+ metadata: this.metadata,
334
+ spec: this.spec,
335
+ service: this._service.apply((service) => service?.entity)
336
+ });
337
+ }
154
338
  /**
155
339
  * The service associated with the deployment.
156
340
  */
157
- service;
341
+ get service() {
342
+ return this._service.apply((service) => {
343
+ if (!service) {
344
+ throw new Error("The service is not available.");
345
+ }
346
+ return service;
347
+ });
348
+ }
158
349
  /**
159
350
  * The HTTP route associated with the deployment.
160
351
  */
161
- httpRoute;
352
+ get httpRoute() {
353
+ return this._httpRoute.apply((httpRoute) => {
354
+ if (!httpRoute) {
355
+ throw new Error("The HTTP route is not available.");
356
+ }
357
+ return httpRoute;
358
+ });
359
+ }
360
+ static create(name, args, opts) {
361
+ return new CreatedDeployment(name, args, opts);
362
+ }
363
+ }
364
+ class CreatedDeployment extends Deployment {
162
365
  constructor(name, args, opts) {
163
- super("highstate:k8s:Deployment", name, args, opts);
164
- const labels = {
165
- "app.kubernetes.io/name": name
166
- };
167
- this.deployment = output(args).apply((args2) => {
168
- const containers = normalize(args2.container, args2.containers);
169
- return new apps.v1.Deployment(
170
- name,
171
- {
172
- metadata: mapMetadata(args2, name),
173
- spec: mergeDeep(
174
- {
175
- template: {
176
- metadata: {
177
- labels
366
+ const { labels, containers, volumes, service, httpRoute } = getPublicWorkloadComponents(
367
+ name,
368
+ args,
369
+ () => this,
370
+ opts
371
+ );
372
+ const deployment = output({ args, containers, volumes }).apply(
373
+ async ({ args: args2, containers: containers2, volumes: volumes2 }) => {
374
+ await verifyProvider(opts.provider, args2.cluster.info);
375
+ return new (args2.patch ? apps.v1.DeploymentPatch : apps.v1.Deployment)(
376
+ name,
377
+ {
378
+ metadata: mapMetadata(args2.patch?.metadata ?? args2, name),
379
+ spec: deepmerge(
380
+ {
381
+ template: {
382
+ metadata: {
383
+ labels
384
+ },
385
+ spec: {
386
+ containers: containers2.map((container) => mapContainerToRaw(container, name)),
387
+ volumes: volumes2
388
+ }
178
389
  },
179
- spec: {
180
- containers: containers.map((container) => mapContainerToRaw(name, container)),
181
- volumes: containers.flatMap((container) => normalize(container.volume, container.volumes)).map(mapWorkloadVolume)
390
+ selector: {
391
+ matchLabels: labels
182
392
  }
183
393
  },
184
- selector: {
185
- matchLabels: labels
186
- }
187
- },
188
- omit(args2, deploymentExtraArgs)
189
- )
190
- },
191
- {
192
- ...opts,
193
- parent: this
194
- }
195
- );
196
- });
197
- this.service = output({
198
- args: args.service,
199
- httpRouteArgs: args.httpRoute,
200
- namespace: this.deployment.metadata.namespace,
201
- containers: this.deployment.spec.template.spec.containers
202
- }).apply(({ args: args2, httpRouteArgs, namespace, containers }) => {
203
- if (!args2 && !httpRouteArgs) {
204
- return void 0;
205
- }
206
- const ports = containers.flatMap((container) => container.ports ?? []);
207
- return new Service(
208
- args2?.name ?? name,
209
- {
210
- ...args2,
211
- namespace,
212
- ports: (
213
- // allow to completely override the ports
214
- !args2?.port && !args2?.ports ? ports.map(mapContainerPortToServicePort) : args2?.ports
215
- ),
216
- selector: labels
217
- },
218
- {
219
- ...opts,
220
- parent: this
221
- }
222
- );
223
- });
224
- this.httpRoute = output({
225
- args: args.httpRoute,
226
- service: this.service
227
- }).apply(({ args: args2, service }) => {
228
- if (!args2 || !service) {
229
- return void 0;
230
- }
231
- return new HttpRoute(
232
- name,
233
- {
234
- ...args2,
235
- rule: {
236
- backend: service.service
237
- }
238
- },
239
- { ...opts, parent: this }
240
- );
241
- });
242
- this.registerOutputs({
243
- deployment: this.deployment,
244
- service: this.service
245
- });
246
- }
247
- getRequiredService() {
248
- return this.service.apply((service) => {
249
- if (!service) {
250
- throw new Error("The service is not available for this deployment.");
394
+ omit(args2, publicWorkloadExtraArgs)
395
+ )
396
+ },
397
+ { parent: this, ...opts }
398
+ );
251
399
  }
252
- return service;
253
- });
400
+ );
401
+ super(
402
+ "highstate:k8s:Deployment",
403
+ name,
404
+ args,
405
+ opts,
406
+ output(args.cluster).info,
407
+ deployment.metadata,
408
+ deployment.spec,
409
+ deployment.status,
410
+ service,
411
+ httpRoute,
412
+ [deployment]
413
+ );
254
414
  }
255
415
  }
256
416
 
257
- function mapPersistentVolumeClaimToRaw(args) {
258
- return {
259
- metadata: mapMetadata(args),
260
- spec: args
261
- };
262
- }
263
-
264
417
  class StatefulSet extends ComponentResource {
418
+ constructor(type, name, args, opts, clusterInfo, metadata, spec, status, _service, _httpRoute) {
419
+ super(type, name, args, opts);
420
+ this.clusterInfo = clusterInfo;
421
+ this.metadata = metadata;
422
+ this.spec = spec;
423
+ this.status = status;
424
+ this._service = _service;
425
+ this._httpRoute = _httpRoute;
426
+ }
265
427
  /**
266
- * The underlying Kubernetes stateful set.
428
+ * The Highstate stateful set entity.
267
429
  */
268
- statefulSet;
430
+ get entity() {
431
+ return output({
432
+ type: "k8s.stateful-set",
433
+ clusterInfo: this.clusterInfo,
434
+ metadata: this.metadata,
435
+ service: this.service.entity
436
+ });
437
+ }
269
438
  /**
270
439
  * The service associated with the stateful set.
271
440
  */
272
- service;
273
- constructor(name, args, opts) {
274
- super("highstate:k8s:StatefulSet", name, args, opts);
275
- const labels = {
276
- "app.kubernetes.io/name": name
277
- };
278
- this.service = output(args.service).apply((service) => {
279
- return new Service(
280
- service?.name ?? name,
281
- {
282
- ...service,
283
- clusterIP: "None"
284
- },
285
- { ...opts, parent: this }
286
- );
287
- });
288
- this.statefulSet = output(args).apply((args2) => {
289
- return new apps.v1.StatefulSet(name, {
290
- metadata: mapMetadata(args2),
291
- spec: mergeDeep(args2, {
292
- serviceName: this.service.service.metadata.name,
293
- template: {
294
- metadata: {
295
- labels
296
- },
297
- spec: {
298
- containers: normalize(args2.container, args2.containers).map((container) => mapContainerToRaw(name, container))
299
- }
300
- },
301
- selector: {
302
- matchLabels: labels
303
- },
304
- volumeClaimTemplates: normalize(args2.volumeClaim, args2.volumeClaims).map(mapPersistentVolumeClaimToRaw)
305
- })
306
- });
441
+ get service() {
442
+ return this._service.apply((service) => {
443
+ if (!service) {
444
+ throw new Error("The service is not available.");
445
+ }
446
+ return service;
307
447
  });
308
- this.registerOutputs({
309
- statefulSet: this.statefulSet,
310
- service: this.service
448
+ }
449
+ /**
450
+ * The HTTP route associated with the stateful set.
451
+ */
452
+ get httpRoute() {
453
+ return this._httpRoute.apply((httpRoute) => {
454
+ if (!httpRoute) {
455
+ throw new Error("The HTTP route is not available.");
456
+ }
457
+ return httpRoute;
311
458
  });
312
459
  }
460
+ static create(name, args, opts) {
461
+ return new CreatedStatefulSet(name, args, opts);
462
+ }
463
+ }
464
+ class CreatedStatefulSet extends StatefulSet {
465
+ constructor(name, args, opts) {
466
+ const { containers, volumes, labels, service, httpRoute } = getPublicWorkloadComponents(
467
+ name,
468
+ args,
469
+ () => this,
470
+ opts
471
+ );
472
+ const statefulSet = output({ args, containers, volumes, service }).apply(
473
+ async ({ args: args2, containers: containers2, volumes: volumes2, service: service2 }) => {
474
+ await verifyProvider(opts.provider, args2.cluster?.info);
475
+ return new (args2.patch ? apps.v1.StatefulSetPatch : apps.v1.StatefulSet)(
476
+ name,
477
+ {
478
+ metadata: mapMetadata(args2.patch?.metadata ?? args2, name),
479
+ spec: deepmerge(
480
+ {
481
+ serviceName: service2?.metadata.name || name,
482
+ template: {
483
+ metadata: !args2.patch ? { labels } : void 0,
484
+ spec: {
485
+ containers: containers2.map((container) => mapContainerToRaw(container, name)),
486
+ volumes: volumes2
487
+ }
488
+ },
489
+ selector: !args2.patch ? { matchLabels: labels } : void 0
490
+ },
491
+ omit(args2, publicWorkloadExtraArgs)
492
+ )
493
+ },
494
+ { parent: this, ...opts }
495
+ );
496
+ }
497
+ );
498
+ super(
499
+ "highstate:k8s:StatefulSet",
500
+ name,
501
+ args,
502
+ opts,
503
+ output(args.cluster).info,
504
+ statefulSet.metadata,
505
+ statefulSet.spec,
506
+ statefulSet.status,
507
+ service,
508
+ httpRoute
509
+ );
510
+ }
313
511
  }
314
512
 
315
513
  class NetworkPolicy extends ComponentResource {
@@ -322,11 +520,28 @@ class NetworkPolicy extends ComponentResource {
322
520
  const normalizedArgs = output(args).apply((args2) => {
323
521
  const ingressRules = normalize(args2.ingressRule, args2.ingressRules);
324
522
  const egressRules = normalize(args2.egressRule, args2.egressRules);
523
+ const endpoints = normalize(args2.egressRule?.toEndpoint, args2.egressRule?.toEndpoints);
524
+ const parsedEndpoints = endpoints.map((endpoint) => parseDomain(endpoint));
525
+ const cidrsFromEndpoints = parsedEndpoints.filter((result) => result.type === ParseResultType.Ip).map((result) => NetworkPolicy.mapCidrFromEndpoint(result));
526
+ const fqdnsFromEndpoints = parsedEndpoints.filter((result) => result.type !== ParseResultType.Invalid).map((result) => result.hostname);
527
+ const extraEgressRules = [];
528
+ if (args2.allowKubeDns) {
529
+ extraEgressRules.push({
530
+ namespaces: ["kube-system"],
531
+ selectors: [{ matchLabels: { "k8s-app": "kube-dns" } }],
532
+ ports: [{ port: 53, protocol: "UDP" }],
533
+ all: false,
534
+ cidrs: [],
535
+ fqdns: [],
536
+ services: []
537
+ });
538
+ }
325
539
  return {
326
540
  ...args2,
327
541
  podSelector: args2.selector ? mapSelectorLikeToSelector(args2.selector) : {},
328
542
  isolateEgress: args2.isolateEgress ?? false,
329
543
  isolateIngress: args2.isolateIngress ?? false,
544
+ allowKubeApiServer: args2.allowKubeApiServer ?? false,
330
545
  ingressRules: ingressRules.map((rule) => ({
331
546
  all: rule.fromAll ?? false,
332
547
  cidrs: normalize(rule.fromCidr, rule.fromCidrs),
@@ -336,15 +551,17 @@ class NetworkPolicy extends ComponentResource {
336
551
  selectors: normalize(rule.fromSelector, rule.fromSelectors),
337
552
  ports: normalize(rule.toPort, rule.toPorts)
338
553
  })),
339
- egressRules: egressRules.map((rule) => ({
340
- all: rule.toAll ?? false,
341
- cidrs: normalize(rule.toCidr, rule.toCidrs),
342
- fqdns: normalize(rule.toFqdn, rule.toFqdns),
343
- services: normalize(rule.toService, rule.toServices),
344
- namespaces: normalize(rule.toNamespace, rule.toNamespaces),
345
- selectors: normalize(rule.toSelector, rule.toSelectors),
346
- ports: normalize(rule.toPort, rule.toPorts)
347
- }))
554
+ egressRules: egressRules.map((rule) => {
555
+ return {
556
+ all: rule.toAll ?? false,
557
+ cidrs: normalize(rule.toCidr, rule.toCidrs).concat(cidrsFromEndpoints),
558
+ fqdns: normalize(rule.toFqdn, rule.toFqdns).concat(fqdnsFromEndpoints),
559
+ services: normalize(rule.toService, rule.toServices),
560
+ namespaces: normalize(rule.toNamespace, rule.toNamespaces),
561
+ selectors: normalize(rule.toSelector, rule.toSelectors),
562
+ ports: normalize(rule.toPort, rule.toPorts)
563
+ };
564
+ }).concat(extraEgressRules)
348
565
  };
349
566
  });
350
567
  this.networkPolicy = normalizedArgs.apply((args2) => {
@@ -354,9 +571,16 @@ class NetworkPolicy extends ComponentResource {
354
571
  });
355
572
  this.registerOutputs({ networkPolicy: this.networkPolicy });
356
573
  }
574
+ static mapCidrFromEndpoint(result) {
575
+ if (result.ipVersion === 4) {
576
+ return `${result.hostname}/32`;
577
+ }
578
+ return `${result.hostname}/128`;
579
+ }
580
+ static supportedCNIs = ["cilium"];
357
581
  static create(name, args, opts) {
358
582
  return output(args).apply(async (args2) => {
359
- if (!args2.cni || args2.cni === "unknown") {
583
+ if (!args2.cni || !NetworkPolicy.supportedCNIs.includes(args2.cni)) {
360
584
  return new NativeNetworkPolicy(name, args2, opts);
361
585
  }
362
586
  const implName = `${capitalize(args2.cni)}NetworkPolicy`;
@@ -368,6 +592,56 @@ class NetworkPolicy extends ComponentResource {
368
592
  return new implClass(name, args2, opts);
369
593
  });
370
594
  }
595
+ static allowInsideNamespace(namespace, k8sCluster, opts) {
596
+ return NetworkPolicy.create(
597
+ "allow-inside-namespace",
598
+ {
599
+ namespace,
600
+ cni: output(k8sCluster).info.cni,
601
+ description: "Allow all traffic inside the namespace.",
602
+ selector: {},
603
+ ingressRule: { fromNamespace: namespace },
604
+ egressRule: { toNamespace: namespace }
605
+ },
606
+ opts
607
+ );
608
+ }
609
+ static allowKubeApiServer(namespace, k8sCluster, opts) {
610
+ return NetworkPolicy.create(
611
+ "allow-kube-api-server",
612
+ {
613
+ namespace,
614
+ cni: output(k8sCluster).info.cni,
615
+ description: "Allow all traffic to the Kubernetes API server from the namespace.",
616
+ allowKubeApiServer: true
617
+ },
618
+ opts
619
+ );
620
+ }
621
+ static allowKubeDns(namespace, k8sCluster, opts) {
622
+ return NetworkPolicy.create(
623
+ "allow-kube-dns",
624
+ {
625
+ namespace,
626
+ cni: output(k8sCluster).info.cni,
627
+ description: "Allow all traffic to the Kubernetes DNS server from the namespace.",
628
+ allowKubeDns: true
629
+ },
630
+ opts
631
+ );
632
+ }
633
+ static allowAllEgress(namespace, k8sCluster, opts) {
634
+ return NetworkPolicy.create(
635
+ "allow-all-egress",
636
+ {
637
+ namespace,
638
+ cni: output(k8sCluster).info.cni,
639
+ description: "Allow all egress traffic from the namespace.",
640
+ egressRule: { toAll: true }
641
+ },
642
+ opts
643
+ );
644
+ }
371
645
  }
372
646
  class NativeNetworkPolicy extends NetworkPolicy {
373
647
  create(name, args, opts) {
@@ -411,10 +685,16 @@ class NativeNetworkPolicy extends NetworkPolicy {
411
685
  if (needFallback) {
412
686
  return [{ to: [{ ipBlock: NativeNetworkPolicy.fallbackIpBlock }] }];
413
687
  }
414
- return args.egressRules.map((rule) => ({
415
- to: rule.all ? void 0 : NativeNetworkPolicy.createRulePeers(rule),
416
- ports: NativeNetworkPolicy.mapPorts(rule.ports)
417
- }));
688
+ const extraRules = [];
689
+ if (args.allowKubeApiServer) {
690
+ extraRules.push({ to: [{ ipBlock: { cidr: "10.96.0.1" } }] });
691
+ }
692
+ return args.egressRules.map((rule) => {
693
+ return {
694
+ to: rule.all ? void 0 : NativeNetworkPolicy.createRulePeers(rule),
695
+ ports: NativeNetworkPolicy.mapPorts(rule.ports)
696
+ };
697
+ }).concat(extraRules);
418
698
  }
419
699
  static createRulePeers(args) {
420
700
  return [
@@ -475,28 +755,80 @@ class NativeNetworkPolicy extends NetworkPolicy {
475
755
  }
476
756
 
477
757
  function useAccessPoint(args) {
478
- const result = output(args).apply((args2) => {
479
- const gateway2 = createGateway({
480
- ...args2,
481
- annotations: {
482
- "cert-manager.io/cluster-issuer": args2.accessPoint.tlsIssuer.clusterIssuerName
483
- },
484
- gateway: args2.accessPoint.gateway
485
- });
486
- const dnsRecord = DnsRecord.create(args2.fqdn, {
487
- provider: args2.accessPoint.dnsProvider,
488
- type: "A",
489
- value: args2.accessPoint.gateway.ip
490
- });
491
- return output({
492
- gateway: gateway2,
493
- dnsRecord
494
- });
495
- });
758
+ const result = output({ args, namespaceName: output(args.namespace).metadata.name }).apply(
759
+ ({ args: args2, namespaceName }) => {
760
+ const gateway2 = createGateway({
761
+ ...args2,
762
+ annotations: {
763
+ "cert-manager.io/cluster-issuer": args2.accessPoint.tlsIssuer.clusterIssuerName
764
+ },
765
+ gateway: args2.accessPoint.gateway
766
+ });
767
+ const dnsRecords = normalize(args2.fqdn, args2.fqdns).map((fqdn) => {
768
+ return DnsRecord.create(fqdn, {
769
+ provider: args2.accessPoint.dnsProvider,
770
+ type: "A",
771
+ value: args2.accessPoint.gateway.ip
772
+ });
773
+ });
774
+ const networkPolicies = [];
775
+ if (args2.accessPoint.gateway.service) {
776
+ const displayName = getAppDisplayName(args2.accessPoint.gateway.service.metadata);
777
+ networkPolicies.push(
778
+ NetworkPolicy.create(
779
+ `allow-ingress-from-${getAppName(args2.accessPoint.gateway.service.metadata)}`,
780
+ {
781
+ cni: args2.accessPoint.gateway.service.clusterInfo.cni,
782
+ namespace: args2.namespace,
783
+ description: `Allow ingress traffic from the gateway "${displayName}".`,
784
+ ingressRule: {
785
+ fromNamespace: args2.accessPoint.gateway.service.metadata.namespace,
786
+ fromSelector: args2.accessPoint.gateway.service.spec.selector
787
+ }
788
+ },
789
+ { provider: args2.provider }
790
+ ),
791
+ NetworkPolicy.create(
792
+ `allow-egress-to-${namespaceName}`,
793
+ {
794
+ cni: args2.accessPoint.gateway.service.clusterInfo.cni,
795
+ namespace: args2.accessPoint.gateway.service.metadata.namespace,
796
+ selector: args2.accessPoint.gateway.service.spec.selector,
797
+ description: `Allow egress traffic to the namespace "${namespaceName}".`,
798
+ egressRule: {
799
+ toNamespace: args2.namespace
800
+ }
801
+ },
802
+ { provider: args2.provider }
803
+ )
804
+ );
805
+ }
806
+ return output({
807
+ gateway: gateway2,
808
+ dnsRecords,
809
+ networkPolicies
810
+ });
811
+ }
812
+ );
496
813
  return toPromise(result);
497
814
  }
815
+ function useStandardAcessPoint(appName, namespace, args, inputs, provider) {
816
+ return useAccessPoint({
817
+ name: appName,
818
+ namespace,
819
+ fqdn: args.fqdn,
820
+ accessPoint: inputs.accessPoint,
821
+ clusterInfo: inputs.k8sCluster.info,
822
+ provider
823
+ });
824
+ }
498
825
  function createGateway(args) {
499
826
  return output(args).apply((args2) => {
827
+ if (args2.clusterInfo.id !== args2.gateway.clusterInfo.id) {
828
+ throw new Error(
829
+ "The provided Kubernetes cluster is different from the one where the gateway controller is deployed."
830
+ );
831
+ }
500
832
  return new gateway.v1.Gateway(
501
833
  args2.name,
502
834
  {
@@ -507,18 +839,19 @@ function createGateway(args) {
507
839
  },
508
840
  spec: {
509
841
  gatewayClassName: output(args2.gateway).gatewayClassName,
510
- listeners: [
511
- {
512
- name: "https",
842
+ listeners: normalize(args2.fqdn, args2.fqdns).map((fqdn) => {
843
+ const normalizedName = fqdn.replace(/\*/g, "wildcard");
844
+ return {
845
+ name: `https-${normalizedName}`,
513
846
  port: output(args2.gateway).httpsListenerPort,
514
847
  protocol: "HTTPS",
515
- hostname: args2.fqdn,
848
+ hostname: fqdn,
516
849
  tls: {
517
850
  mode: "Terminate",
518
- certificateRefs: [{ name: args2.fqdn }]
851
+ certificateRefs: [{ name: normalizedName }]
519
852
  }
520
- }
521
- ]
853
+ };
854
+ })
522
855
  }
523
856
  },
524
857
  { provider: args2.provider, deletedWith: args2.namespace }
@@ -748,7 +1081,7 @@ class Job extends ComponentResource {
748
1081
  {
749
1082
  template: {
750
1083
  spec: {
751
- containers: containers.map((container) => mapContainerToRaw(name, container)),
1084
+ containers: containers.map((container) => mapContainerToRaw(container, name)),
752
1085
  volumes: containers.flatMap((container) => normalize(container.volume, container.volumes)).map(mapWorkloadVolume),
753
1086
  restartPolicy: "Never"
754
1087
  }
@@ -784,7 +1117,7 @@ class CronJob extends ComponentResource {
784
1117
  spec: {
785
1118
  template: {
786
1119
  spec: {
787
- containers: containers.map((container) => mapContainerToRaw(name, container)),
1120
+ containers: containers.map((container) => mapContainerToRaw(container, name)),
788
1121
  volumes: containers.flatMap((container) => normalize(container.volume, container.volumes)).map(mapWorkloadVolume)
789
1122
  }
790
1123
  }
@@ -802,4 +1135,4 @@ class CronJob extends ComponentResource {
802
1135
  }
803
1136
  }
804
1137
 
805
- export { CronJob, Deployment, HttpRoute, Job, NetworkPolicy, ScriptBundle, Service, StatefulSet, createScriptContainer, mapContainerPortToServicePort, mapMetadata, mapNamespaceLikeToNamespaceName, mapNamespaceNameToSelector, mapSelectorLikeToSelector, mapServiceToLabelSelector, useAccessPoint };
1138
+ export { CronJob, Deployment, HttpRoute, Job, NetworkPolicy, PersistentVolumeClaim, ScriptBundle, Service, StatefulSet, createScriptContainer, getAppDisplayName, getAppName, mapContainerPortToServicePort, mapMetadata, mapNamespaceLikeToNamespaceName, mapNamespaceNameToSelector, mapSelectorLikeToSelector, mapServiceToLabelSelector, useAccessPoint, useStandardAcessPoint };