@highstate/k8s 0.7.11 → 0.9.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.
@@ -1,9 +1,10 @@
1
1
  {
2
2
  "sourceHashes": {
3
- "./dist/index.js": "20cf1cb3924125b4edabc00ffec27a08e3b2bff91f838e64062cf120fcc03d51",
4
- "./dist/units/access-point/index.js": "7e761f8a5f846322855a09c61dedefb95a3e0ff987113139d5e2a69578d33e31",
5
- "./dist/units/cert-manager/index.js": "6bf115809f1fc1505fec097289d56bd0e04525eebe9bfb2c0e353b1a0769cf03",
6
- "./dist/units/dns01-issuer/index.js": "d30907c98a5c44aaa89e6c807d5567dadc333ae3d6dfc4f2543fef411e0c7b28",
7
- "./dist/units/existing-cluster/index.js": "bf608ff96a2590f8756e14ce074e598ef23f965c75581631f417869c7e6e2c67"
3
+ "./dist/index.js": "13ad30440365ae37502ac17ef67daeb31e346d7c89d6725a8dced3212d8050a4",
4
+ "./dist/units/access-point/index.js": "6ce68f586a82ce12eefa9c195319bbdcfa55bdd11e2820f939e86de8ef767114",
5
+ "./dist/units/cert-manager/index.js": "950704b0ed45a2c4387030fa407b8ef22898a59ecfa73e27d585a8e268ec61d2",
6
+ "./dist/units/dns01-issuer/index.js": "2a19200eaadfac9978056801d81fb9f472a34e03666d95f4d87a4e8b39bd57ff",
7
+ "./dist/units/existing-cluster/index.js": "c376df4bb731d87030611950299b2a2c6471ca6cff0f486fc9f271d15ae6b887",
8
+ "./dist/units/gateway-api/index.js": "63f1b5bf0f078179866e5faf6793b9a7c3f0f1025fdab09152f75f2d66b58188"
8
9
  }
9
10
  }
package/dist/index.js CHANGED
@@ -9,6 +9,10 @@ import {
9
9
  mapServiceToLabelSelector,
10
10
  resolveHelmChart
11
11
  } from "./chunk-K4WKJ4L5.js";
12
+ import {
13
+ createK8sTerminal,
14
+ detectExternalIps
15
+ } from "./chunk-QLQ3QVGT.js";
12
16
  import {
13
17
  commonExtraArgs,
14
18
  createNamespace,
@@ -23,10 +27,6 @@ import {
23
27
  resourceIdToString,
24
28
  verifyProvider
25
29
  } from "./chunk-T5Z2M4JE.js";
26
- import {
27
- createK8sTerminal,
28
- detectExternalIps
29
- } from "./chunk-QLQ3QVGT.js";
30
30
 
31
31
  // src/deployment.ts
32
32
  import {
@@ -665,24 +665,25 @@ var NetworkPolicy = class _NetworkPolicy extends ComponentResource5 {
665
665
  static supportedCNIs = ["cilium"];
666
666
  static create(name, args, opts) {
667
667
  return output6(args).apply(async (args2) => {
668
- if (!args2.cni || !_NetworkPolicy.supportedCNIs.includes(args2.cni)) {
668
+ const cni = args2.cluster.info.cni;
669
+ if (!cni || !_NetworkPolicy.supportedCNIs.includes(cni)) {
669
670
  return new NativeNetworkPolicy(name, args2, opts);
670
671
  }
671
- const implName = `${capitalize(args2.cni)}NetworkPolicy`;
672
- const implModule = await import(`@highstate/${args2.cni}`);
672
+ const implName = `${capitalize(cni)}NetworkPolicy`;
673
+ const implModule = await import(`@highstate/${cni}`);
673
674
  const implClass = implModule[implName];
674
675
  if (!implClass) {
675
- throw new Error(`No implementation found for ${args2.cni}`);
676
+ throw new Error(`No implementation found for ${cni}`);
676
677
  }
677
678
  return new implClass(name, args2, opts);
678
679
  });
679
680
  }
680
- static allowInsideNamespace(namespace, k8sCluster, opts) {
681
+ static allowInsideNamespace(namespace, cluster, opts) {
681
682
  return _NetworkPolicy.create(
682
683
  "allow-inside-namespace",
683
684
  {
684
685
  namespace,
685
- cni: output6(k8sCluster).info.cni,
686
+ cluster,
686
687
  description: "Allow all traffic inside the namespace.",
687
688
  selector: {},
688
689
  ingressRule: { fromNamespace: namespace },
@@ -691,36 +692,36 @@ var NetworkPolicy = class _NetworkPolicy extends ComponentResource5 {
691
692
  opts
692
693
  );
693
694
  }
694
- static allowKubeApiServer(namespace, k8sCluster, opts) {
695
+ static allowKubeApiServer(namespace, cluster, opts) {
695
696
  return _NetworkPolicy.create(
696
697
  "allow-kube-api-server",
697
698
  {
698
699
  namespace,
699
- cni: output6(k8sCluster).info.cni,
700
+ cluster,
700
701
  description: "Allow all traffic to the Kubernetes API server from the namespace.",
701
702
  allowKubeApiServer: true
702
703
  },
703
704
  opts
704
705
  );
705
706
  }
706
- static allowKubeDns(namespace, k8sCluster, opts) {
707
+ static allowKubeDns(namespace, cluster, opts) {
707
708
  return _NetworkPolicy.create(
708
709
  "allow-kube-dns",
709
710
  {
710
711
  namespace,
711
- cni: output6(k8sCluster).info.cni,
712
+ cluster,
712
713
  description: "Allow all traffic to the Kubernetes DNS server from the namespace.",
713
714
  allowKubeDns: true
714
715
  },
715
716
  opts
716
717
  );
717
718
  }
718
- static allowAllEgress(namespace, k8sCluster, opts) {
719
+ static allowAllEgress(namespace, cluster, opts) {
719
720
  return _NetworkPolicy.create(
720
721
  "allow-all-egress",
721
722
  {
722
723
  namespace,
723
- cni: output6(k8sCluster).info.cni,
724
+ cluster,
724
725
  description: "Allow all egress traffic from the namespace.",
725
726
  egressRule: { toAll: true }
726
727
  },
@@ -772,7 +773,12 @@ var NativeNetworkPolicy = class _NativeNetworkPolicy extends NetworkPolicy {
772
773
  }
773
774
  const extraRules = [];
774
775
  if (args.allowKubeApiServer) {
775
- extraRules.push({ to: [{ ipBlock: { cidr: "10.96.0.1" } }] });
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
+ });
776
782
  }
777
783
  return args.egressRules.map((rule) => {
778
784
  return {
@@ -857,9 +863,9 @@ function useAccessPoint(args) {
857
863
  },
858
864
  gateway: args2.accessPoint.gateway
859
865
  });
860
- const dnsRecords = normalize4(args2.fqdn, args2.fqdns).map((fqdn) => {
861
- return DnsRecord.create(fqdn, {
862
- provider: args2.accessPoint.dnsProvider,
866
+ const dnsRecords = normalize4(args2.fqdn, args2.fqdns).flatMap((fqdn) => {
867
+ return DnsRecord.createSet(fqdn, {
868
+ providers: args2.accessPoint.dnsProviders,
863
869
  type: "A",
864
870
  value: args2.accessPoint.gateway.ip
865
871
  });
@@ -871,8 +877,8 @@ function useAccessPoint(args) {
871
877
  NetworkPolicy.create(
872
878
  `allow-ingress-from-${getAppName(args2.accessPoint.gateway.service.metadata)}`,
873
879
  {
874
- cni: args2.accessPoint.gateway.service.clusterInfo.cni,
875
880
  namespace: args2.namespace,
881
+ cluster: args2.cluster,
876
882
  description: `Allow ingress traffic from the gateway "${displayName}".`,
877
883
  ingressRule: {
878
884
  fromNamespace: args2.accessPoint.gateway.service.metadata.namespace,
@@ -884,8 +890,8 @@ function useAccessPoint(args) {
884
890
  NetworkPolicy.create(
885
891
  `allow-egress-to-${namespaceName}`,
886
892
  {
887
- cni: args2.accessPoint.gateway.service.clusterInfo.cni,
888
893
  namespace: args2.accessPoint.gateway.service.metadata.namespace,
894
+ cluster: args2.cluster,
889
895
  selector: args2.accessPoint.gateway.service.spec.selector,
890
896
  description: `Allow egress traffic to the namespace "${namespaceName}".`,
891
897
  egressRule: {
@@ -898,7 +904,7 @@ function useAccessPoint(args) {
898
904
  }
899
905
  return output7({
900
906
  gateway: gateway2,
901
- dnsRecords,
907
+ dnsRecords: output7(dnsRecords).apply((records) => records.flat()),
902
908
  networkPolicies
903
909
  });
904
910
  }
@@ -911,13 +917,13 @@ function useStandardAcessPoint(appName, namespace, args, inputs, provider) {
911
917
  namespace,
912
918
  fqdn: args.fqdn,
913
919
  accessPoint: inputs.accessPoint,
914
- clusterInfo: inputs.k8sCluster.info,
920
+ cluster: inputs.k8sCluster,
915
921
  provider
916
922
  });
917
923
  }
918
924
  function createGateway(args) {
919
925
  return output7(args).apply((args2) => {
920
- if (args2.clusterInfo.id !== args2.gateway.clusterInfo.id) {
926
+ if (args2.cluster.info.id !== args2.gateway.clusterInfo.id) {
921
927
  throw new Error(
922
928
  "The provided Kubernetes cluster is different from the one where the gateway controller is deployed."
923
929
  );
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/deployment.ts","../src/container.ts","../src/pvc.ts","../src/workload.ts","../src/stateful-set.ts","../src/network-policy.ts","../src/access-point.ts","../src/scripting/bundle.ts","../src/scripting/environment.ts","../src/scripting/container.ts","../src/job.ts","../src/cron-job.ts"],"sourcesContent":["import type { k8s } from \"@highstate/library\"\nimport type { HttpRoute } from \"./gateway\"\nimport type { Service } from \"./service\"\nimport {\n output,\n type ComponentResourceOptions,\n Output,\n type Inputs,\n ComponentResource,\n type InputArray,\n Resource,\n type Input,\n type InstanceTerminal,\n interpolate,\n} from \"@highstate/pulumi\"\nimport { apps, types } from \"@pulumi/kubernetes\"\nimport { omit } from \"remeda\"\nimport { deepmerge } from \"deepmerge-ts\"\nimport { trimIndentation } from \"@highstate/contract\"\nimport { mapMetadata, verifyProvider } from \"./shared\"\nimport { mapContainerToRaw } from \"./container\"\nimport {\n getPublicWorkloadComponents,\n publicWorkloadExtraArgs,\n type PublicWorkloadArgs,\n} from \"./workload\"\n\nexport type DeploymentArgs = Omit<PublicWorkloadArgs, \"patch\"> & {\n patch?: Input<k8s.Deployment>\n\n /**\n * The shell to use in the terminal.\n *\n * By default, `bash` is used.\n */\n terminalShell?: string\n} & Omit<Partial<types.input.apps.v1.DeploymentSpec>, \"template\"> & {\n template?: {\n metadata?: types.input.meta.v1.ObjectMeta\n spec?: Partial<types.input.core.v1.PodSpec>\n }\n }\n\nexport abstract class Deployment extends ComponentResource {\n protected constructor(\n type: string,\n name: string,\n private readonly args: Inputs,\n opts: ComponentResourceOptions,\n\n /**\n * The cluster where the deployment is created.\n */\n readonly cluster: Output<k8s.Cluster>,\n\n /**\n * The metadata of the underlying Kubernetes deployment.\n */\n readonly metadata: Output<types.output.meta.v1.ObjectMeta>,\n\n /**\n * The spec of the underlying Kubernetes deployment.\n */\n readonly spec: Output<types.output.apps.v1.DeploymentSpec>,\n\n /**\n * The status of the underlying Kubernetes deployment.\n */\n readonly status: Output<types.output.apps.v1.DeploymentStatus>,\n\n private readonly _service: Output<Service | undefined>,\n private readonly _httpRoute: Output<HttpRoute | undefined>,\n\n /**\n * The resources associated with the deployment.\n */\n readonly resources: InputArray<Resource>,\n ) {\n super(type, name, args, opts)\n }\n\n /**\n * The Highstate deployment entity.\n */\n get entity(): Output<k8s.Deployment> {\n return output({\n type: \"k8s.deployment\",\n clusterInfo: this.cluster.info,\n metadata: this.metadata,\n spec: this.spec,\n service: this._service.apply(service => service?.entity),\n })\n }\n\n get optionalService(): Output<Service | undefined> {\n return this._service\n }\n\n /**\n * The service associated with the deployment.\n */\n get service(): Output<Service> {\n return this._service.apply(service => {\n if (!service) {\n throw new Error(\"The service is not available.\")\n }\n\n return service\n })\n }\n\n /**\n * The HTTP route associated with the deployment.\n */\n get httpRoute(): Output<HttpRoute> {\n return this._httpRoute.apply(httpRoute => {\n if (!httpRoute) {\n throw new Error(\"The HTTP route is not available.\")\n }\n\n return httpRoute\n })\n }\n\n /**\n * The instance terminal to interact with the deployment.\n */\n get terminal(): Output<InstanceTerminal> {\n return output({\n name: this.metadata.name,\n title: this.metadata.name,\n image: \"ghcr.io/exeteres/highstate/terminal-kubectl\",\n command: [\"script\", \"-q\", \"-c\", \"/enter-container.sh\", \"/dev/null\"],\n files: {\n \"/kubeconfig\": this.cluster.kubeconfig,\n\n \"/enter-container.sh\": {\n mode: 0o755,\n content: interpolate`\n #!/bin/bash\n\n exec kubectl exec -it -n ${this.metadata.namespace} deployment/${this.metadata.name} -- ${this.args.terminalShell ?? \"bash\"}\n `.apply(trimIndentation),\n },\n },\n env: {\n KUBECONFIG: \"/kubeconfig\",\n },\n })\n }\n\n static create(name: string, args: DeploymentArgs, opts: ComponentResourceOptions): Deployment {\n return new CreatedDeployment(name, args, opts)\n }\n}\n\nclass CreatedDeployment extends Deployment {\n constructor(name: string, args: DeploymentArgs, opts: ComponentResourceOptions) {\n const { labels, containers, volumes, service, httpRoute } = getPublicWorkloadComponents(\n name,\n args,\n () => this,\n opts,\n )\n\n const deployment = output({ args, containers, volumes }).apply(\n async ({ args, containers, volumes }) => {\n await verifyProvider(opts.provider, args.cluster.info)\n\n return new (args.patch ? apps.v1.DeploymentPatch : apps.v1.Deployment)(\n name,\n {\n metadata: mapMetadata(args.patch?.metadata ?? args, name),\n spec: deepmerge(\n {\n template: {\n metadata: !args.patch ? { labels } : undefined,\n spec: {\n containers: containers.map(container => mapContainerToRaw(container, name)),\n volumes,\n },\n },\n selector: !args.patch ? { matchLabels: labels } : undefined,\n },\n omit(args, publicWorkloadExtraArgs),\n ),\n },\n { parent: this, ...opts },\n )\n },\n )\n\n super(\n \"highstate:k8s:Deployment\",\n name,\n args,\n opts,\n\n output(args.cluster),\n deployment.metadata,\n deployment.spec,\n deployment.status,\n\n service,\n httpRoute,\n\n [deployment],\n )\n }\n}\n","import type { PartialKeys } from \"@highstate/contract\"\nimport { core, type types } from \"@pulumi/kubernetes\"\nimport { normalize, output, type Input, type InputArray, type Unwrap } from \"@highstate/pulumi\"\nimport { concat, map, omit } from \"remeda\"\nimport { PersistentVolumeClaim } from \"./pvc\"\n\nexport type Container = Omit<PartialKeys<types.input.core.v1.Container, \"name\">, \"volumeMounts\"> & {\n /**\n * The single port to add to the container.\n */\n port?: Input<types.input.core.v1.ContainerPort>\n\n /**\n * The volume mount to attach to the container.\n */\n volumeMount?: Input<ContainerVolumeMount>\n\n /**\n * The volume mounts to attach to the container.\n */\n volumeMounts?: InputArray<ContainerVolumeMount>\n\n /**\n * The volume to include in the parent workload.\n * It is like the `volumes` property, but defined at the container level.\n * It will be defined as a volume mount in the parent workload automatically.\n */\n volume?: Input<WorkloadVolume>\n\n /**\n * The volumes to include in the parent workload.\n * It is like the `volumes` property, but defined at the container level.\n * It will be defined as a volume mount in the parent workload automatically.\n */\n volumes?: InputArray<WorkloadVolume>\n\n /**\n * The map of environment variables to set in the container.\n * It is like the `env` property, but more convenient to use.\n */\n environment?: Input<ContainerEnvironment>\n\n /**\n * The source of environment variables to set in the container.\n * It is like the `envFrom` property, but more convenient to use.\n */\n environmentSource?: Input<ContainerEnvironmentSource>\n\n /**\n * The sources of environment variables to set in the container.\n * It is like the `envFrom` property, but more convenient to use.\n */\n environmentSources?: InputArray<ContainerEnvironmentSource>\n}\n\nconst containerExtraArgs = [\n \"port\",\n \"volumeMount\",\n \"volume\",\n \"environment\",\n \"environmentSource\",\n \"environmentSources\",\n] as const\n\nexport type ContainerEnvironment = Record<\n string,\n Input<string | undefined | null | ContainerEnvironmentVariable>\n>\n\nexport type ContainerEnvironmentVariable =\n | types.input.core.v1.EnvVarSource\n | {\n /**\n * The secret to select from.\n */\n secret: Input<core.v1.Secret>\n\n /**\n * The key of the secret to select from.\n */\n key: string\n }\n | {\n /**\n * The config map to select from.\n */\n configMap: Input<core.v1.ConfigMap>\n\n /**\n * The key of the config map to select from.\n */\n key: string\n }\n\nexport type ContainerEnvironmentSource =\n | types.input.core.v1.EnvFromSource\n | core.v1.ConfigMap\n | core.v1.Secret\n\nexport type ContainerVolumeMount =\n | types.input.core.v1.VolumeMount\n | (Omit<types.input.core.v1.VolumeMount, \"name\"> & {\n /**\n * The volume to mount.\n */\n volume: Input<WorkloadVolume>\n })\n\nexport type WorkloadVolume =\n | types.input.core.v1.Volume\n | core.v1.PersistentVolumeClaim\n | PersistentVolumeClaim\n | core.v1.ConfigMap\n | core.v1.Secret\n\nexport function mapContainerToRaw(\n container: Unwrap<Container>,\n fallbackName: string,\n): types.input.core.v1.Container {\n const containerName = container.name ?? fallbackName\n\n return {\n ...omit(container, containerExtraArgs),\n\n name: containerName,\n ports: normalize(container.port, container.ports),\n\n volumeMounts: map(normalize(container.volumeMount, container.volumeMounts), mapVolumeMount),\n\n env: concat(\n container.environment ? mapContainerEnvironment(container.environment) : [],\n container.env ?? [],\n ),\n\n envFrom: concat(\n map(\n normalize(container.environmentSource, container.environmentSources),\n mapEnvironmentSource,\n ),\n container.envFrom ?? [],\n ),\n }\n}\n\nexport function mapContainerEnvironment(\n environment: Unwrap<ContainerEnvironment>,\n): types.input.core.v1.EnvVar[] {\n const envVars: types.input.core.v1.EnvVar[] = []\n\n for (const [name, value] of Object.entries(environment)) {\n if (!value) {\n continue\n }\n\n if (typeof value === \"string\") {\n envVars.push({ name, value })\n continue\n }\n\n if (\"secret\" in value) {\n envVars.push({\n name,\n valueFrom: {\n secretKeyRef: {\n name: value.secret.metadata.name,\n key: value.key,\n },\n },\n })\n continue\n }\n\n if (\"configMap\" in value) {\n envVars.push({\n name,\n valueFrom: {\n configMapKeyRef: {\n name: value.configMap.metadata.name,\n key: value.key,\n },\n },\n })\n continue\n }\n\n envVars.push({ name, valueFrom: value })\n }\n\n return envVars\n}\n\nexport function mapVolumeMount(volumeMount: ContainerVolumeMount): types.input.core.v1.VolumeMount {\n if (\"volume\" in volumeMount) {\n return omit(\n {\n ...volumeMount,\n name: output(volumeMount.volume)\n .apply(mapWorkloadVolume)\n .apply(volume => output(volume.name)),\n },\n [\"volume\"],\n )\n }\n\n return {\n ...volumeMount,\n name: volumeMount.name,\n }\n}\n\nexport function mapEnvironmentSource(\n envFrom: ContainerEnvironmentSource,\n): types.input.core.v1.EnvFromSource {\n if (envFrom instanceof core.v1.ConfigMap) {\n return {\n configMapRef: {\n name: envFrom.metadata.name,\n },\n }\n }\n\n if (envFrom instanceof core.v1.Secret) {\n return {\n secretRef: {\n name: envFrom.metadata.name,\n },\n }\n }\n\n return envFrom\n}\n\nexport function mapWorkloadVolume(volume: WorkloadVolume) {\n if (volume instanceof PersistentVolumeClaim) {\n return {\n name: volume.metadata.name,\n persistentVolumeClaim: {\n claimName: volume.metadata.name,\n },\n }\n }\n\n if (volume instanceof core.v1.PersistentVolumeClaim) {\n return {\n name: volume.metadata.name,\n persistentVolumeClaim: {\n claimName: volume.metadata.name,\n },\n }\n }\n\n if (volume instanceof core.v1.ConfigMap) {\n return {\n name: volume.metadata.name,\n configMap: {\n name: volume.metadata.name,\n },\n }\n }\n\n if (volume instanceof core.v1.Secret) {\n return {\n name: volume.metadata.name,\n secret: {\n secretName: volume.metadata.name,\n },\n }\n }\n\n return volume\n}\n","import type { k8s } from \"@highstate/library\"\nimport { core, type types } from \"@pulumi/kubernetes\"\nimport {\n ComponentResource,\n Output,\n output,\n type ComponentResourceOptions,\n type CustomResourceOptions,\n type Input,\n type Inputs,\n} from \"@highstate/pulumi\"\nimport { deepmerge } from \"deepmerge-ts\"\nimport { omit } from \"remeda\"\nimport {\n commonExtraArgs,\n mapMetadata,\n resourceIdToString,\n verifyProvider,\n type CommonArgs,\n type ResourceId,\n} from \"./shared\"\n\nexport type PersistentVolumeClaimArgs = CommonArgs &\n types.input.core.v1.PersistentVolumeClaimSpec & {\n /**\n * The size of the volume to request.\n *\n * By default, the size is set to \"100Mi\".\n */\n size?: string\n\n /**\n * The cluster to create the resource in.\n */\n cluster: Input<k8s.Cluster>\n }\n\nconst extraPersistentVolumeClaimArgs = [...commonExtraArgs, \"size\", \"cluster\"] as const\n\nexport abstract class PersistentVolumeClaim extends ComponentResource {\n protected constructor(\n type: string,\n name: string,\n args: Inputs,\n opts: ComponentResourceOptions,\n\n /**\n * The cluster info associated with the pvc.\n */\n readonly clusterInfo: Output<k8s.ClusterInfo>,\n\n /**\n * The metadata of the underlying Kubernetes pvc.\n */\n readonly metadata: Output<types.output.meta.v1.ObjectMeta>,\n\n /**\n * The spec of the underlying Kubernetes pvc.\n */\n readonly spec: Output<types.output.core.v1.PersistentVolumeClaimSpec>,\n\n /**\n * The status of the underlying Kubernetes pvc.\n */\n readonly status: Output<types.output.core.v1.PersistentVolumeClaimStatus>,\n ) {\n super(type, name, args, opts)\n }\n\n /**\n * The Highstate service entity.\n */\n get entity(): Output<k8s.PersistentVolumeClaim> {\n return output({\n type: \"k8s.persistent-volume-claim\",\n clusterInfo: this.clusterInfo,\n metadata: this.metadata,\n })\n }\n\n static create(\n name: string,\n args: PersistentVolumeClaimArgs,\n opts: ComponentResourceOptions,\n ): PersistentVolumeClaim {\n return new CreatedPersistentVolumeClaim(name, args, opts)\n }\n\n static of(\n name: string,\n entity: Input<k8s.PersistentVolumeClaim>,\n opts: ComponentResourceOptions,\n ): PersistentVolumeClaim {\n return new ExternalPersistentVolumeClaim(\n name,\n output(entity).metadata,\n output(entity).clusterInfo,\n opts,\n )\n }\n}\n\nexport class CreatedPersistentVolumeClaim extends PersistentVolumeClaim {\n constructor(name: string, args: PersistentVolumeClaimArgs, opts: CustomResourceOptions) {\n const pvc = output(args).apply(args => {\n return new core.v1.PersistentVolumeClaim(\n name,\n {\n metadata: mapMetadata(args, name),\n spec: deepmerge(\n {\n accessModes: [\"ReadWriteOnce\"],\n resources: {\n requests: {\n storage: args.size ?? \"100Mi\",\n },\n },\n } satisfies types.input.core.v1.PersistentVolumeClaimSpec,\n omit(args, extraPersistentVolumeClaimArgs),\n ),\n },\n opts,\n )\n })\n\n super(\n \"k8s:PersistentVolumeClaim\",\n name,\n args,\n opts,\n\n output(args.cluster).info,\n pvc.metadata,\n pvc.spec,\n pvc.status,\n )\n }\n}\n\nexport class ExternalPersistentVolumeClaim extends PersistentVolumeClaim {\n constructor(\n name: string,\n id: Input<ResourceId>,\n clusterInfo: Input<k8s.ClusterInfo>,\n opts: ComponentResourceOptions,\n ) {\n const pvc = output(id).apply(async id => {\n await verifyProvider(opts.provider, this.clusterInfo)\n\n return core.v1.PersistentVolumeClaim.get(\n //\n name,\n resourceIdToString(id),\n { parent: this, provider: opts.provider },\n )\n })\n\n super(\n \"highstate:k8s:ExternalPersistentVolumeClaim\",\n name,\n { id, clusterInfo },\n opts,\n\n output(clusterInfo),\n pvc.metadata,\n pvc.spec,\n pvc.status,\n )\n }\n}\n\nexport function getAutoVolumeName(workloadName: string, index: number): string {\n if (index === 0) {\n return `${workloadName}-data`\n }\n\n return `${workloadName}-data-${index}`\n}\n","import type { types } from \"@pulumi/kubernetes\"\nimport type { k8s } from \"@highstate/library\"\nimport { normalize, type ComponentResourceOptions, type InputArray } from \"@highstate/pulumi\"\nimport { ComponentResource, output, type Input, type Output } from \"@pulumi/pulumi\"\nimport { uniqueBy } from \"remeda\"\nimport { commonExtraArgs, type CommonArgs } from \"./shared\"\nimport { mapContainerPortToServicePort, Service, type ServiceArgs } from \"./service\"\nimport { HttpRoute, type HttpRouteArgs } from \"./gateway\"\nimport {\n mapContainerToRaw,\n mapWorkloadVolume,\n type Container,\n type WorkloadVolume,\n} from \"./container\"\n\nexport type WorkloadArgs = CommonArgs & {\n container?: Input<Container>\n containers?: InputArray<Container>\n\n /**\n * The cluster to create the resource in.\n */\n cluster: Input<k8s.Cluster>\n}\n\nexport const workloadExtraArgs = [...commonExtraArgs, \"container\", \"containers\"] as const\n\nexport class WorkloadBase<TArgs extends WorkloadArgs> extends ComponentResource {\n protected readonly containers: Output<types.input.core.v1.Container[]>\n protected readonly volumes: Output<types.input.core.v1.Volume[]>\n\n constructor(type: string, name: string, args: TArgs, opts: ComponentResourceOptions | undefined) {\n super(type, name, args, opts)\n\n const containers = output(args).apply(args => normalize(args.container, args.containers))\n\n this.containers = containers.apply(containers =>\n containers.map(container => mapContainerToRaw(container, name)),\n )\n\n this.volumes = containers.apply(containers =>\n containers\n .flatMap(container => normalize(container.volume, container.volumes))\n .map(mapWorkloadVolume),\n )\n }\n}\n\nexport type PublicWorkloadArgs = WorkloadArgs & {\n service?: Input<Omit<ServiceArgs, \"cluster\" | \"namespace\">>\n httpRoute?: Input<Omit<HttpRouteArgs, \"cluster\" | \"namespace\">>\n patch?: Input<k8s.Deployment | k8s.StatefulSet>\n} & Partial<types.input.apps.v1.StatefulSetSpec>\n\nexport const publicWorkloadExtraArgs = [...workloadExtraArgs, \"service\", \"httpRoute\"] as const\n\nexport function getWorkloadComponents(name: string, args: WorkloadArgs) {\n const labels = {\n \"app.kubernetes.io/name\": name,\n }\n\n const containers = output(args).apply(args => normalize(args.container, args.containers))\n const volumes = containers.apply(containers => {\n const containerVolumes = containers\n .flatMap(container => normalize(container.volume, container.volumes))\n .map(mapWorkloadVolume)\n\n const containerVolumeMounts = containers\n .flatMap(container => {\n return normalize(container.volumeMount, container.volumeMounts)\n .map(volumeMount => {\n return \"volume\" in volumeMount ? volumeMount.volume : undefined\n })\n .filter(Boolean) as WorkloadVolume[]\n })\n .map(mapWorkloadVolume)\n\n return uniqueBy([...containerVolumes, ...containerVolumeMounts], volume => volume.name)\n })\n\n return { labels, containers, volumes }\n}\n\nexport function getPublicWorkloadComponents(\n name: string,\n args: PublicWorkloadArgs,\n parent: () => ComponentResource,\n opts: ComponentResourceOptions,\n) {\n const { labels, containers, volumes } = getWorkloadComponents(name, args)\n\n const service = output({ args, containers }).apply(({ args, containers }) => {\n if (!args.service && !args.httpRoute) {\n return undefined\n }\n\n if (args.patch?.service) {\n return Service.of(name, args.patch.service, { parent: parent(), ...opts })\n }\n\n if (args.patch) {\n return undefined\n }\n\n const ports = containers.flatMap(container => normalize(container.port, container.ports))\n\n return Service.create(\n name,\n {\n ...args.service,\n selector: labels,\n cluster: args.cluster,\n namespace: args.namespace,\n\n ports:\n // allow to completely override the ports\n !args.service?.port && !args.service?.ports\n ? ports.map(mapContainerPortToServicePort)\n : args.service?.ports,\n },\n { parent: parent(), ...opts },\n )\n })\n\n const httpRoute = output({\n args,\n service,\n }).apply(({ args, service }) => {\n if (!args.httpRoute || !service) {\n return undefined\n }\n\n if (args.patch) {\n return undefined\n }\n\n return new HttpRoute(\n name,\n {\n ...args.httpRoute,\n rule: {\n backend: service,\n },\n },\n { parent: parent(), ...opts },\n )\n })\n\n return { labels, containers, volumes, service, httpRoute }\n}\n","import type { k8s } from \"@highstate/library\"\nimport type { HttpRoute } from \"./gateway\"\nimport type { Service } from \"./service\"\nimport {\n output,\n type ComponentResourceOptions,\n ComponentResource,\n Output,\n type Inputs,\n type Input,\n} from \"@highstate/pulumi\"\nimport { apps, type types } from \"@pulumi/kubernetes\"\nimport { omit } from \"remeda\"\nimport { deepmerge } from \"deepmerge-ts\"\nimport {\n getPublicWorkloadComponents,\n publicWorkloadExtraArgs,\n type PublicWorkloadArgs,\n} from \"./workload\"\nimport { mapMetadata, verifyProvider } from \"./shared\"\nimport { mapContainerToRaw } from \"./container\"\n\nexport type StatefulSetArgs = Omit<PublicWorkloadArgs, \"patch\"> & {\n patch?: Input<k8s.StatefulSet>\n} & Partial<types.input.apps.v1.StatefulSetSpec>\n\nexport abstract class StatefulSet extends ComponentResource {\n protected constructor(\n type: string,\n name: string,\n args: Inputs,\n opts: ComponentResourceOptions,\n\n /**\n * The cluster info associated with the stateful set.\n */\n readonly clusterInfo: Output<k8s.ClusterInfo>,\n\n /**\n * The metadata of the underlying Kubernetes stateful set.\n */\n readonly metadata: Output<types.output.meta.v1.ObjectMeta>,\n\n /**\n * The spec of the underlying Kubernetes stateful set.\n */\n readonly spec: Output<types.output.apps.v1.StatefulSetSpec>,\n\n /**\n * The status of the underlying Kubernetes stateful set.\n */\n readonly status: Output<types.output.apps.v1.StatefulSetStatus>,\n\n private readonly _service: Output<Service | undefined>,\n private readonly _httpRoute: Output<HttpRoute | undefined>,\n ) {\n super(type, name, args, opts)\n }\n\n /**\n * The Highstate stateful set entity.\n */\n get entity(): Output<k8s.StatefulSet> {\n return output({\n type: \"k8s.stateful-set\",\n clusterInfo: this.clusterInfo,\n metadata: this.metadata,\n service: this.service.entity,\n })\n }\n\n get optionalService(): Output<Service | undefined> {\n return this._service\n }\n\n /**\n * The service associated with the stateful set.\n */\n get service(): Output<Service> {\n return this._service.apply(service => {\n if (!service) {\n throw new Error(\"The service is not available.\")\n }\n\n return service\n })\n }\n\n /**\n * The HTTP route associated with the stateful set.\n */\n get httpRoute(): Output<HttpRoute> {\n return this._httpRoute.apply(httpRoute => {\n if (!httpRoute) {\n throw new Error(\"The HTTP route is not available.\")\n }\n\n return httpRoute\n })\n }\n\n static create(name: string, args: StatefulSetArgs, opts: ComponentResourceOptions): StatefulSet {\n return new CreatedStatefulSet(name, args, opts)\n }\n}\n\nclass CreatedStatefulSet extends StatefulSet {\n constructor(name: string, args: StatefulSetArgs, opts: ComponentResourceOptions) {\n const { containers, volumes, labels, service, httpRoute } = getPublicWorkloadComponents(\n name,\n args,\n () => this,\n opts,\n )\n\n const statefulSet = output({ args, containers, volumes, service }).apply(\n async ({ args, containers, volumes, service }) => {\n await verifyProvider(opts.provider, args.cluster?.info)\n\n return new (args.patch ? apps.v1.StatefulSetPatch : apps.v1.StatefulSet)(\n name,\n {\n metadata: mapMetadata(args.patch?.metadata ?? args, name),\n spec: deepmerge(\n {\n serviceName: service?.metadata.name || name,\n template: {\n metadata: !args.patch ? { labels } : undefined,\n spec: {\n containers: containers.map(container => mapContainerToRaw(container, name)),\n volumes,\n },\n },\n selector: !args.patch ? { matchLabels: labels } : undefined,\n },\n omit(args, publicWorkloadExtraArgs),\n ),\n },\n { parent: this, ...opts },\n )\n },\n )\n\n super(\n \"highstate:k8s:StatefulSet\",\n name,\n args,\n opts,\n\n output(args.cluster).info,\n statefulSet.metadata,\n statefulSet.spec,\n statefulSet.status,\n\n service,\n httpRoute,\n )\n }\n}\n","import { networking, types, type core } from \"@pulumi/kubernetes\"\nimport {\n ComponentResource,\n normalize,\n output,\n type Input,\n type InputArray,\n type Output,\n type Resource,\n type ResourceOptions,\n type Unwrap,\n} from \"@highstate/pulumi\"\nimport { capitalize, flat, merge, mergeDeep } from \"remeda\"\nimport { parseDomain, ParseResultType, type ParseResultIp } from \"parse-domain\"\nimport { k8s } from \"@highstate/library\"\nimport {\n mapMetadata,\n mapNamespaceLikeToNamespaceName,\n mapNamespaceNameToSelector,\n mapSelectorLikeToSelector,\n type CommonArgs,\n type NamespaceLike,\n type SelectorLike,\n} from \"./shared\"\nimport { mapServiceToLabelSelector } from \"./service\"\n\nexport type NetworkPolicyPort = {\n /**\n * The protocol to match.\n *\n * If not provided, \"TCP\" will be used.\n */\n protocol?: string\n} & (\n | {\n /**\n * The single port to match.\n */\n port: number\n }\n | {\n /**\n * The range of ports to match.\n */\n range: [start: number, end: number]\n }\n)\n\nexport type IngressRuleArgs = {\n /**\n * Whether to allow all incoming traffic.\n *\n * If set to `true`, all other rules will be ignored for matched traffic.\n */\n fromAll?: Input<boolean>\n\n /**\n * The allowed cidr for incoming traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n fromCidr?: Input<string>\n\n /**\n * The list of allowed cidrs for incoming traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n fromCidrs?: InputArray<string>\n\n /**\n * The service to allow traffic from.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n fromService?: Input<core.v1.Service>\n\n /**\n * The list of allowed services for incoming traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n fromServices?: InputArray<core.v1.Service>\n\n /**\n * The namespace to allow traffic from.\n *\n * If provided with `fromSelector(s)`, it will be ANDed with them.\n * Otherwise, it will match all pods in the namespace.\n *\n * Will be ORed with other conditions inside the same rule (except ports and selectors).\n */\n fromNamespace?: Input<NamespaceLike>\n\n /**\n * The list of allowed namespaces for incoming traffic.\n *\n * If provided with `fromSelector(s)`, it will be ANDed with them.\n * Otherwise, it will match all pods in the namespaces.\n *\n * Will be ORed with other conditions inside the same rule (except ports and selectors).\n */\n fromNamespaces?: InputArray<NamespaceLike>\n\n /**\n * The selector for incoming traffic.\n *\n * If provided with `fromNamespace(s)`, it will be ANDed with them.\n * Otherwise, it will match pods in all namespaces.\n *\n * Will be ORed with other conditions inside the same rule (except ports and namespaces).\n */\n fromSelector?: Input<SelectorLike>\n\n /**\n * The list of selectors for incoming traffic.\n *\n * If provided with `fromNamespace(s)`, it will be ANDed with them.\n * Otherwise, it will match pods in all namespaces.\n *\n * Will be ORed with other conditions inside the same rule (except ports and namespaces).\n */\n fromSelectors?: InputArray<SelectorLike>\n\n /**\n * The port to allow incoming traffic on.\n *\n * Will be ANDed with all conditions inside the same rule.\n */\n toPort?: Input<NetworkPolicyPort>\n\n /**\n * The list of allowed ports for incoming traffic.\n *\n * Will be ANDed with all conditions inside the same rule.\n */\n toPorts?: InputArray<NetworkPolicyPort>\n}\n\nexport type EgressRuleArgs = {\n /**\n * Whether to allow all outgoing traffic.\n *\n * If set to `true`, all other rules will be ignored for matched traffic.\n */\n toAll?: Input<boolean>\n\n /**\n * The allowed cidr for outgoing traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toCidr?: Input<string>\n\n /**\n * The list of allowed cidrs for outgoing traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toCidrs?: InputArray<string>\n\n /**\n * The FQDN to allow outgoing traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toFqdn?: Input<string>\n\n /**\n * The list of allowed FQDNs for outgoing traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toFqdns?: InputArray<string>\n\n /**\n * Either the FQDN or the IP address of the endpoint to allow outgoing traffic.\n *\n * Just a syntactic sugar for `toFqdn` and `toCidr` for cases when the endpoint can be both.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toEndpoint?: Input<string>\n\n /**\n * The list of allowed endpoints for outgoing traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toEndpoints?: InputArray<string>\n\n /**\n * The service to allow traffic to.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toService?: Input<core.v1.Service>\n\n /**\n * The list of allowed services for outgoing traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toServices?: InputArray<core.v1.Service>\n\n /**\n * The namespace to allow traffic to.\n *\n * If provided with `toSelector(s)`, it will be ANDed with them.\n * Otherwise, it will match all pods in the namespace.\n *\n * Will be ORed with other conditions inside the same rule (except ports and selectors).\n */\n toNamespace?: Input<NamespaceLike>\n\n /**\n * The list of allowed namespaces for outgoing traffic.\n *\n * If provided with `toSelector(s)`, it will be ANDed with them.\n * Otherwise, it will match all pods in the namespaces.\n *\n * Will be ORed with other conditions inside the same rule (except ports and selectors).\n */\n toNamespaces?: InputArray<NamespaceLike>\n\n /**\n * The selector for outgoing traffic.\n *\n * If provided with `toNamespace(s)`, it will be ANDe with them.\n *\n * Otherwise, it will match pods only in all namespaces.\n */\n toSelector?: Input<SelectorLike>\n\n /**\n * The list of selectors for outgoing traffic.\n *\n * If provided with `toNamespace(s)`, it will be ANDed with them.\n * Otherwise, it will match pods only in all namespaces.\n */\n toSelectors?: InputArray<SelectorLike>\n\n /**\n * The port to allow outgoing traffic on.\n *\n * Will be ANDed with all conditions inside the same rule.\n */\n toPort?: Input<NetworkPolicyPort>\n\n /**\n * The list of allowed ports for outgoing traffic.\n *\n * Will be ANDed with all conditions inside the same rule.\n */\n toPorts?: InputArray<NetworkPolicyPort>\n}\n\nexport type NetworkPolicyArgs = CommonArgs & {\n /**\n * The description of this network policy.\n */\n description?: Input<string>\n\n /**\n * The pod selector for this network policy.\n * If not provided, it will select all pods in the namespace.\n */\n selector?: SelectorLike\n\n /**\n * The rule for incoming traffic.\n */\n ingressRule?: Input<IngressRuleArgs>\n\n /**\n * The rules for incoming traffic.\n */\n ingressRules?: InputArray<IngressRuleArgs>\n\n /**\n * The rule for outgoing traffic.\n */\n egressRule?: Input<EgressRuleArgs>\n\n /**\n * The rules for outgoing traffic.\n */\n egressRules?: InputArray<EgressRuleArgs>\n\n /**\n * Enable the isolation of ingress traffic, so that only matched traffic can ingress.\n */\n isolateIngress?: Input<boolean>\n\n /**\n * Enable the isolation of egress traffic, so that only matched traffic can egress.\n */\n isolateEgress?: Input<boolean>\n\n /**\n * Allow the eggress traffic to the API server of the cluster.\n *\n * By default, `false`.\n */\n allowKubeApiServer?: Input<boolean>\n\n /**\n * Allow the eggress traffic to the DNS server of the cluster.\n *\n * By default, `false`.\n */\n allowKubeDns?: Input<boolean>\n}\n\nexport type FullNetworkPolicyArgs = NetworkPolicyArgs & {\n /**\n * The name of the CNI plugin to use for creating network policies.\n * If not provided or set to `unknown`, it will use the native `NetworkPolicy` resource.\n */\n cni?: Input<string | undefined>\n}\n\nexport type NormalizedRuleArgs = {\n all: boolean\n cidrs: string[]\n fqdns: string[]\n services: core.v1.Service[]\n namespaces: NamespaceLike[]\n selectors: SelectorLike[]\n ports: NetworkPolicyPort[]\n}\n\nexport type NormalizedNetworkPolicyArgs = Omit<\n Unwrap<NetworkPolicyArgs>,\n | \"podSelector\"\n | \"ingressRule\"\n | \"ingressRules\"\n | \"egressRule\"\n | \"egressRules\"\n | \"isolateIngress\"\n | \"isolateEgress\"\n | \"allowKubeApiServer\"\n | \"allowKubeDNS\"\n> & {\n podSelector: Unwrap<types.input.meta.v1.LabelSelector>\n\n isolateIngress: boolean\n isolateEgress: boolean\n\n allowKubeApiServer: boolean\n\n ingressRules: NormalizedRuleArgs[]\n egressRules: NormalizedRuleArgs[]\n}\n\n/**\n * The abstract resource for creating network policies.\n * Will use different resources depending on the environment.\n *\n * Note: In the worst case, it will create native `NetworkPolicy` resources and ignore some features like L7 rules.\n */\nexport abstract class NetworkPolicy extends ComponentResource {\n /**\n * The underlying network policy resource.\n */\n public readonly networkPolicy: Output<Resource>\n\n protected constructor(name: string, args: Unwrap<NetworkPolicyArgs>, opts?: ResourceOptions) {\n super(\"k8s:network-policy\", name, args, opts)\n\n const normalizedArgs = output(args).apply(args => {\n const ingressRules = normalize(args.ingressRule, args.ingressRules)\n const egressRules = normalize(args.egressRule, args.egressRules)\n\n const endpoints = normalize(args.egressRule?.toEndpoint, args.egressRule?.toEndpoints)\n const parsedEndpoints = endpoints.map(endpoint => parseDomain(endpoint))\n\n const cidrsFromEndpoints = parsedEndpoints\n .filter(result => result.type === ParseResultType.Ip)\n .map(result => NetworkPolicy.mapCidrFromEndpoint(result))\n\n const fqdnsFromEndpoints = parsedEndpoints\n .filter(result => result.type !== ParseResultType.Invalid)\n .map(result => result.hostname)\n\n const extraEgressRules: NormalizedRuleArgs[] = []\n\n if (args.allowKubeDns) {\n extraEgressRules.push({\n namespaces: [\"kube-system\"],\n selectors: [{ matchLabels: { \"k8s-app\": \"kube-dns\" } }],\n ports: [{ port: 53, protocol: \"UDP\" }],\n all: false,\n cidrs: [],\n fqdns: [],\n services: [],\n })\n }\n\n return {\n ...args,\n\n podSelector: args.selector ? mapSelectorLikeToSelector(args.selector) : {},\n\n isolateEgress: args.isolateEgress ?? false,\n isolateIngress: args.isolateIngress ?? false,\n\n allowKubeApiServer: args.allowKubeApiServer ?? false,\n\n ingressRules: ingressRules.map(rule => ({\n all: rule.fromAll ?? false,\n cidrs: normalize(rule.fromCidr, rule.fromCidrs),\n fqdns: [],\n services: normalize(rule.fromService, rule.fromServices),\n namespaces: normalize(rule.fromNamespace, rule.fromNamespaces),\n selectors: normalize(rule.fromSelector, rule.fromSelectors),\n ports: normalize(rule.toPort, rule.toPorts),\n })),\n\n egressRules: egressRules\n .map(rule => {\n return {\n all: rule.toAll ?? false,\n cidrs: normalize(rule.toCidr, rule.toCidrs).concat(cidrsFromEndpoints),\n fqdns: normalize(rule.toFqdn, rule.toFqdns).concat(fqdnsFromEndpoints),\n services: normalize(rule.toService, rule.toServices),\n namespaces: normalize(rule.toNamespace, rule.toNamespaces),\n selectors: normalize(rule.toSelector, rule.toSelectors),\n ports: normalize(rule.toPort, rule.toPorts),\n } as NormalizedRuleArgs\n })\n .concat(extraEgressRules),\n }\n })\n\n this.networkPolicy = normalizedArgs.apply(args => {\n return output(\n this.create(name, args as NormalizedNetworkPolicyArgs, { ...opts, parent: this }),\n )\n })\n\n this.registerOutputs({ networkPolicy: this.networkPolicy })\n }\n\n private static mapCidrFromEndpoint(result: ParseResultIp): string {\n if (result.ipVersion === 4) {\n return `${result.hostname}/32`\n }\n\n return `${result.hostname}/128`\n }\n\n protected abstract create(\n name: string,\n args: NormalizedNetworkPolicyArgs,\n opts?: ResourceOptions,\n ): Input<Resource>\n\n private static readonly supportedCNIs = [\"cilium\"]\n\n static create(\n name: string,\n args: FullNetworkPolicyArgs,\n opts: ResourceOptions,\n ): Output<NetworkPolicy> {\n return output(args).apply(async args => {\n if (!args.cni || !NetworkPolicy.supportedCNIs.includes(args.cni)) {\n return new NativeNetworkPolicy(name, args, opts)\n }\n\n const implName = `${capitalize(args.cni)}NetworkPolicy`\n const implModule = (await import(`@highstate/${args.cni}`)) as Record<string, unknown>\n\n type NetworkPolicyFactory = new (\n name: string,\n args: Unwrap<NetworkPolicyArgs>,\n opts?: ResourceOptions,\n ) => NetworkPolicy\n\n const implClass = implModule[implName] as NetworkPolicyFactory | undefined\n if (!implClass) {\n throw new Error(`No implementation found for ${args.cni}`)\n }\n\n return new implClass(name, args, opts)\n })\n }\n\n static allowInsideNamespace(\n namespace: Input<NamespaceLike>,\n k8sCluster: Input<k8s.Cluster>,\n opts: ResourceOptions,\n ): Output<NetworkPolicy> {\n return NetworkPolicy.create(\n \"allow-inside-namespace\",\n {\n namespace,\n cni: output(k8sCluster).info.cni,\n\n description: \"Allow all traffic inside the namespace.\",\n selector: {},\n\n ingressRule: { fromNamespace: namespace },\n egressRule: { toNamespace: namespace },\n },\n opts,\n )\n }\n\n static allowKubeApiServer(\n namespace: Input<NamespaceLike>,\n k8sCluster: Input<k8s.Cluster>,\n opts: ResourceOptions,\n ): Output<NetworkPolicy> {\n return NetworkPolicy.create(\n \"allow-kube-api-server\",\n {\n namespace,\n cni: output(k8sCluster).info.cni,\n\n description: \"Allow all traffic to the Kubernetes API server from the namespace.\",\n\n allowKubeApiServer: true,\n },\n opts,\n )\n }\n\n static allowKubeDns(\n namespace: Input<NamespaceLike>,\n k8sCluster: Input<k8s.Cluster>,\n opts: ResourceOptions,\n ): Output<NetworkPolicy> {\n return NetworkPolicy.create(\n \"allow-kube-dns\",\n {\n namespace,\n cni: output(k8sCluster).info.cni,\n\n description: \"Allow all traffic to the Kubernetes DNS server from the namespace.\",\n\n allowKubeDns: true,\n },\n opts,\n )\n }\n\n static allowAllEgress(\n namespace: Input<NamespaceLike>,\n k8sCluster: Input<k8s.Cluster>,\n opts: ResourceOptions,\n ): Output<NetworkPolicy> {\n return NetworkPolicy.create(\n \"allow-all-egress\",\n {\n namespace,\n cni: output(k8sCluster).info.cni,\n\n description: \"Allow all egress traffic from the namespace.\",\n\n egressRule: { toAll: true },\n },\n opts,\n )\n }\n}\n\nexport class NativeNetworkPolicy extends NetworkPolicy {\n protected create(\n name: string,\n args: NormalizedNetworkPolicyArgs,\n opts?: ResourceOptions,\n ): Resource {\n const ingress = NativeNetworkPolicy.createIngressRules(args)\n const egress = NativeNetworkPolicy.createEgressRules(args)\n\n const policyTypes: string[] = []\n\n if (ingress.length > 0 || args.isolateIngress) {\n policyTypes.push(\"Ingress\")\n }\n\n if (egress.length > 0 || args.isolateEgress) {\n policyTypes.push(\"Egress\")\n }\n\n return new networking.v1.NetworkPolicy(\n name,\n {\n metadata: mergeDeep(mapMetadata(args, name), {\n annotations: args.description\n ? { \"kubernetes.io/description\": args.description }\n : undefined,\n }),\n spec: {\n podSelector: args.podSelector,\n ingress,\n egress,\n policyTypes,\n },\n },\n opts,\n )\n }\n\n private static fallbackIpBlock: types.input.networking.v1.IPBlock = {\n cidr: \"0.0.0.0/0\",\n except: [\"10.0.0.0/8\", \"172.16.0.0/12\", \"192.168.0.0/16\"],\n }\n\n private static createIngressRules(\n args: NormalizedNetworkPolicyArgs,\n ): types.input.networking.v1.NetworkPolicyIngressRule[] {\n return args.ingressRules.map(rule => ({\n from: rule.all ? undefined : NativeNetworkPolicy.createRulePeers(rule),\n ports: NativeNetworkPolicy.mapPorts(rule.ports),\n }))\n }\n\n private static createEgressRules(\n args: NormalizedNetworkPolicyArgs,\n ): types.input.networking.v1.NetworkPolicyEgressRule[] {\n // the native resource does not support FQDNs\n // to provide compatibility, we need to fallback to all except private CIDRs\n const needFallback = args.egressRules.some(rule => rule.fqdns.length > 0)\n if (needFallback) {\n return [{ to: [{ ipBlock: NativeNetworkPolicy.fallbackIpBlock }] }]\n }\n\n const extraRules: types.input.networking.v1.NetworkPolicyEgressRule[] = []\n\n if (args.allowKubeApiServer) {\n // TODO: the \"10.96.0.1\" is not guaranteed to be the API server\n extraRules.push({ to: [{ ipBlock: { cidr: \"10.96.0.1\" } }] })\n }\n\n return args.egressRules\n .map(rule => {\n return {\n to: rule.all ? undefined : NativeNetworkPolicy.createRulePeers(rule),\n ports: NativeNetworkPolicy.mapPorts(rule.ports),\n } as types.input.networking.v1.NetworkPolicyEgressRule\n })\n .concat(extraRules)\n }\n\n private static createRulePeers(\n this: void,\n args: NormalizedRuleArgs,\n ): types.input.networking.v1.NetworkPolicyPeer[] {\n return [\n ...NativeNetworkPolicy.createCidrPeers(args),\n ...NativeNetworkPolicy.createServicePeers(args),\n ...NativeNetworkPolicy.createSelectorPeers(args),\n ]\n }\n\n private static createCidrPeers(\n args: NormalizedRuleArgs,\n ): types.input.networking.v1.NetworkPolicyPeer[] {\n return args.cidrs.map(cidr => ({ ipBlock: { cidr } }))\n }\n\n private static createServicePeers(\n args: NormalizedRuleArgs,\n ): types.input.networking.v1.NetworkPolicyPeer[] {\n return args.services.map(service => {\n const selector = mapServiceToLabelSelector(service)\n\n return {\n namespaceSelector: mapNamespaceNameToSelector(service.metadata.namespace),\n podSelector: selector,\n }\n })\n }\n\n private static createSelectorPeers(\n args: NormalizedRuleArgs,\n ): types.input.networking.v1.NetworkPolicyPeer[] {\n const selectorPeers = args.selectors.map(selector => ({\n podSelector: mapSelectorLikeToSelector(selector),\n }))\n\n const namespacePeers = args.namespaces.map(NativeNetworkPolicy.createNamespacePeer)\n\n if (namespacePeers.length === 0) {\n // if there are no namespaces, we can just return selector peers\n return selectorPeers\n }\n\n if (selectorPeers.length === 0) {\n // if there are no selectors, we can just return namespace peers\n return namespacePeers\n }\n\n // if there are both, we need to create a cartesian product\n return flat(\n selectorPeers.map(selectorPeer => {\n return namespacePeers.map(namespacePeer => merge(selectorPeer, namespacePeer))\n }),\n )\n }\n\n private static createNamespacePeer(\n this: void,\n namespace: NamespaceLike,\n ): types.input.networking.v1.NetworkPolicyPeer {\n const namespaceName = mapNamespaceLikeToNamespaceName(namespace)\n const namespaceSelector = mapNamespaceNameToSelector(namespaceName)\n\n return { namespaceSelector }\n }\n\n private static mapPorts(\n ports: NetworkPolicyPort[],\n ): types.input.networking.v1.NetworkPolicyPort[] {\n return ports.map(port => {\n if (\"port\" in port) {\n return {\n port: port.port,\n protocol: port.protocol ?? \"TCP\",\n }\n }\n\n return {\n port: port.range[0],\n endPort: port.range[1],\n protocol: port.protocol ?? \"TCP\",\n }\n })\n }\n}\n","import type { k8s } from \"@highstate/library\"\nimport type { core, Provider } from \"@pulumi/kubernetes\"\nimport { DnsRecord } from \"@highstate/common\"\nimport { gateway } from \"@highstate/gateway-api\"\nimport {\n normalize,\n Output,\n output,\n toPromise,\n type Input,\n type InputArray,\n} from \"@highstate/pulumi\"\nimport { NetworkPolicy } from \"./network-policy\"\nimport { getAppDisplayName, getAppName, mapNamespaceLikeToNamespaceName } from \"./shared\"\n\nexport type UseAccessPointResult = {\n /**\n * The gateway instance created according to the access point.\n */\n gateway: gateway.v1.Gateway\n\n /**\n * The DNS record associated created according to the access point and gateway.\n */\n dnsRecords: DnsRecord[]\n\n /**\n * The network policies associated with the access point.\n */\n networkPolicies: NetworkPolicy[]\n}\n\nexport type UseAccessPointArgs = Omit<CreateGatewayArgs, \"gateway\"> & {\n accessPoint: Input<k8s.AccessPoint>\n}\n\nexport function useAccessPoint(args: UseAccessPointArgs): Promise<UseAccessPointResult> {\n const result = output({ args, namespaceName: output(args.namespace).metadata.name }).apply(\n ({ args, namespaceName }) => {\n const gateway = createGateway({\n ...args,\n annotations: {\n \"cert-manager.io/cluster-issuer\": args.accessPoint.tlsIssuer.clusterIssuerName,\n },\n gateway: args.accessPoint.gateway,\n })\n\n const dnsRecords = normalize(args.fqdn, args.fqdns).map(fqdn => {\n return DnsRecord.create(fqdn, {\n provider: args.accessPoint.dnsProvider,\n type: \"A\",\n value: args.accessPoint.gateway.ip,\n })\n })\n\n const networkPolicies: Output<NetworkPolicy>[] = []\n\n if (args.accessPoint.gateway.service) {\n const displayName = getAppDisplayName(args.accessPoint.gateway.service.metadata)\n\n networkPolicies.push(\n NetworkPolicy.create(\n `allow-ingress-from-${getAppName(args.accessPoint.gateway.service.metadata)}`,\n {\n cni: args.accessPoint.gateway.service.clusterInfo.cni,\n namespace: args.namespace,\n\n description: `Allow ingress traffic from the gateway \"${displayName}\".`,\n\n ingressRule: {\n fromNamespace: args.accessPoint.gateway.service.metadata.namespace,\n fromSelector: args.accessPoint.gateway.service.spec.selector,\n },\n },\n { provider: args.provider },\n ),\n\n NetworkPolicy.create(\n `allow-egress-to-${namespaceName}`,\n {\n cni: args.accessPoint.gateway.service.clusterInfo.cni,\n namespace: args.accessPoint.gateway.service.metadata.namespace,\n selector: args.accessPoint.gateway.service.spec.selector,\n\n description: `Allow egress traffic to the namespace \"${namespaceName}\".`,\n\n egressRule: {\n toNamespace: args.namespace,\n },\n },\n { provider: args.provider },\n ),\n )\n }\n\n return output({\n gateway,\n dnsRecords,\n networkPolicies,\n })\n },\n )\n\n return toPromise(result)\n}\n\nexport type StandardAccessPointArgs = {\n fqdn: string\n}\n\nexport type StandardAccessPointInputs = {\n accessPoint: Output<k8s.AccessPoint>\n k8sCluster: Output<k8s.Cluster>\n}\n\nexport function useStandardAcessPoint(\n appName: string,\n namespace: core.v1.Namespace,\n args: StandardAccessPointArgs,\n inputs: StandardAccessPointInputs,\n provider: Provider,\n): Promise<UseAccessPointResult> {\n return useAccessPoint({\n name: appName,\n namespace,\n\n fqdn: args.fqdn,\n\n accessPoint: inputs.accessPoint,\n clusterInfo: inputs.k8sCluster.info,\n provider,\n })\n}\n\nexport type CreateGatewayArgs = {\n name: string\n namespace: Input<core.v1.Namespace>\n annotations?: Input<Record<string, string>>\n\n fqdn?: Input<string>\n fqdns?: InputArray<string>\n\n gateway: Input<k8s.Gateway>\n clusterInfo: Input<k8s.ClusterInfo>\n provider: Provider\n}\n\nexport function createGateway(args: CreateGatewayArgs): Output<gateway.v1.Gateway> {\n return output(args).apply(args => {\n if (args.clusterInfo.id !== args.gateway.clusterInfo.id) {\n throw new Error(\n \"The provided Kubernetes cluster is different from the one where the gateway controller is deployed.\",\n )\n }\n\n return new gateway.v1.Gateway(\n args.name,\n {\n metadata: {\n name: args.name,\n namespace: mapNamespaceLikeToNamespaceName(args.namespace),\n annotations: args.annotations,\n },\n spec: {\n gatewayClassName: output(args.gateway).gatewayClassName,\n listeners: normalize(args.fqdn, args.fqdns).map(fqdn => {\n const normalizedName = fqdn.replace(/\\*/g, \"wildcard\")\n\n return {\n name: `https-${normalizedName}`,\n port: output(args.gateway).httpsListenerPort,\n protocol: \"HTTPS\",\n hostname: fqdn,\n tls: {\n mode: \"Terminate\",\n certificateRefs: [{ name: normalizedName }],\n },\n }\n }),\n },\n },\n { provider: args.provider, deletedWith: args.namespace },\n )\n })\n}\n","import type { ContainerEnvironment, ContainerVolumeMount, WorkloadVolume } from \"../container\"\nimport { core } from \"@pulumi/kubernetes\"\nimport { apply, normalize, type InputArray } from \"@highstate/pulumi\"\nimport {\n ComponentResource,\n output,\n type ComponentResourceOptions,\n type Input,\n type Output,\n type Unwrap,\n} from \"@pulumi/pulumi\"\nimport { pipe } from \"remeda\"\nimport { deepmerge } from \"deepmerge-ts\"\nimport { text, trimIndentation } from \"@highstate/contract\"\nimport { mapMetadata, type CommonArgs } from \"../shared\"\nimport {\n emptyScriptEnvironment,\n type ResolvedScriptEnvironment,\n type ScriptDistribution,\n type ScriptEnvironment,\n} from \"./environment\"\n\nexport type ScriptBundleArgs = CommonArgs & {\n /**\n * The environment to bundle the scripts from.\n */\n environment?: Input<ScriptEnvironment>\n\n /**\n * The environments to bundle the scripts from.\n */\n environments?: InputArray<ScriptEnvironment>\n\n /**\n * The distribution to use for the scripts.\n */\n distribution: ScriptDistribution\n}\n\nexport class ScriptBundle extends ComponentResource {\n /**\n * The config map containing the scripts.\n */\n readonly configMap: Output<core.v1.ConfigMap>\n\n /**\n * The volumes that should be included in the workload.\n */\n readonly volumes: Output<WorkloadVolume[]>\n\n /**\n * The volume mounts that should be defined in the container.\n */\n readonly volumeMounts: Output<ContainerVolumeMount[]>\n\n /**\n * The environment variables that should be defined in the container.\n */\n readonly environment: Output<ContainerEnvironment>\n\n /**\n * The distribution to use for the scripts.\n */\n readonly distribution: ScriptDistribution\n\n constructor(name: string, args: ScriptBundleArgs, opts?: ComponentResourceOptions) {\n super(\"highstate:k8s:ScriptBundle\", name, args, opts)\n\n const scriptEnvironment = pipe(\n output(args),\n apply(args => normalize(args.environment, args.environments)),\n apply(args => deepmerge(emptyScriptEnvironment, ...args)),\n ) as Output<Unwrap<ResolvedScriptEnvironment>>\n\n this.distribution = args.distribution\n this.environment = scriptEnvironment.environment\n\n this.configMap = output({ scriptEnvironment, args }).apply(({ scriptEnvironment, args }) => {\n return new core.v1.ConfigMap(\n name,\n {\n metadata: mapMetadata(args, name),\n data: createScriptData(this.distribution, scriptEnvironment),\n },\n { ...opts, parent: this },\n )\n })\n\n this.volumes = scriptEnvironment.volumes.apply(volumes => {\n return [\n ...volumes,\n {\n name: this.configMap.metadata.name,\n\n configMap: {\n name: this.configMap.metadata.name,\n defaultMode: 0o550, // read and execute permissions\n },\n },\n ]\n })\n\n this.volumeMounts = scriptEnvironment.volumeMounts.apply(volumeMounts => {\n return [\n ...volumeMounts,\n {\n volume: this.configMap,\n mountPath: \"/scripts\",\n },\n ]\n })\n\n this.registerOutputs({\n configMap: this.configMap,\n volumes: this.volumes,\n volumeMounts: this.volumeMounts,\n environment: this.environment,\n })\n }\n}\n\nfunction createScriptData(\n distribution: ScriptDistribution,\n environment: Unwrap<ResolvedScriptEnvironment>,\n): Record<string, string> {\n const scriptData: Record<string, string> = {}\n const actions: string[] = []\n\n const distributionEnvironment = environment[distribution]\n\n if (distributionEnvironment.preInstallPackages.length > 0) {\n scriptData[\"pre-install-packages.sh\"] = getInstallPackagesScript(\n distribution,\n distributionEnvironment.preInstallPackages,\n )\n\n actions.push(`\n echo \"+ Installing pre-install packages...\"\n /scripts/pre-install-packages.sh\n echo \"+ Pre-install packages installed successfully\"\n `)\n }\n\n if (Object.keys(distributionEnvironment.preInstallScripts).length > 0) {\n for (const key in distributionEnvironment.preInstallScripts) {\n scriptData[`pre-install-${key}`] = distributionEnvironment.preInstallScripts[key]\n\n actions.push(`\n echo \"+ Running pre-install script '${key}'...\"\n /scripts/pre-install-${key}\n echo \"+ Pre-install script '${key}'... Done\"\n `)\n }\n }\n\n if (distributionEnvironment.packages.length > 0) {\n scriptData[\"install-packages.sh\"] = getInstallPackagesScript(\n distribution,\n distributionEnvironment.packages,\n )\n\n actions.push(`\n echo \"+ Installing packages...\"\n /scripts/install-packages.sh\n echo \"+ Packages installed successfully\"\n `)\n }\n\n if (Object.keys(environment.setupScripts).length > 0) {\n for (const key in environment.setupScripts) {\n scriptData[`setup-${key}`] = environment.setupScripts[key]\n\n actions.push(`\n echo \"+ Running setup script '${key}'...\"\n /scripts/setup-${key}\n echo \"+ Setup script '${key}'... Done\"\n `)\n }\n }\n\n if (Object.keys(environment.cleanupScripts).length > 0) {\n const cleanupActions: string[] = []\n\n for (const key in environment.cleanupScripts) {\n scriptData[`cleanup-${key}`] = environment.cleanupScripts[key]\n\n cleanupActions.push(`\n echo \"+ Running cleanup script '${key}'...\"\n /scripts/cleanup-${key}\n echo \"+ Cleanup script '${key}'... Done\"\n `)\n }\n\n actions.push(`\n function cleanup() {\n ${cleanupActions.map(s => s.trim()).join(\"\\n\\n\")}\n }\n\n trap cleanup EXIT\n trap cleanup SIGTERM\n `)\n }\n\n for (const key in environment.scripts) {\n scriptData[key] = environment.scripts[key]\n }\n\n scriptData[\"entrypoint.sh\"] = trimIndentation(`\n #!/bin/sh\n set -e\n\n if [ -z \"$1\" ]; then\n echo \"Usage: entrypoint.sh <main script> [args...]\"\n exit 1\n fi\n\n ${actions.map(s => s.trim()).join(\"\\n\\n\")}\n\n echo \"+ Running main script...\"\n $@\n echo \"+ Main script completed\"\n `)\n\n return scriptData\n}\n\nfunction getInstallPackagesScript(distribution: ScriptDistribution, packages: string[]): string {\n if (distribution === \"alpine\") {\n return text`\n #!/bin/sh\n set -e\n\n apk add --no-cache ${packages.join(\" \")}\n `\n } else {\n return text`\n #!/bin/sh\n set -e\n\n apt-get update\n apt-get install -y ${packages.join(\" \")}\n `\n }\n}\n","import type { Input, InputArray, InputMap } from \"@highstate/pulumi\"\nimport type { ContainerEnvironment, ContainerVolumeMount, WorkloadVolume } from \"../container\"\n\nexport type ScriptDistribution = \"alpine\" | \"ubuntu\"\n\nexport type DistributionEnvironment = {\n /**\n * The utility packages that should be installed before running \"preInstallScripts\".\n *\n * Useful for installing tools like `curl` to install additional repositories.\n */\n preInstallPackages?: InputArray<string>\n\n /**\n * The pre-install scripts that should be run before installing packages.\n * Typically, these scripts are used to install additional repositories.\n */\n preInstallScripts?: InputMap<string>\n\n /**\n * The packages that are available in the environment.\n */\n packages?: InputArray<string>\n}\n\nexport type ScriptEnvironment = {\n [distribution in ScriptDistribution]?: DistributionEnvironment\n} & {\n /**\n * The setup scripts that should be run before the script.\n */\n setupScripts?: InputMap<string>\n\n /**\n * The cleanup scripts that should be run after the script.\n */\n cleanupScripts?: InputMap<string>\n\n /**\n * The arbitrary scripts available in the environment.\n */\n scripts?: InputMap<string>\n\n /**\n * The volumes that should be defined in the environment.\n */\n volumes?: InputArray<WorkloadVolume>\n\n /**\n * The volume mounts that should be defined in the environment.\n */\n volumeMounts?: InputArray<ContainerVolumeMount>\n\n /**\n * The environment variables that should be defined in the environment.\n */\n environment?: Input<ContainerEnvironment>\n}\n\nexport type ResolvedScriptEnvironment = Omit<Required<ScriptEnvironment>, ScriptDistribution> & {\n [distribution in ScriptDistribution]: Required<DistributionEnvironment>\n}\n\nconst emptyDistributionEnvironment: Required<DistributionEnvironment> = {\n preInstallPackages: [],\n preInstallScripts: {},\n packages: [],\n}\n\nexport const emptyScriptEnvironment: ResolvedScriptEnvironment = {\n alpine: emptyDistributionEnvironment,\n ubuntu: emptyDistributionEnvironment,\n setupScripts: {},\n cleanupScripts: {},\n scripts: {},\n volumes: [],\n volumeMounts: [],\n environment: {},\n}\n","import type { Container } from \"../container\"\nimport type { ScriptBundle } from \"./bundle\"\nimport { Output, output, type Input } from \"@pulumi/pulumi\"\nimport { merge } from \"remeda\"\n\nexport interface ScriptContainer extends Container {\n /**\n * The script bundle to use.\n */\n bundle: Input<ScriptBundle>\n\n /**\n * The name of the main script to run.\n * The script must be available in the bundle.\n */\n main: Input<string>\n}\n\n/**\n * Creates a spec for a container that runs a script.\n * This spec can be used to create a complete workload or an init container.\n *\n * @param options The options to create the container spec.\n * @returns The container spec.\n */\nexport function createScriptContainer(options: ScriptContainer): Output<Container> {\n return output(options).apply(options => {\n const image =\n options.bundle.distribution === \"alpine\"\n ? \"alpine@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c\"\n : \"ubuntu@sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782\"\n\n return {\n image,\n command: [\"/scripts/entrypoint.sh\", `/scripts/${options.main}`],\n\n ...options,\n\n volumeMounts: merge(options.bundle.volumeMounts, options.volumeMounts),\n volumes: merge(options.bundle.volumes, options.volumes),\n environment: merge(options.bundle.environment, options.environment),\n }\n })\n}\n","import { batch, type types } from \"@pulumi/kubernetes\"\nimport {\n ComponentResource,\n normalize,\n Output,\n output,\n type ComponentResourceOptions,\n type Input,\n type InputArray,\n} from \"@highstate/pulumi\"\nimport { mergeDeep, omit } from \"remeda\"\nimport { mapContainerToRaw, mapWorkloadVolume, type Container } from \"./container\"\nimport { commonExtraArgs, mapMetadata, type CommonArgs } from \"./shared\"\n\nexport type JobArgs = CommonArgs & {\n container?: Input<Container>\n containers?: InputArray<Container>\n} & Omit<Partial<types.input.batch.v1.JobSpec>, \"template\"> & {\n template?: {\n metadata?: types.input.meta.v1.ObjectMeta\n spec?: Partial<types.input.core.v1.PodSpec>\n }\n }\n\nconst jobExtraArgs = [...commonExtraArgs, \"container\", \"containers\"] as const\n\nexport class Job extends ComponentResource {\n /**\n * The underlying Kubernetes job.\n */\n public readonly job: Output<batch.v1.Job>\n\n constructor(name: string, args: JobArgs, opts?: ComponentResourceOptions) {\n super(\"highstate:k8s:Job\", name, args, opts)\n\n this.job = output(args).apply(args => {\n const containers = normalize(args.container, args.containers)\n\n return new batch.v1.Job(\n name,\n {\n metadata: mapMetadata(args, name),\n spec: mergeDeep(\n {\n template: {\n spec: {\n containers: containers.map(container => mapContainerToRaw(container, name)),\n\n volumes: containers\n .flatMap(container => normalize(container.volume, container.volumes))\n .map(mapWorkloadVolume),\n\n restartPolicy: \"Never\",\n },\n },\n } satisfies types.input.batch.v1.JobSpec,\n omit(args, jobExtraArgs) as types.input.batch.v1.JobSpec,\n ),\n },\n { parent: this, ...opts },\n )\n })\n\n this.registerOutputs({ job: this.job })\n }\n}\n","import type { RequiredKeys } from \"@highstate/contract\"\nimport { batch, type types } from \"@pulumi/kubernetes\"\nimport {\n ComponentResource,\n normalize,\n Output,\n output,\n type ComponentResourceOptions,\n type Input,\n type InputArray,\n} from \"@highstate/pulumi\"\nimport { mergeDeep, omit } from \"remeda\"\nimport { mapContainerToRaw, mapWorkloadVolume, type Container } from \"./container\"\nimport { commonExtraArgs, mapMetadata, type CommonArgs } from \"./shared\"\n\nexport type CronJobArgs = CommonArgs & {\n container?: Input<Container>\n containers?: InputArray<Container>\n} & Omit<RequiredKeys<Partial<types.input.batch.v1.CronJobSpec>, \"schedule\">, \"jobTemplate\"> & {\n jobTemplate?: {\n metadata?: types.input.meta.v1.ObjectMeta\n spec?: Omit<types.input.batch.v1.JobSpec, \"template\"> & {\n template?: {\n metadata?: types.input.meta.v1.ObjectMeta\n spec?: Partial<types.input.core.v1.PodSpec>\n }\n }\n }\n }\n\nconst cronJobExtraArgs = [...commonExtraArgs, \"container\", \"containers\"] as const\n\nexport class CronJob extends ComponentResource {\n /**\n * The underlying Kubernetes job.\n */\n public readonly cronJob: Output<batch.v1.CronJob>\n\n constructor(name: string, args: CronJobArgs, opts?: ComponentResourceOptions) {\n super(\"highstate:k8s:CronJob\", name, args, opts)\n\n this.cronJob = output(args).apply(args => {\n const containers = normalize(args.container, args.containers)\n\n return new batch.v1.CronJob(\n name,\n {\n metadata: mapMetadata(args, name),\n\n spec: mergeDeep(\n {\n jobTemplate: {\n spec: {\n template: {\n spec: {\n containers: containers.map(container => mapContainerToRaw(container, name)),\n\n volumes: containers\n .flatMap(container => normalize(container.volume, container.volumes))\n .map(mapWorkloadVolume),\n },\n },\n },\n },\n\n schedule: args.schedule,\n } satisfies types.input.batch.v1.CronJobSpec,\n omit(args, cronJobExtraArgs) as types.input.batch.v1.CronJobSpec,\n ),\n },\n { parent: this, ...opts },\n )\n })\n\n this.registerOutputs({ cronJob: this.cronJob })\n }\n}\n"],"mappings":"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","names":["output","ComponentResource","omit","deepmerge","core","output","omit","args","id","omit","output","core","normalize","ComponentResource","output","output","args","normalize","containers","service","ComponentResource","output","args","containers","volumes","deepmerge","omit","output","ComponentResource","apps","omit","deepmerge","ComponentResource","output","args","containers","volumes","service","apps","deepmerge","omit","ComponentResource","normalize","output","ComponentResource","output","args","normalize","normalize","output","output","args","gateway","normalize","core","normalize","ComponentResource","output","deepmerge","trimIndentation","ComponentResource","output","args","normalize","deepmerge","scriptEnvironment","core","trimIndentation","output","merge","options","ComponentResource","normalize","output","mergeDeep","omit","ComponentResource","output","args","normalize","mergeDeep","omit","batch","ComponentResource","normalize","output","mergeDeep","omit","ComponentResource","output","args","normalize","batch","mergeDeep","omit"]}
1
+ {"version":3,"sources":["../src/deployment.ts","../src/container.ts","../src/pvc.ts","../src/workload.ts","../src/stateful-set.ts","../src/network-policy.ts","../src/access-point.ts","../src/scripting/bundle.ts","../src/scripting/environment.ts","../src/scripting/container.ts","../src/job.ts","../src/cron-job.ts"],"sourcesContent":["import type { k8s } from \"@highstate/library\"\nimport type { HttpRoute } from \"./gateway\"\nimport type { Service } from \"./service\"\nimport {\n output,\n type ComponentResourceOptions,\n Output,\n type Inputs,\n ComponentResource,\n type InputArray,\n Resource,\n type Input,\n type InstanceTerminal,\n interpolate,\n} from \"@highstate/pulumi\"\nimport { apps, types } from \"@pulumi/kubernetes\"\nimport { omit } from \"remeda\"\nimport { deepmerge } from \"deepmerge-ts\"\nimport { trimIndentation } from \"@highstate/contract\"\nimport { mapMetadata, verifyProvider } from \"./shared\"\nimport { mapContainerToRaw } from \"./container\"\nimport {\n getPublicWorkloadComponents,\n publicWorkloadExtraArgs,\n type PublicWorkloadArgs,\n} from \"./workload\"\n\nexport type DeploymentArgs = Omit<PublicWorkloadArgs, \"patch\"> & {\n patch?: Input<k8s.Deployment>\n\n /**\n * The shell to use in the terminal.\n *\n * By default, `bash` is used.\n */\n terminalShell?: string\n} & Omit<Partial<types.input.apps.v1.DeploymentSpec>, \"template\"> & {\n template?: {\n metadata?: types.input.meta.v1.ObjectMeta\n spec?: Partial<types.input.core.v1.PodSpec>\n }\n }\n\nexport abstract class Deployment extends ComponentResource {\n protected constructor(\n type: string,\n name: string,\n private readonly args: Inputs,\n opts: ComponentResourceOptions,\n\n /**\n * The cluster where the deployment is created.\n */\n readonly cluster: Output<k8s.Cluster>,\n\n /**\n * The metadata of the underlying Kubernetes deployment.\n */\n readonly metadata: Output<types.output.meta.v1.ObjectMeta>,\n\n /**\n * The spec of the underlying Kubernetes deployment.\n */\n readonly spec: Output<types.output.apps.v1.DeploymentSpec>,\n\n /**\n * The status of the underlying Kubernetes deployment.\n */\n readonly status: Output<types.output.apps.v1.DeploymentStatus>,\n\n private readonly _service: Output<Service | undefined>,\n private readonly _httpRoute: Output<HttpRoute | undefined>,\n\n /**\n * The resources associated with the deployment.\n */\n readonly resources: InputArray<Resource>,\n ) {\n super(type, name, args, opts)\n }\n\n /**\n * The Highstate deployment entity.\n */\n get entity(): Output<k8s.Deployment> {\n return output({\n type: \"k8s.deployment\",\n clusterInfo: this.cluster.info,\n metadata: this.metadata,\n spec: this.spec,\n service: this._service.apply(service => service?.entity),\n })\n }\n\n get optionalService(): Output<Service | undefined> {\n return this._service\n }\n\n /**\n * The service associated with the deployment.\n */\n get service(): Output<Service> {\n return this._service.apply(service => {\n if (!service) {\n throw new Error(\"The service is not available.\")\n }\n\n return service\n })\n }\n\n /**\n * The HTTP route associated with the deployment.\n */\n get httpRoute(): Output<HttpRoute> {\n return this._httpRoute.apply(httpRoute => {\n if (!httpRoute) {\n throw new Error(\"The HTTP route is not available.\")\n }\n\n return httpRoute\n })\n }\n\n /**\n * The instance terminal to interact with the deployment.\n */\n get terminal(): Output<InstanceTerminal> {\n return output({\n name: this.metadata.name,\n title: this.metadata.name,\n image: \"ghcr.io/exeteres/highstate/terminal-kubectl\",\n command: [\"script\", \"-q\", \"-c\", \"/enter-container.sh\", \"/dev/null\"],\n files: {\n \"/kubeconfig\": this.cluster.kubeconfig,\n\n \"/enter-container.sh\": {\n mode: 0o755,\n content: interpolate`\n #!/bin/bash\n\n exec kubectl exec -it -n ${this.metadata.namespace} deployment/${this.metadata.name} -- ${this.args.terminalShell ?? \"bash\"}\n `.apply(trimIndentation),\n },\n },\n env: {\n KUBECONFIG: \"/kubeconfig\",\n },\n })\n }\n\n static create(name: string, args: DeploymentArgs, opts: ComponentResourceOptions): Deployment {\n return new CreatedDeployment(name, args, opts)\n }\n}\n\nclass CreatedDeployment extends Deployment {\n constructor(name: string, args: DeploymentArgs, opts: ComponentResourceOptions) {\n const { labels, containers, volumes, service, httpRoute } = getPublicWorkloadComponents(\n name,\n args,\n () => this,\n opts,\n )\n\n const deployment = output({ args, containers, volumes }).apply(\n async ({ args, containers, volumes }) => {\n await verifyProvider(opts.provider, args.cluster.info)\n\n return new (args.patch ? apps.v1.DeploymentPatch : apps.v1.Deployment)(\n name,\n {\n metadata: mapMetadata(args.patch?.metadata ?? args, name),\n spec: deepmerge(\n {\n template: {\n metadata: !args.patch ? { labels } : undefined,\n spec: {\n containers: containers.map(container => mapContainerToRaw(container, name)),\n volumes,\n },\n },\n selector: !args.patch ? { matchLabels: labels } : undefined,\n },\n omit(args, publicWorkloadExtraArgs),\n ),\n },\n { parent: this, ...opts },\n )\n },\n )\n\n super(\n \"highstate:k8s:Deployment\",\n name,\n args,\n opts,\n\n output(args.cluster),\n deployment.metadata,\n deployment.spec,\n deployment.status,\n\n service,\n httpRoute,\n\n [deployment],\n )\n }\n}\n","import type { PartialKeys } from \"@highstate/contract\"\nimport { core, type types } from \"@pulumi/kubernetes\"\nimport { normalize, output, type Input, type InputArray, type Unwrap } from \"@highstate/pulumi\"\nimport { concat, map, omit } from \"remeda\"\nimport { PersistentVolumeClaim } from \"./pvc\"\n\nexport type Container = Omit<PartialKeys<types.input.core.v1.Container, \"name\">, \"volumeMounts\"> & {\n /**\n * The single port to add to the container.\n */\n port?: Input<types.input.core.v1.ContainerPort>\n\n /**\n * The volume mount to attach to the container.\n */\n volumeMount?: Input<ContainerVolumeMount>\n\n /**\n * The volume mounts to attach to the container.\n */\n volumeMounts?: InputArray<ContainerVolumeMount>\n\n /**\n * The volume to include in the parent workload.\n * It is like the `volumes` property, but defined at the container level.\n * It will be defined as a volume mount in the parent workload automatically.\n */\n volume?: Input<WorkloadVolume>\n\n /**\n * The volumes to include in the parent workload.\n * It is like the `volumes` property, but defined at the container level.\n * It will be defined as a volume mount in the parent workload automatically.\n */\n volumes?: InputArray<WorkloadVolume>\n\n /**\n * The map of environment variables to set in the container.\n * It is like the `env` property, but more convenient to use.\n */\n environment?: Input<ContainerEnvironment>\n\n /**\n * The source of environment variables to set in the container.\n * It is like the `envFrom` property, but more convenient to use.\n */\n environmentSource?: Input<ContainerEnvironmentSource>\n\n /**\n * The sources of environment variables to set in the container.\n * It is like the `envFrom` property, but more convenient to use.\n */\n environmentSources?: InputArray<ContainerEnvironmentSource>\n}\n\nconst containerExtraArgs = [\n \"port\",\n \"volumeMount\",\n \"volume\",\n \"environment\",\n \"environmentSource\",\n \"environmentSources\",\n] as const\n\nexport type ContainerEnvironment = Record<\n string,\n Input<string | undefined | null | ContainerEnvironmentVariable>\n>\n\nexport type ContainerEnvironmentVariable =\n | types.input.core.v1.EnvVarSource\n | {\n /**\n * The secret to select from.\n */\n secret: Input<core.v1.Secret>\n\n /**\n * The key of the secret to select from.\n */\n key: string\n }\n | {\n /**\n * The config map to select from.\n */\n configMap: Input<core.v1.ConfigMap>\n\n /**\n * The key of the config map to select from.\n */\n key: string\n }\n\nexport type ContainerEnvironmentSource =\n | types.input.core.v1.EnvFromSource\n | core.v1.ConfigMap\n | core.v1.Secret\n\nexport type ContainerVolumeMount =\n | types.input.core.v1.VolumeMount\n | (Omit<types.input.core.v1.VolumeMount, \"name\"> & {\n /**\n * The volume to mount.\n */\n volume: Input<WorkloadVolume>\n })\n\nexport type WorkloadVolume =\n | types.input.core.v1.Volume\n | core.v1.PersistentVolumeClaim\n | PersistentVolumeClaim\n | core.v1.ConfigMap\n | core.v1.Secret\n\nexport function mapContainerToRaw(\n container: Unwrap<Container>,\n fallbackName: string,\n): types.input.core.v1.Container {\n const containerName = container.name ?? fallbackName\n\n return {\n ...omit(container, containerExtraArgs),\n\n name: containerName,\n ports: normalize(container.port, container.ports),\n\n volumeMounts: map(normalize(container.volumeMount, container.volumeMounts), mapVolumeMount),\n\n env: concat(\n container.environment ? mapContainerEnvironment(container.environment) : [],\n container.env ?? [],\n ),\n\n envFrom: concat(\n map(\n normalize(container.environmentSource, container.environmentSources),\n mapEnvironmentSource,\n ),\n container.envFrom ?? [],\n ),\n }\n}\n\nexport function mapContainerEnvironment(\n environment: Unwrap<ContainerEnvironment>,\n): types.input.core.v1.EnvVar[] {\n const envVars: types.input.core.v1.EnvVar[] = []\n\n for (const [name, value] of Object.entries(environment)) {\n if (!value) {\n continue\n }\n\n if (typeof value === \"string\") {\n envVars.push({ name, value })\n continue\n }\n\n if (\"secret\" in value) {\n envVars.push({\n name,\n valueFrom: {\n secretKeyRef: {\n name: value.secret.metadata.name,\n key: value.key,\n },\n },\n })\n continue\n }\n\n if (\"configMap\" in value) {\n envVars.push({\n name,\n valueFrom: {\n configMapKeyRef: {\n name: value.configMap.metadata.name,\n key: value.key,\n },\n },\n })\n continue\n }\n\n envVars.push({ name, valueFrom: value })\n }\n\n return envVars\n}\n\nexport function mapVolumeMount(volumeMount: ContainerVolumeMount): types.input.core.v1.VolumeMount {\n if (\"volume\" in volumeMount) {\n return omit(\n {\n ...volumeMount,\n name: output(volumeMount.volume)\n .apply(mapWorkloadVolume)\n .apply(volume => output(volume.name)),\n },\n [\"volume\"],\n )\n }\n\n return {\n ...volumeMount,\n name: volumeMount.name,\n }\n}\n\nexport function mapEnvironmentSource(\n envFrom: ContainerEnvironmentSource,\n): types.input.core.v1.EnvFromSource {\n if (envFrom instanceof core.v1.ConfigMap) {\n return {\n configMapRef: {\n name: envFrom.metadata.name,\n },\n }\n }\n\n if (envFrom instanceof core.v1.Secret) {\n return {\n secretRef: {\n name: envFrom.metadata.name,\n },\n }\n }\n\n return envFrom\n}\n\nexport function mapWorkloadVolume(volume: WorkloadVolume) {\n if (volume instanceof PersistentVolumeClaim) {\n return {\n name: volume.metadata.name,\n persistentVolumeClaim: {\n claimName: volume.metadata.name,\n },\n }\n }\n\n if (volume instanceof core.v1.PersistentVolumeClaim) {\n return {\n name: volume.metadata.name,\n persistentVolumeClaim: {\n claimName: volume.metadata.name,\n },\n }\n }\n\n if (volume instanceof core.v1.ConfigMap) {\n return {\n name: volume.metadata.name,\n configMap: {\n name: volume.metadata.name,\n },\n }\n }\n\n if (volume instanceof core.v1.Secret) {\n return {\n name: volume.metadata.name,\n secret: {\n secretName: volume.metadata.name,\n },\n }\n }\n\n return volume\n}\n","import type { k8s } from \"@highstate/library\"\nimport { core, type types } from \"@pulumi/kubernetes\"\nimport {\n ComponentResource,\n Output,\n output,\n type ComponentResourceOptions,\n type CustomResourceOptions,\n type Input,\n type Inputs,\n} from \"@highstate/pulumi\"\nimport { deepmerge } from \"deepmerge-ts\"\nimport { omit } from \"remeda\"\nimport {\n commonExtraArgs,\n mapMetadata,\n resourceIdToString,\n verifyProvider,\n type CommonArgs,\n type ResourceId,\n} from \"./shared\"\n\nexport type PersistentVolumeClaimArgs = CommonArgs &\n types.input.core.v1.PersistentVolumeClaimSpec & {\n /**\n * The size of the volume to request.\n *\n * By default, the size is set to \"100Mi\".\n */\n size?: string\n\n /**\n * The cluster to create the resource in.\n */\n cluster: Input<k8s.Cluster>\n }\n\nconst extraPersistentVolumeClaimArgs = [...commonExtraArgs, \"size\", \"cluster\"] as const\n\nexport abstract class PersistentVolumeClaim extends ComponentResource {\n protected constructor(\n type: string,\n name: string,\n args: Inputs,\n opts: ComponentResourceOptions,\n\n /**\n * The cluster info associated with the pvc.\n */\n readonly clusterInfo: Output<k8s.ClusterInfo>,\n\n /**\n * The metadata of the underlying Kubernetes pvc.\n */\n readonly metadata: Output<types.output.meta.v1.ObjectMeta>,\n\n /**\n * The spec of the underlying Kubernetes pvc.\n */\n readonly spec: Output<types.output.core.v1.PersistentVolumeClaimSpec>,\n\n /**\n * The status of the underlying Kubernetes pvc.\n */\n readonly status: Output<types.output.core.v1.PersistentVolumeClaimStatus>,\n ) {\n super(type, name, args, opts)\n }\n\n /**\n * The Highstate service entity.\n */\n get entity(): Output<k8s.PersistentVolumeClaim> {\n return output({\n type: \"k8s.persistent-volume-claim\",\n clusterInfo: this.clusterInfo,\n metadata: this.metadata,\n })\n }\n\n static create(\n name: string,\n args: PersistentVolumeClaimArgs,\n opts: ComponentResourceOptions,\n ): PersistentVolumeClaim {\n return new CreatedPersistentVolumeClaim(name, args, opts)\n }\n\n static of(\n name: string,\n entity: Input<k8s.PersistentVolumeClaim>,\n opts: ComponentResourceOptions,\n ): PersistentVolumeClaim {\n return new ExternalPersistentVolumeClaim(\n name,\n output(entity).metadata,\n output(entity).clusterInfo,\n opts,\n )\n }\n}\n\nexport class CreatedPersistentVolumeClaim extends PersistentVolumeClaim {\n constructor(name: string, args: PersistentVolumeClaimArgs, opts: CustomResourceOptions) {\n const pvc = output(args).apply(args => {\n return new core.v1.PersistentVolumeClaim(\n name,\n {\n metadata: mapMetadata(args, name),\n spec: deepmerge(\n {\n accessModes: [\"ReadWriteOnce\"],\n resources: {\n requests: {\n storage: args.size ?? \"100Mi\",\n },\n },\n } satisfies types.input.core.v1.PersistentVolumeClaimSpec,\n omit(args, extraPersistentVolumeClaimArgs),\n ),\n },\n opts,\n )\n })\n\n super(\n \"k8s:PersistentVolumeClaim\",\n name,\n args,\n opts,\n\n output(args.cluster).info,\n pvc.metadata,\n pvc.spec,\n pvc.status,\n )\n }\n}\n\nexport class ExternalPersistentVolumeClaim extends PersistentVolumeClaim {\n constructor(\n name: string,\n id: Input<ResourceId>,\n clusterInfo: Input<k8s.ClusterInfo>,\n opts: ComponentResourceOptions,\n ) {\n const pvc = output(id).apply(async id => {\n await verifyProvider(opts.provider, this.clusterInfo)\n\n return core.v1.PersistentVolumeClaim.get(\n //\n name,\n resourceIdToString(id),\n { parent: this, provider: opts.provider },\n )\n })\n\n super(\n \"highstate:k8s:ExternalPersistentVolumeClaim\",\n name,\n { id, clusterInfo },\n opts,\n\n output(clusterInfo),\n pvc.metadata,\n pvc.spec,\n pvc.status,\n )\n }\n}\n\nexport function getAutoVolumeName(workloadName: string, index: number): string {\n if (index === 0) {\n return `${workloadName}-data`\n }\n\n return `${workloadName}-data-${index}`\n}\n","import type { types } from \"@pulumi/kubernetes\"\nimport type { k8s } from \"@highstate/library\"\nimport { normalize, type ComponentResourceOptions, type InputArray } from \"@highstate/pulumi\"\nimport { ComponentResource, output, type Input, type Output } from \"@pulumi/pulumi\"\nimport { uniqueBy } from \"remeda\"\nimport { commonExtraArgs, type CommonArgs } from \"./shared\"\nimport { mapContainerPortToServicePort, Service, type ServiceArgs } from \"./service\"\nimport { HttpRoute, type HttpRouteArgs } from \"./gateway\"\nimport {\n mapContainerToRaw,\n mapWorkloadVolume,\n type Container,\n type WorkloadVolume,\n} from \"./container\"\n\nexport type WorkloadArgs = CommonArgs & {\n container?: Input<Container>\n containers?: InputArray<Container>\n\n /**\n * The cluster to create the resource in.\n */\n cluster: Input<k8s.Cluster>\n}\n\nexport const workloadExtraArgs = [...commonExtraArgs, \"container\", \"containers\"] as const\n\nexport class WorkloadBase<TArgs extends WorkloadArgs> extends ComponentResource {\n protected readonly containers: Output<types.input.core.v1.Container[]>\n protected readonly volumes: Output<types.input.core.v1.Volume[]>\n\n constructor(type: string, name: string, args: TArgs, opts: ComponentResourceOptions | undefined) {\n super(type, name, args, opts)\n\n const containers = output(args).apply(args => normalize(args.container, args.containers))\n\n this.containers = containers.apply(containers =>\n containers.map(container => mapContainerToRaw(container, name)),\n )\n\n this.volumes = containers.apply(containers =>\n containers\n .flatMap(container => normalize(container.volume, container.volumes))\n .map(mapWorkloadVolume),\n )\n }\n}\n\nexport type PublicWorkloadArgs = WorkloadArgs & {\n service?: Input<Omit<ServiceArgs, \"cluster\" | \"namespace\">>\n httpRoute?: Input<Omit<HttpRouteArgs, \"cluster\" | \"namespace\">>\n patch?: Input<k8s.Deployment | k8s.StatefulSet>\n} & Partial<types.input.apps.v1.StatefulSetSpec>\n\nexport const publicWorkloadExtraArgs = [...workloadExtraArgs, \"service\", \"httpRoute\"] as const\n\nexport function getWorkloadComponents(name: string, args: WorkloadArgs) {\n const labels = {\n \"app.kubernetes.io/name\": name,\n }\n\n const containers = output(args).apply(args => normalize(args.container, args.containers))\n const volumes = containers.apply(containers => {\n const containerVolumes = containers\n .flatMap(container => normalize(container.volume, container.volumes))\n .map(mapWorkloadVolume)\n\n const containerVolumeMounts = containers\n .flatMap(container => {\n return normalize(container.volumeMount, container.volumeMounts)\n .map(volumeMount => {\n return \"volume\" in volumeMount ? volumeMount.volume : undefined\n })\n .filter(Boolean) as WorkloadVolume[]\n })\n .map(mapWorkloadVolume)\n\n return uniqueBy([...containerVolumes, ...containerVolumeMounts], volume => volume.name)\n })\n\n return { labels, containers, volumes }\n}\n\nexport function getPublicWorkloadComponents(\n name: string,\n args: PublicWorkloadArgs,\n parent: () => ComponentResource,\n opts: ComponentResourceOptions,\n) {\n const { labels, containers, volumes } = getWorkloadComponents(name, args)\n\n const service = output({ args, containers }).apply(({ args, containers }) => {\n if (!args.service && !args.httpRoute) {\n return undefined\n }\n\n if (args.patch?.service) {\n return Service.of(name, args.patch.service, { parent: parent(), ...opts })\n }\n\n if (args.patch) {\n return undefined\n }\n\n const ports = containers.flatMap(container => normalize(container.port, container.ports))\n\n return Service.create(\n name,\n {\n ...args.service,\n selector: labels,\n cluster: args.cluster,\n namespace: args.namespace,\n\n ports:\n // allow to completely override the ports\n !args.service?.port && !args.service?.ports\n ? ports.map(mapContainerPortToServicePort)\n : args.service?.ports,\n },\n { parent: parent(), ...opts },\n )\n })\n\n const httpRoute = output({\n args,\n service,\n }).apply(({ args, service }) => {\n if (!args.httpRoute || !service) {\n return undefined\n }\n\n if (args.patch) {\n return undefined\n }\n\n return new HttpRoute(\n name,\n {\n ...args.httpRoute,\n rule: {\n backend: service,\n },\n },\n { parent: parent(), ...opts },\n )\n })\n\n return { labels, containers, volumes, service, httpRoute }\n}\n","import type { k8s } from \"@highstate/library\"\nimport type { HttpRoute } from \"./gateway\"\nimport type { Service } from \"./service\"\nimport {\n output,\n type ComponentResourceOptions,\n ComponentResource,\n Output,\n type Inputs,\n type Input,\n} from \"@highstate/pulumi\"\nimport { apps, type types } from \"@pulumi/kubernetes\"\nimport { omit } from \"remeda\"\nimport { deepmerge } from \"deepmerge-ts\"\nimport {\n getPublicWorkloadComponents,\n publicWorkloadExtraArgs,\n type PublicWorkloadArgs,\n} from \"./workload\"\nimport { mapMetadata, verifyProvider } from \"./shared\"\nimport { mapContainerToRaw } from \"./container\"\n\nexport type StatefulSetArgs = Omit<PublicWorkloadArgs, \"patch\"> & {\n patch?: Input<k8s.StatefulSet>\n} & Partial<types.input.apps.v1.StatefulSetSpec>\n\nexport abstract class StatefulSet extends ComponentResource {\n protected constructor(\n type: string,\n name: string,\n args: Inputs,\n opts: ComponentResourceOptions,\n\n /**\n * The cluster info associated with the stateful set.\n */\n readonly clusterInfo: Output<k8s.ClusterInfo>,\n\n /**\n * The metadata of the underlying Kubernetes stateful set.\n */\n readonly metadata: Output<types.output.meta.v1.ObjectMeta>,\n\n /**\n * The spec of the underlying Kubernetes stateful set.\n */\n readonly spec: Output<types.output.apps.v1.StatefulSetSpec>,\n\n /**\n * The status of the underlying Kubernetes stateful set.\n */\n readonly status: Output<types.output.apps.v1.StatefulSetStatus>,\n\n private readonly _service: Output<Service | undefined>,\n private readonly _httpRoute: Output<HttpRoute | undefined>,\n ) {\n super(type, name, args, opts)\n }\n\n /**\n * The Highstate stateful set entity.\n */\n get entity(): Output<k8s.StatefulSet> {\n return output({\n type: \"k8s.stateful-set\",\n clusterInfo: this.clusterInfo,\n metadata: this.metadata,\n service: this.service.entity,\n })\n }\n\n get optionalService(): Output<Service | undefined> {\n return this._service\n }\n\n /**\n * The service associated with the stateful set.\n */\n get service(): Output<Service> {\n return this._service.apply(service => {\n if (!service) {\n throw new Error(\"The service is not available.\")\n }\n\n return service\n })\n }\n\n /**\n * The HTTP route associated with the stateful set.\n */\n get httpRoute(): Output<HttpRoute> {\n return this._httpRoute.apply(httpRoute => {\n if (!httpRoute) {\n throw new Error(\"The HTTP route is not available.\")\n }\n\n return httpRoute\n })\n }\n\n static create(name: string, args: StatefulSetArgs, opts: ComponentResourceOptions): StatefulSet {\n return new CreatedStatefulSet(name, args, opts)\n }\n}\n\nclass CreatedStatefulSet extends StatefulSet {\n constructor(name: string, args: StatefulSetArgs, opts: ComponentResourceOptions) {\n const { containers, volumes, labels, service, httpRoute } = getPublicWorkloadComponents(\n name,\n args,\n () => this,\n opts,\n )\n\n const statefulSet = output({ args, containers, volumes, service }).apply(\n async ({ args, containers, volumes, service }) => {\n await verifyProvider(opts.provider, args.cluster?.info)\n\n return new (args.patch ? apps.v1.StatefulSetPatch : apps.v1.StatefulSet)(\n name,\n {\n metadata: mapMetadata(args.patch?.metadata ?? args, name),\n spec: deepmerge(\n {\n serviceName: service?.metadata.name || name,\n template: {\n metadata: !args.patch ? { labels } : undefined,\n spec: {\n containers: containers.map(container => mapContainerToRaw(container, name)),\n volumes,\n },\n },\n selector: !args.patch ? { matchLabels: labels } : undefined,\n },\n omit(args, publicWorkloadExtraArgs),\n ),\n },\n { parent: this, ...opts },\n )\n },\n )\n\n super(\n \"highstate:k8s:StatefulSet\",\n name,\n args,\n opts,\n\n output(args.cluster).info,\n statefulSet.metadata,\n statefulSet.spec,\n statefulSet.status,\n\n service,\n httpRoute,\n )\n }\n}\n","import { networking, types, type core } from \"@pulumi/kubernetes\"\nimport {\n ComponentResource,\n normalize,\n output,\n type Input,\n type InputArray,\n type Output,\n type Resource,\n type ResourceOptions,\n type Unwrap,\n} from \"@highstate/pulumi\"\nimport { capitalize, flat, merge, mergeDeep } from \"remeda\"\nimport { parseDomain, ParseResultType, type ParseResultIp } from \"parse-domain\"\nimport { k8s } from \"@highstate/library\"\nimport {\n mapMetadata,\n mapNamespaceLikeToNamespaceName,\n mapNamespaceNameToSelector,\n mapSelectorLikeToSelector,\n type CommonArgs,\n type NamespaceLike,\n type SelectorLike,\n} from \"./shared\"\nimport { mapServiceToLabelSelector } from \"./service\"\n\nexport type NetworkPolicyPort = {\n /**\n * The protocol to match.\n *\n * If not provided, \"TCP\" will be used.\n */\n protocol?: string\n} & (\n | {\n /**\n * The single port to match.\n */\n port: number\n }\n | {\n /**\n * The range of ports to match.\n */\n range: [start: number, end: number]\n }\n)\n\nexport type IngressRuleArgs = {\n /**\n * Whether to allow all incoming traffic.\n *\n * If set to `true`, all other rules will be ignored for matched traffic.\n */\n fromAll?: Input<boolean>\n\n /**\n * The allowed cidr for incoming traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n fromCidr?: Input<string>\n\n /**\n * The list of allowed cidrs for incoming traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n fromCidrs?: InputArray<string>\n\n /**\n * The service to allow traffic from.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n fromService?: Input<core.v1.Service>\n\n /**\n * The list of allowed services for incoming traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n fromServices?: InputArray<core.v1.Service>\n\n /**\n * The namespace to allow traffic from.\n *\n * If provided with `fromSelector(s)`, it will be ANDed with them.\n * Otherwise, it will match all pods in the namespace.\n *\n * Will be ORed with other conditions inside the same rule (except ports and selectors).\n */\n fromNamespace?: Input<NamespaceLike>\n\n /**\n * The list of allowed namespaces for incoming traffic.\n *\n * If provided with `fromSelector(s)`, it will be ANDed with them.\n * Otherwise, it will match all pods in the namespaces.\n *\n * Will be ORed with other conditions inside the same rule (except ports and selectors).\n */\n fromNamespaces?: InputArray<NamespaceLike>\n\n /**\n * The selector for incoming traffic.\n *\n * If provided with `fromNamespace(s)`, it will be ANDed with them.\n * Otherwise, it will match pods in all namespaces.\n *\n * Will be ORed with other conditions inside the same rule (except ports and namespaces).\n */\n fromSelector?: Input<SelectorLike>\n\n /**\n * The list of selectors for incoming traffic.\n *\n * If provided with `fromNamespace(s)`, it will be ANDed with them.\n * Otherwise, it will match pods in all namespaces.\n *\n * Will be ORed with other conditions inside the same rule (except ports and namespaces).\n */\n fromSelectors?: InputArray<SelectorLike>\n\n /**\n * The port to allow incoming traffic on.\n *\n * Will be ANDed with all conditions inside the same rule.\n */\n toPort?: Input<NetworkPolicyPort>\n\n /**\n * The list of allowed ports for incoming traffic.\n *\n * Will be ANDed with all conditions inside the same rule.\n */\n toPorts?: InputArray<NetworkPolicyPort>\n}\n\nexport type EgressRuleArgs = {\n /**\n * Whether to allow all outgoing traffic.\n *\n * If set to `true`, all other rules will be ignored for matched traffic.\n */\n toAll?: Input<boolean>\n\n /**\n * The allowed cidr for outgoing traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toCidr?: Input<string>\n\n /**\n * The list of allowed cidrs for outgoing traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toCidrs?: InputArray<string>\n\n /**\n * The FQDN to allow outgoing traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toFqdn?: Input<string>\n\n /**\n * The list of allowed FQDNs for outgoing traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toFqdns?: InputArray<string>\n\n /**\n * Either the FQDN or the IP address of the endpoint to allow outgoing traffic.\n *\n * Just a syntactic sugar for `toFqdn` and `toCidr` for cases when the endpoint can be both.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toEndpoint?: Input<string>\n\n /**\n * The list of allowed endpoints for outgoing traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toEndpoints?: InputArray<string>\n\n /**\n * The service to allow traffic to.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toService?: Input<core.v1.Service>\n\n /**\n * The list of allowed services for outgoing traffic.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n */\n toServices?: InputArray<core.v1.Service>\n\n /**\n * The namespace to allow traffic to.\n *\n * If provided with `toSelector(s)`, it will be ANDed with them.\n * Otherwise, it will match all pods in the namespace.\n *\n * Will be ORed with other conditions inside the same rule (except ports and selectors).\n */\n toNamespace?: Input<NamespaceLike>\n\n /**\n * The list of allowed namespaces for outgoing traffic.\n *\n * If provided with `toSelector(s)`, it will be ANDed with them.\n * Otherwise, it will match all pods in the namespaces.\n *\n * Will be ORed with other conditions inside the same rule (except ports and selectors).\n */\n toNamespaces?: InputArray<NamespaceLike>\n\n /**\n * The selector for outgoing traffic.\n *\n * If provided with `toNamespace(s)`, it will be ANDe with them.\n *\n * Otherwise, it will match pods only in all namespaces.\n */\n toSelector?: Input<SelectorLike>\n\n /**\n * The list of selectors for outgoing traffic.\n *\n * If provided with `toNamespace(s)`, it will be ANDed with them.\n * Otherwise, it will match pods only in all namespaces.\n */\n toSelectors?: InputArray<SelectorLike>\n\n /**\n * The port to allow outgoing traffic on.\n *\n * Will be ANDed with all conditions inside the same rule.\n */\n toPort?: Input<NetworkPolicyPort>\n\n /**\n * The list of allowed ports for outgoing traffic.\n *\n * Will be ANDed with all conditions inside the same rule.\n */\n toPorts?: InputArray<NetworkPolicyPort>\n}\n\nexport type NetworkPolicyArgs = CommonArgs & {\n /**\n * The description of this network policy.\n */\n description?: Input<string>\n\n /**\n * The pod selector for this network policy.\n * If not provided, it will select all pods in the namespace.\n */\n selector?: SelectorLike\n\n /**\n * The rule for incoming traffic.\n */\n ingressRule?: Input<IngressRuleArgs>\n\n /**\n * The rules for incoming traffic.\n */\n ingressRules?: InputArray<IngressRuleArgs>\n\n /**\n * The rule for outgoing traffic.\n */\n egressRule?: Input<EgressRuleArgs>\n\n /**\n * The rules for outgoing traffic.\n */\n egressRules?: InputArray<EgressRuleArgs>\n\n /**\n * Enable the isolation of ingress traffic, so that only matched traffic can ingress.\n */\n isolateIngress?: Input<boolean>\n\n /**\n * Enable the isolation of egress traffic, so that only matched traffic can egress.\n */\n isolateEgress?: Input<boolean>\n\n /**\n * Allow the eggress traffic to the API server of the cluster.\n *\n * By default, `false`.\n */\n allowKubeApiServer?: Input<boolean>\n\n /**\n * Allow the eggress traffic to the DNS server of the cluster.\n *\n * By default, `false`.\n */\n allowKubeDns?: Input<boolean>\n\n /**\n * The cluster to create the network policy in.\n */\n cluster: Input<k8s.Cluster>\n}\n\nexport type NormalizedRuleArgs = {\n all: boolean\n cidrs: string[]\n fqdns: string[]\n services: core.v1.Service[]\n namespaces: NamespaceLike[]\n selectors: SelectorLike[]\n ports: NetworkPolicyPort[]\n}\n\nexport type NormalizedNetworkPolicyArgs = Omit<\n Unwrap<NetworkPolicyArgs>,\n | \"podSelector\"\n | \"ingressRule\"\n | \"ingressRules\"\n | \"egressRule\"\n | \"egressRules\"\n | \"isolateIngress\"\n | \"isolateEgress\"\n | \"allowKubeApiServer\"\n | \"allowKubeDNS\"\n> & {\n podSelector: Unwrap<types.input.meta.v1.LabelSelector>\n\n isolateIngress: boolean\n isolateEgress: boolean\n\n allowKubeApiServer: boolean\n\n ingressRules: NormalizedRuleArgs[]\n egressRules: NormalizedRuleArgs[]\n}\n\n/**\n * The abstract resource for creating network policies.\n * Will use different resources depending on the environment.\n *\n * Note: In the worst case, it will create native `NetworkPolicy` resources and ignore some features like L7 rules.\n */\nexport abstract class NetworkPolicy extends ComponentResource {\n /**\n * The underlying network policy resource.\n */\n public readonly networkPolicy: Output<Resource>\n\n protected constructor(name: string, args: Unwrap<NetworkPolicyArgs>, opts?: ResourceOptions) {\n super(\"k8s:network-policy\", name, args, opts)\n\n const normalizedArgs = output(args).apply(args => {\n const ingressRules = normalize(args.ingressRule, args.ingressRules)\n const egressRules = normalize(args.egressRule, args.egressRules)\n\n const endpoints = normalize(args.egressRule?.toEndpoint, args.egressRule?.toEndpoints)\n const parsedEndpoints = endpoints.map(endpoint => parseDomain(endpoint))\n\n const cidrsFromEndpoints = parsedEndpoints\n .filter(result => result.type === ParseResultType.Ip)\n .map(result => NetworkPolicy.mapCidrFromEndpoint(result))\n\n const fqdnsFromEndpoints = parsedEndpoints\n .filter(result => result.type !== ParseResultType.Invalid)\n .map(result => result.hostname)\n\n const extraEgressRules: NormalizedRuleArgs[] = []\n\n if (args.allowKubeDns) {\n extraEgressRules.push({\n namespaces: [\"kube-system\"],\n selectors: [{ matchLabels: { \"k8s-app\": \"kube-dns\" } }],\n ports: [{ port: 53, protocol: \"UDP\" }],\n all: false,\n cidrs: [],\n fqdns: [],\n services: [],\n })\n }\n\n return {\n ...args,\n\n podSelector: args.selector ? mapSelectorLikeToSelector(args.selector) : {},\n\n isolateEgress: args.isolateEgress ?? false,\n isolateIngress: args.isolateIngress ?? false,\n\n allowKubeApiServer: args.allowKubeApiServer ?? false,\n\n ingressRules: ingressRules.map(rule => ({\n all: rule.fromAll ?? false,\n cidrs: normalize(rule.fromCidr, rule.fromCidrs),\n fqdns: [],\n services: normalize(rule.fromService, rule.fromServices),\n namespaces: normalize(rule.fromNamespace, rule.fromNamespaces),\n selectors: normalize(rule.fromSelector, rule.fromSelectors),\n ports: normalize(rule.toPort, rule.toPorts),\n })),\n\n egressRules: egressRules\n .map(rule => {\n return {\n all: rule.toAll ?? false,\n cidrs: normalize(rule.toCidr, rule.toCidrs).concat(cidrsFromEndpoints),\n fqdns: normalize(rule.toFqdn, rule.toFqdns).concat(fqdnsFromEndpoints),\n services: normalize(rule.toService, rule.toServices),\n namespaces: normalize(rule.toNamespace, rule.toNamespaces),\n selectors: normalize(rule.toSelector, rule.toSelectors),\n ports: normalize(rule.toPort, rule.toPorts),\n } as NormalizedRuleArgs\n })\n .concat(extraEgressRules),\n }\n })\n\n this.networkPolicy = normalizedArgs.apply(args => {\n return output(\n this.create(name, args as NormalizedNetworkPolicyArgs, { ...opts, parent: this }),\n )\n })\n\n this.registerOutputs({ networkPolicy: this.networkPolicy })\n }\n\n private static mapCidrFromEndpoint(result: ParseResultIp): string {\n if (result.ipVersion === 4) {\n return `${result.hostname}/32`\n }\n\n return `${result.hostname}/128`\n }\n\n protected abstract create(\n name: string,\n args: NormalizedNetworkPolicyArgs,\n opts?: ResourceOptions,\n ): Input<Resource>\n\n private static readonly supportedCNIs = [\"cilium\"]\n\n static create(\n name: string,\n args: NetworkPolicyArgs,\n opts: ResourceOptions,\n ): Output<NetworkPolicy> {\n return output(args).apply(async args => {\n const cni = args.cluster.info.cni\n\n if (!cni || !NetworkPolicy.supportedCNIs.includes(cni)) {\n return new NativeNetworkPolicy(name, args, opts)\n }\n\n const implName = `${capitalize(cni)}NetworkPolicy`\n const implModule = (await import(`@highstate/${cni}`)) as Record<string, unknown>\n\n type NetworkPolicyFactory = new (\n name: string,\n args: Unwrap<NetworkPolicyArgs>,\n opts?: ResourceOptions,\n ) => NetworkPolicy\n\n const implClass = implModule[implName] as NetworkPolicyFactory | undefined\n if (!implClass) {\n throw new Error(`No implementation found for ${cni}`)\n }\n\n return new implClass(name, args, opts)\n })\n }\n\n static allowInsideNamespace(\n namespace: Input<NamespaceLike>,\n cluster: Input<k8s.Cluster>,\n opts: ResourceOptions,\n ): Output<NetworkPolicy> {\n return NetworkPolicy.create(\n \"allow-inside-namespace\",\n {\n namespace,\n cluster,\n\n description: \"Allow all traffic inside the namespace.\",\n selector: {},\n\n ingressRule: { fromNamespace: namespace },\n egressRule: { toNamespace: namespace },\n },\n opts,\n )\n }\n\n static allowKubeApiServer(\n namespace: Input<NamespaceLike>,\n cluster: Input<k8s.Cluster>,\n opts: ResourceOptions,\n ): Output<NetworkPolicy> {\n return NetworkPolicy.create(\n \"allow-kube-api-server\",\n {\n namespace,\n cluster,\n\n description: \"Allow all traffic to the Kubernetes API server from the namespace.\",\n\n allowKubeApiServer: true,\n },\n opts,\n )\n }\n\n static allowKubeDns(\n namespace: Input<NamespaceLike>,\n cluster: Input<k8s.Cluster>,\n opts: ResourceOptions,\n ): Output<NetworkPolicy> {\n return NetworkPolicy.create(\n \"allow-kube-dns\",\n {\n namespace,\n cluster,\n\n description: \"Allow all traffic to the Kubernetes DNS server from the namespace.\",\n\n allowKubeDns: true,\n },\n opts,\n )\n }\n\n static allowAllEgress(\n namespace: Input<NamespaceLike>,\n cluster: Input<k8s.Cluster>,\n opts: ResourceOptions,\n ): Output<NetworkPolicy> {\n return NetworkPolicy.create(\n \"allow-all-egress\",\n {\n namespace,\n cluster,\n\n description: \"Allow all egress traffic from the namespace.\",\n\n egressRule: { toAll: true },\n },\n opts,\n )\n }\n}\n\nexport class NativeNetworkPolicy extends NetworkPolicy {\n protected create(\n name: string,\n args: NormalizedNetworkPolicyArgs,\n opts?: ResourceOptions,\n ): Resource {\n const ingress = NativeNetworkPolicy.createIngressRules(args)\n const egress = NativeNetworkPolicy.createEgressRules(args)\n\n const policyTypes: string[] = []\n\n if (ingress.length > 0 || args.isolateIngress) {\n policyTypes.push(\"Ingress\")\n }\n\n if (egress.length > 0 || args.isolateEgress) {\n policyTypes.push(\"Egress\")\n }\n\n return new networking.v1.NetworkPolicy(\n name,\n {\n metadata: mergeDeep(mapMetadata(args, name), {\n annotations: args.description\n ? { \"kubernetes.io/description\": args.description }\n : undefined,\n }),\n spec: {\n podSelector: args.podSelector,\n ingress,\n egress,\n policyTypes,\n },\n },\n opts,\n )\n }\n\n private static fallbackIpBlock: types.input.networking.v1.IPBlock = {\n cidr: \"0.0.0.0/0\",\n except: [\"10.0.0.0/8\", \"172.16.0.0/12\", \"192.168.0.0/16\"],\n }\n\n private static createIngressRules(\n args: NormalizedNetworkPolicyArgs,\n ): types.input.networking.v1.NetworkPolicyIngressRule[] {\n return args.ingressRules.map(rule => ({\n from: rule.all ? undefined : NativeNetworkPolicy.createRulePeers(rule),\n ports: NativeNetworkPolicy.mapPorts(rule.ports),\n }))\n }\n\n private static createEgressRules(\n args: NormalizedNetworkPolicyArgs,\n ): types.input.networking.v1.NetworkPolicyEgressRule[] {\n // the native resource does not support FQDNs\n // to provide compatibility, we need to fallback to all except private CIDRs\n const needFallback = args.egressRules.some(rule => rule.fqdns.length > 0)\n if (needFallback) {\n return [{ to: [{ ipBlock: NativeNetworkPolicy.fallbackIpBlock }] }]\n }\n\n const extraRules: types.input.networking.v1.NetworkPolicyEgressRule[] = []\n\n if (args.allowKubeApiServer) {\n const apiServerIp = args.cluster.info.kubeApiServerIp ?? \"10.96.0.1\"\n const apiServerPort = args.cluster.info.kubeApiServerPort ?? 443\n\n extraRules.push({\n to: [{ ipBlock: { cidr: `${apiServerIp}/32` } }],\n ports: [{ port: apiServerPort, protocol: \"TCP\" }],\n })\n }\n\n return args.egressRules\n .map(rule => {\n return {\n to: rule.all ? undefined : NativeNetworkPolicy.createRulePeers(rule),\n ports: NativeNetworkPolicy.mapPorts(rule.ports),\n } as types.input.networking.v1.NetworkPolicyEgressRule\n })\n .concat(extraRules)\n }\n\n private static createRulePeers(\n this: void,\n args: NormalizedRuleArgs,\n ): types.input.networking.v1.NetworkPolicyPeer[] {\n return [\n ...NativeNetworkPolicy.createCidrPeers(args),\n ...NativeNetworkPolicy.createServicePeers(args),\n ...NativeNetworkPolicy.createSelectorPeers(args),\n ]\n }\n\n private static createCidrPeers(\n args: NormalizedRuleArgs,\n ): types.input.networking.v1.NetworkPolicyPeer[] {\n return args.cidrs.map(cidr => ({ ipBlock: { cidr } }))\n }\n\n private static createServicePeers(\n args: NormalizedRuleArgs,\n ): types.input.networking.v1.NetworkPolicyPeer[] {\n return args.services.map(service => {\n const selector = mapServiceToLabelSelector(service)\n\n return {\n namespaceSelector: mapNamespaceNameToSelector(service.metadata.namespace),\n podSelector: selector,\n }\n })\n }\n\n private static createSelectorPeers(\n args: NormalizedRuleArgs,\n ): types.input.networking.v1.NetworkPolicyPeer[] {\n const selectorPeers = args.selectors.map(selector => ({\n podSelector: mapSelectorLikeToSelector(selector),\n }))\n\n const namespacePeers = args.namespaces.map(NativeNetworkPolicy.createNamespacePeer)\n\n if (namespacePeers.length === 0) {\n // if there are no namespaces, we can just return selector peers\n return selectorPeers\n }\n\n if (selectorPeers.length === 0) {\n // if there are no selectors, we can just return namespace peers\n return namespacePeers\n }\n\n // if there are both, we need to create a cartesian product\n return flat(\n selectorPeers.map(selectorPeer => {\n return namespacePeers.map(namespacePeer => merge(selectorPeer, namespacePeer))\n }),\n )\n }\n\n private static createNamespacePeer(\n this: void,\n namespace: NamespaceLike,\n ): types.input.networking.v1.NetworkPolicyPeer {\n const namespaceName = mapNamespaceLikeToNamespaceName(namespace)\n const namespaceSelector = mapNamespaceNameToSelector(namespaceName)\n\n return { namespaceSelector }\n }\n\n private static mapPorts(\n ports: NetworkPolicyPort[],\n ): types.input.networking.v1.NetworkPolicyPort[] {\n return ports.map(port => {\n if (\"port\" in port) {\n return {\n port: port.port,\n protocol: port.protocol ?? \"TCP\",\n }\n }\n\n return {\n port: port.range[0],\n endPort: port.range[1],\n protocol: port.protocol ?? \"TCP\",\n }\n })\n }\n}\n","import type { k8s } from \"@highstate/library\"\nimport type { core, Provider } from \"@pulumi/kubernetes\"\nimport { DnsRecord } from \"@highstate/common\"\nimport { gateway } from \"@highstate/gateway-api\"\nimport {\n normalize,\n Output,\n output,\n toPromise,\n type Input,\n type InputArray,\n} from \"@highstate/pulumi\"\nimport { NetworkPolicy } from \"./network-policy\"\nimport { getAppDisplayName, getAppName, mapNamespaceLikeToNamespaceName } from \"./shared\"\n\nexport type UseAccessPointResult = {\n /**\n * The gateway instance created according to the access point.\n */\n gateway: gateway.v1.Gateway\n\n /**\n * The DNS record associated created according to the access point and gateway.\n */\n dnsRecords: DnsRecord[]\n\n /**\n * The network policies associated with the access point.\n */\n networkPolicies: NetworkPolicy[]\n}\n\nexport type UseAccessPointArgs = Omit<CreateGatewayArgs, \"gateway\"> & {\n accessPoint: Input<k8s.AccessPoint>\n}\n\nexport function useAccessPoint(args: UseAccessPointArgs): Promise<UseAccessPointResult> {\n const result = output({ args, namespaceName: output(args.namespace).metadata.name }).apply(\n ({ args, namespaceName }) => {\n const gateway = createGateway({\n ...args,\n annotations: {\n \"cert-manager.io/cluster-issuer\": args.accessPoint.tlsIssuer.clusterIssuerName,\n },\n gateway: args.accessPoint.gateway,\n })\n\n const dnsRecords = normalize(args.fqdn, args.fqdns).flatMap(fqdn => {\n return DnsRecord.createSet(fqdn, {\n providers: args.accessPoint.dnsProviders,\n type: \"A\",\n value: args.accessPoint.gateway.ip,\n })\n })\n\n const networkPolicies: Output<NetworkPolicy>[] = []\n\n if (args.accessPoint.gateway.service) {\n const displayName = getAppDisplayName(args.accessPoint.gateway.service.metadata)\n\n networkPolicies.push(\n NetworkPolicy.create(\n `allow-ingress-from-${getAppName(args.accessPoint.gateway.service.metadata)}`,\n {\n namespace: args.namespace,\n cluster: args.cluster,\n\n description: `Allow ingress traffic from the gateway \"${displayName}\".`,\n\n ingressRule: {\n fromNamespace: args.accessPoint.gateway.service.metadata.namespace,\n fromSelector: args.accessPoint.gateway.service.spec.selector,\n },\n },\n { provider: args.provider },\n ),\n\n NetworkPolicy.create(\n `allow-egress-to-${namespaceName}`,\n {\n namespace: args.accessPoint.gateway.service.metadata.namespace,\n cluster: args.cluster,\n\n selector: args.accessPoint.gateway.service.spec.selector,\n\n description: `Allow egress traffic to the namespace \"${namespaceName}\".`,\n\n egressRule: {\n toNamespace: args.namespace,\n },\n },\n { provider: args.provider },\n ),\n )\n }\n\n return output({\n gateway,\n dnsRecords: output(dnsRecords).apply(records => records.flat()),\n networkPolicies,\n })\n },\n )\n\n return toPromise(result)\n}\n\nexport type StandardAccessPointArgs = {\n fqdn: string\n}\n\nexport type StandardAccessPointInputs = {\n accessPoint: Output<k8s.AccessPoint>\n k8sCluster: Output<k8s.Cluster>\n}\n\nexport function useStandardAcessPoint(\n appName: string,\n namespace: core.v1.Namespace,\n args: StandardAccessPointArgs,\n inputs: StandardAccessPointInputs,\n provider: Provider,\n): Promise<UseAccessPointResult> {\n return useAccessPoint({\n name: appName,\n namespace,\n\n fqdn: args.fqdn,\n\n accessPoint: inputs.accessPoint,\n cluster: inputs.k8sCluster,\n provider,\n })\n}\n\nexport type CreateGatewayArgs = {\n name: string\n namespace: Input<core.v1.Namespace>\n annotations?: Input<Record<string, string>>\n\n fqdn?: Input<string>\n fqdns?: InputArray<string>\n\n gateway: Input<k8s.Gateway>\n cluster: Input<k8s.Cluster>\n provider: Provider\n}\n\nexport function createGateway(args: CreateGatewayArgs): Output<gateway.v1.Gateway> {\n return output(args).apply(args => {\n if (args.cluster.info.id !== args.gateway.clusterInfo.id) {\n throw new Error(\n \"The provided Kubernetes cluster is different from the one where the gateway controller is deployed.\",\n )\n }\n\n return new gateway.v1.Gateway(\n args.name,\n {\n metadata: {\n name: args.name,\n namespace: mapNamespaceLikeToNamespaceName(args.namespace),\n annotations: args.annotations,\n },\n spec: {\n gatewayClassName: output(args.gateway).gatewayClassName,\n listeners: normalize(args.fqdn, args.fqdns).map(fqdn => {\n const normalizedName = fqdn.replace(/\\*/g, \"wildcard\")\n\n return {\n name: `https-${normalizedName}`,\n port: output(args.gateway).httpsListenerPort,\n protocol: \"HTTPS\",\n hostname: fqdn,\n tls: {\n mode: \"Terminate\",\n certificateRefs: [{ name: normalizedName }],\n },\n }\n }),\n },\n },\n { provider: args.provider, deletedWith: args.namespace },\n )\n })\n}\n","import type { ContainerEnvironment, ContainerVolumeMount, WorkloadVolume } from \"../container\"\nimport { core } from \"@pulumi/kubernetes\"\nimport { apply, normalize, type InputArray } from \"@highstate/pulumi\"\nimport {\n ComponentResource,\n output,\n type ComponentResourceOptions,\n type Input,\n type Output,\n type Unwrap,\n} from \"@pulumi/pulumi\"\nimport { pipe } from \"remeda\"\nimport { deepmerge } from \"deepmerge-ts\"\nimport { text, trimIndentation } from \"@highstate/contract\"\nimport { mapMetadata, type CommonArgs } from \"../shared\"\nimport {\n emptyScriptEnvironment,\n type ResolvedScriptEnvironment,\n type ScriptDistribution,\n type ScriptEnvironment,\n} from \"./environment\"\n\nexport type ScriptBundleArgs = CommonArgs & {\n /**\n * The environment to bundle the scripts from.\n */\n environment?: Input<ScriptEnvironment>\n\n /**\n * The environments to bundle the scripts from.\n */\n environments?: InputArray<ScriptEnvironment>\n\n /**\n * The distribution to use for the scripts.\n */\n distribution: ScriptDistribution\n}\n\nexport class ScriptBundle extends ComponentResource {\n /**\n * The config map containing the scripts.\n */\n readonly configMap: Output<core.v1.ConfigMap>\n\n /**\n * The volumes that should be included in the workload.\n */\n readonly volumes: Output<WorkloadVolume[]>\n\n /**\n * The volume mounts that should be defined in the container.\n */\n readonly volumeMounts: Output<ContainerVolumeMount[]>\n\n /**\n * The environment variables that should be defined in the container.\n */\n readonly environment: Output<ContainerEnvironment>\n\n /**\n * The distribution to use for the scripts.\n */\n readonly distribution: ScriptDistribution\n\n constructor(name: string, args: ScriptBundleArgs, opts?: ComponentResourceOptions) {\n super(\"highstate:k8s:ScriptBundle\", name, args, opts)\n\n const scriptEnvironment = pipe(\n output(args),\n apply(args => normalize(args.environment, args.environments)),\n apply(args => deepmerge(emptyScriptEnvironment, ...args)),\n ) as Output<Unwrap<ResolvedScriptEnvironment>>\n\n this.distribution = args.distribution\n this.environment = scriptEnvironment.environment\n\n this.configMap = output({ scriptEnvironment, args }).apply(({ scriptEnvironment, args }) => {\n return new core.v1.ConfigMap(\n name,\n {\n metadata: mapMetadata(args, name),\n data: createScriptData(this.distribution, scriptEnvironment),\n },\n { ...opts, parent: this },\n )\n })\n\n this.volumes = scriptEnvironment.volumes.apply(volumes => {\n return [\n ...volumes,\n {\n name: this.configMap.metadata.name,\n\n configMap: {\n name: this.configMap.metadata.name,\n defaultMode: 0o550, // read and execute permissions\n },\n },\n ]\n })\n\n this.volumeMounts = scriptEnvironment.volumeMounts.apply(volumeMounts => {\n return [\n ...volumeMounts,\n {\n volume: this.configMap,\n mountPath: \"/scripts\",\n },\n ]\n })\n\n this.registerOutputs({\n configMap: this.configMap,\n volumes: this.volumes,\n volumeMounts: this.volumeMounts,\n environment: this.environment,\n })\n }\n}\n\nfunction createScriptData(\n distribution: ScriptDistribution,\n environment: Unwrap<ResolvedScriptEnvironment>,\n): Record<string, string> {\n const scriptData: Record<string, string> = {}\n const actions: string[] = []\n\n const distributionEnvironment = environment[distribution]\n\n if (distributionEnvironment.preInstallPackages.length > 0) {\n scriptData[\"pre-install-packages.sh\"] = getInstallPackagesScript(\n distribution,\n distributionEnvironment.preInstallPackages,\n )\n\n actions.push(`\n echo \"+ Installing pre-install packages...\"\n /scripts/pre-install-packages.sh\n echo \"+ Pre-install packages installed successfully\"\n `)\n }\n\n if (Object.keys(distributionEnvironment.preInstallScripts).length > 0) {\n for (const key in distributionEnvironment.preInstallScripts) {\n scriptData[`pre-install-${key}`] = distributionEnvironment.preInstallScripts[key]\n\n actions.push(`\n echo \"+ Running pre-install script '${key}'...\"\n /scripts/pre-install-${key}\n echo \"+ Pre-install script '${key}'... Done\"\n `)\n }\n }\n\n if (distributionEnvironment.packages.length > 0) {\n scriptData[\"install-packages.sh\"] = getInstallPackagesScript(\n distribution,\n distributionEnvironment.packages,\n )\n\n actions.push(`\n echo \"+ Installing packages...\"\n /scripts/install-packages.sh\n echo \"+ Packages installed successfully\"\n `)\n }\n\n if (Object.keys(environment.setupScripts).length > 0) {\n for (const key in environment.setupScripts) {\n scriptData[`setup-${key}`] = environment.setupScripts[key]\n\n actions.push(`\n echo \"+ Running setup script '${key}'...\"\n /scripts/setup-${key}\n echo \"+ Setup script '${key}'... Done\"\n `)\n }\n }\n\n if (Object.keys(environment.cleanupScripts).length > 0) {\n const cleanupActions: string[] = []\n\n for (const key in environment.cleanupScripts) {\n scriptData[`cleanup-${key}`] = environment.cleanupScripts[key]\n\n cleanupActions.push(`\n echo \"+ Running cleanup script '${key}'...\"\n /scripts/cleanup-${key}\n echo \"+ Cleanup script '${key}'... Done\"\n `)\n }\n\n actions.push(`\n function cleanup() {\n ${cleanupActions.map(s => s.trim()).join(\"\\n\\n\")}\n }\n\n trap cleanup EXIT\n trap cleanup SIGTERM\n `)\n }\n\n for (const key in environment.scripts) {\n scriptData[key] = environment.scripts[key]\n }\n\n scriptData[\"entrypoint.sh\"] = trimIndentation(`\n #!/bin/sh\n set -e\n\n if [ -z \"$1\" ]; then\n echo \"Usage: entrypoint.sh <main script> [args...]\"\n exit 1\n fi\n\n ${actions.map(s => s.trim()).join(\"\\n\\n\")}\n\n echo \"+ Running main script...\"\n $@\n echo \"+ Main script completed\"\n `)\n\n return scriptData\n}\n\nfunction getInstallPackagesScript(distribution: ScriptDistribution, packages: string[]): string {\n if (distribution === \"alpine\") {\n return text`\n #!/bin/sh\n set -e\n\n apk add --no-cache ${packages.join(\" \")}\n `\n } else {\n return text`\n #!/bin/sh\n set -e\n\n apt-get update\n apt-get install -y ${packages.join(\" \")}\n `\n }\n}\n","import type { Input, InputArray, InputMap } from \"@highstate/pulumi\"\nimport type { ContainerEnvironment, ContainerVolumeMount, WorkloadVolume } from \"../container\"\n\nexport type ScriptDistribution = \"alpine\" | \"ubuntu\"\n\nexport type DistributionEnvironment = {\n /**\n * The utility packages that should be installed before running \"preInstallScripts\".\n *\n * Useful for installing tools like `curl` to install additional repositories.\n */\n preInstallPackages?: InputArray<string>\n\n /**\n * The pre-install scripts that should be run before installing packages.\n * Typically, these scripts are used to install additional repositories.\n */\n preInstallScripts?: InputMap<string>\n\n /**\n * The packages that are available in the environment.\n */\n packages?: InputArray<string>\n}\n\nexport type ScriptEnvironment = {\n [distribution in ScriptDistribution]?: DistributionEnvironment\n} & {\n /**\n * The setup scripts that should be run before the script.\n */\n setupScripts?: InputMap<string>\n\n /**\n * The cleanup scripts that should be run after the script.\n */\n cleanupScripts?: InputMap<string>\n\n /**\n * The arbitrary scripts available in the environment.\n */\n scripts?: InputMap<string>\n\n /**\n * The volumes that should be defined in the environment.\n */\n volumes?: InputArray<WorkloadVolume>\n\n /**\n * The volume mounts that should be defined in the environment.\n */\n volumeMounts?: InputArray<ContainerVolumeMount>\n\n /**\n * The environment variables that should be defined in the environment.\n */\n environment?: Input<ContainerEnvironment>\n}\n\nexport type ResolvedScriptEnvironment = Omit<Required<ScriptEnvironment>, ScriptDistribution> & {\n [distribution in ScriptDistribution]: Required<DistributionEnvironment>\n}\n\nconst emptyDistributionEnvironment: Required<DistributionEnvironment> = {\n preInstallPackages: [],\n preInstallScripts: {},\n packages: [],\n}\n\nexport const emptyScriptEnvironment: ResolvedScriptEnvironment = {\n alpine: emptyDistributionEnvironment,\n ubuntu: emptyDistributionEnvironment,\n setupScripts: {},\n cleanupScripts: {},\n scripts: {},\n volumes: [],\n volumeMounts: [],\n environment: {},\n}\n","import type { Container } from \"../container\"\nimport type { ScriptBundle } from \"./bundle\"\nimport { Output, output, type Input } from \"@pulumi/pulumi\"\nimport { merge } from \"remeda\"\n\nexport interface ScriptContainer extends Container {\n /**\n * The script bundle to use.\n */\n bundle: Input<ScriptBundle>\n\n /**\n * The name of the main script to run.\n * The script must be available in the bundle.\n */\n main: Input<string>\n}\n\n/**\n * Creates a spec for a container that runs a script.\n * This spec can be used to create a complete workload or an init container.\n *\n * @param options The options to create the container spec.\n * @returns The container spec.\n */\nexport function createScriptContainer(options: ScriptContainer): Output<Container> {\n return output(options).apply(options => {\n const image =\n options.bundle.distribution === \"alpine\"\n ? \"alpine@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c\"\n : \"ubuntu@sha256:72297848456d5d37d1262630108ab308d3e9ec7ed1c3286a32fe09856619a782\"\n\n return {\n image,\n command: [\"/scripts/entrypoint.sh\", `/scripts/${options.main}`],\n\n ...options,\n\n volumeMounts: merge(options.bundle.volumeMounts, options.volumeMounts),\n volumes: merge(options.bundle.volumes, options.volumes),\n environment: merge(options.bundle.environment, options.environment),\n }\n })\n}\n","import { batch, type types } from \"@pulumi/kubernetes\"\nimport {\n ComponentResource,\n normalize,\n Output,\n output,\n type ComponentResourceOptions,\n type Input,\n type InputArray,\n} from \"@highstate/pulumi\"\nimport { mergeDeep, omit } from \"remeda\"\nimport { mapContainerToRaw, mapWorkloadVolume, type Container } from \"./container\"\nimport { commonExtraArgs, mapMetadata, type CommonArgs } from \"./shared\"\n\nexport type JobArgs = CommonArgs & {\n container?: Input<Container>\n containers?: InputArray<Container>\n} & Omit<Partial<types.input.batch.v1.JobSpec>, \"template\"> & {\n template?: {\n metadata?: types.input.meta.v1.ObjectMeta\n spec?: Partial<types.input.core.v1.PodSpec>\n }\n }\n\nconst jobExtraArgs = [...commonExtraArgs, \"container\", \"containers\"] as const\n\nexport class Job extends ComponentResource {\n /**\n * The underlying Kubernetes job.\n */\n public readonly job: Output<batch.v1.Job>\n\n constructor(name: string, args: JobArgs, opts?: ComponentResourceOptions) {\n super(\"highstate:k8s:Job\", name, args, opts)\n\n this.job = output(args).apply(args => {\n const containers = normalize(args.container, args.containers)\n\n return new batch.v1.Job(\n name,\n {\n metadata: mapMetadata(args, name),\n spec: mergeDeep(\n {\n template: {\n spec: {\n containers: containers.map(container => mapContainerToRaw(container, name)),\n\n volumes: containers\n .flatMap(container => normalize(container.volume, container.volumes))\n .map(mapWorkloadVolume),\n\n restartPolicy: \"Never\",\n },\n },\n } satisfies types.input.batch.v1.JobSpec,\n omit(args, jobExtraArgs) as types.input.batch.v1.JobSpec,\n ),\n },\n { parent: this, ...opts },\n )\n })\n\n this.registerOutputs({ job: this.job })\n }\n}\n","import type { RequiredKeys } from \"@highstate/contract\"\nimport { batch, type types } from \"@pulumi/kubernetes\"\nimport {\n ComponentResource,\n normalize,\n Output,\n output,\n type ComponentResourceOptions,\n type Input,\n type InputArray,\n} from \"@highstate/pulumi\"\nimport { mergeDeep, omit } from \"remeda\"\nimport { mapContainerToRaw, mapWorkloadVolume, type Container } from \"./container\"\nimport { commonExtraArgs, mapMetadata, type CommonArgs } from \"./shared\"\n\nexport type CronJobArgs = CommonArgs & {\n container?: Input<Container>\n containers?: InputArray<Container>\n} & Omit<RequiredKeys<Partial<types.input.batch.v1.CronJobSpec>, \"schedule\">, \"jobTemplate\"> & {\n jobTemplate?: {\n metadata?: types.input.meta.v1.ObjectMeta\n spec?: Omit<types.input.batch.v1.JobSpec, \"template\"> & {\n template?: {\n metadata?: types.input.meta.v1.ObjectMeta\n spec?: Partial<types.input.core.v1.PodSpec>\n }\n }\n }\n }\n\nconst cronJobExtraArgs = [...commonExtraArgs, \"container\", \"containers\"] as const\n\nexport class CronJob extends ComponentResource {\n /**\n * The underlying Kubernetes job.\n */\n public readonly cronJob: Output<batch.v1.CronJob>\n\n constructor(name: string, args: CronJobArgs, opts?: ComponentResourceOptions) {\n super(\"highstate:k8s:CronJob\", name, args, opts)\n\n this.cronJob = output(args).apply(args => {\n const containers = normalize(args.container, args.containers)\n\n return new batch.v1.CronJob(\n name,\n {\n metadata: mapMetadata(args, name),\n\n spec: mergeDeep(\n {\n jobTemplate: {\n spec: {\n template: {\n spec: {\n containers: containers.map(container => mapContainerToRaw(container, name)),\n\n volumes: containers\n .flatMap(container => normalize(container.volume, container.volumes))\n .map(mapWorkloadVolume),\n },\n },\n },\n },\n\n schedule: args.schedule,\n } satisfies types.input.batch.v1.CronJobSpec,\n omit(args, cronJobExtraArgs) as types.input.batch.v1.CronJobSpec,\n ),\n },\n { parent: this, ...opts },\n )\n })\n\n this.registerOutputs({ cronJob: this.cronJob })\n }\n}\n"],"mappings":"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","names":["output","ComponentResource","omit","deepmerge","core","output","omit","args","id","omit","output","core","normalize","ComponentResource","output","output","args","normalize","containers","service","ComponentResource","output","args","containers","volumes","deepmerge","omit","output","ComponentResource","apps","omit","deepmerge","ComponentResource","output","args","containers","volumes","service","apps","deepmerge","omit","ComponentResource","normalize","output","ComponentResource","output","args","normalize","normalize","output","output","args","gateway","normalize","core","normalize","ComponentResource","output","deepmerge","trimIndentation","ComponentResource","output","args","normalize","deepmerge","scriptEnvironment","core","trimIndentation","output","merge","options","ComponentResource","normalize","output","mergeDeep","omit","ComponentResource","output","args","normalize","mergeDeep","omit","batch","ComponentResource","normalize","output","mergeDeep","omit","ComponentResource","output","args","normalize","batch","mergeDeep","omit"]}
@@ -4,7 +4,7 @@ import { forUnit } from "@highstate/pulumi";
4
4
  var { inputs, outputs } = forUnit(k8s.accessPoint);
5
5
  var access_point_default = outputs({
6
6
  accessPoint: {
7
- dnsProvider: inputs.dnsProvider,
7
+ dnsProviders: inputs.dnsProviders,
8
8
  gateway: inputs.gateway,
9
9
  tlsIssuer: inputs.tlsIssuer
10
10
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/units/access-point/index.ts"],"sourcesContent":["import { k8s } from \"@highstate/library\"\nimport { forUnit } from \"@highstate/pulumi\"\n\nconst { inputs, outputs } = forUnit(k8s.accessPoint)\n\nexport default outputs({\n accessPoint: {\n dnsProvider: inputs.dnsProvider,\n gateway: inputs.gateway,\n tlsIssuer: inputs.tlsIssuer,\n },\n})\n"],"mappings":";AAAA,SAAS,WAAW;AACpB,SAAS,eAAe;AAExB,IAAM,EAAE,QAAQ,QAAQ,IAAI,QAAQ,IAAI,WAAW;AAEnD,IAAO,uBAAQ,QAAQ;AAAA,EACrB,aAAa;AAAA,IACX,aAAa,OAAO;AAAA,IACpB,SAAS,OAAO;AAAA,IAChB,WAAW,OAAO;AAAA,EACpB;AACF,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/units/access-point/index.ts"],"sourcesContent":["import { k8s } from \"@highstate/library\"\nimport { forUnit } from \"@highstate/pulumi\"\n\nconst { inputs, outputs } = forUnit(k8s.accessPoint)\n\nexport default outputs({\n accessPoint: {\n dnsProviders: inputs.dnsProviders,\n gateway: inputs.gateway,\n tlsIssuer: inputs.tlsIssuer,\n },\n})\n"],"mappings":";AAAA,SAAS,WAAW;AACpB,SAAS,eAAe;AAExB,IAAM,EAAE,QAAQ,QAAQ,IAAI,QAAQ,IAAI,WAAW;AAEnD,IAAO,uBAAQ,QAAQ;AAAA,EACrB,aAAa;AAAA,IACX,cAAc,OAAO;AAAA,IACrB,SAAS,OAAO;AAAA,IAChB,WAAW,OAAO;AAAA,EACpB;AACF,CAAC;","names":[]}
@@ -21,7 +21,6 @@ async function createDns01Solver(dnsProviderInput, provider2) {
21
21
  // src/units/dns01-issuer/index.ts
22
22
  var { name, inputs, outputs } = forUnit(k8s.dns01TlsIssuer);
23
23
  var provider = await getProvider(inputs.k8sCluster);
24
- var dns01Solver = await createDns01Solver(inputs.dnsProvider, provider);
25
24
  new cert_manager.v1.ClusterIssuer(
26
25
  name,
27
26
  {
@@ -31,12 +30,14 @@ new cert_manager.v1.ClusterIssuer(
31
30
  spec: {
32
31
  acme: {
33
32
  server: "https://acme-v02.api.letsencrypt.org/directory",
34
- solvers: [
35
- {
36
- dns01: dns01Solver,
37
- selector: { dnsZones: [inputs.dnsProvider.domain] }
38
- }
39
- ],
33
+ solvers: inputs.dnsProviders.apply(
34
+ (dnsProviders) => dnsProviders.map((dnsProvider) => {
35
+ return {
36
+ dns01: createDns01Solver(dnsProvider, provider),
37
+ selector: { dnsZones: [dnsProvider.domain] }
38
+ };
39
+ })
40
+ ),
40
41
  privateKeySecretRef: {
41
42
  name
42
43
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/units/dns01-issuer/index.ts","../../../src/units/dns01-issuer/solver.ts"],"sourcesContent":["import { k8s } from \"@highstate/library\"\nimport { forUnit, unsecret } from \"@highstate/pulumi\"\nimport { cert_manager } from \"@highstate/cert-manager\"\nimport { getProvider } from \"../../shared\"\nimport { createDns01Solver } from \"./solver\"\n\nconst { name, inputs, outputs } = forUnit(k8s.dns01TlsIssuer)\n\nconst provider = await getProvider(inputs.k8sCluster)\nconst dns01Solver = await createDns01Solver(inputs.dnsProvider, provider)\n\nnew cert_manager.v1.ClusterIssuer(\n name,\n {\n metadata: {\n name,\n },\n spec: {\n acme: {\n server: \"https://acme-v02.api.letsencrypt.org/directory\",\n solvers: [\n {\n dns01: dns01Solver,\n selector: { dnsZones: [inputs.dnsProvider.domain] },\n },\n ],\n privateKeySecretRef: {\n name,\n },\n },\n },\n },\n { provider },\n)\n\nexport default outputs({\n tlsIssuer: {\n clusterInfo: unsecret(inputs.k8sCluster.info),\n clusterIssuerName: name,\n },\n})\n","import type { dns } from \"@highstate/library\"\nimport type { types } from \"@highstate/cert-manager\"\nimport type { Input } from \"@pulumi/pulumi\"\nimport type { Provider } from \"@pulumi/kubernetes\"\nimport { capitalize } from \"remeda\"\nimport { toPromise } from \"@highstate/pulumi\"\n\nexport async function createDns01Solver(\n dnsProviderInput: Input<dns.Provider>,\n provider: Provider,\n): Promise<types.input.cert_manager.v1.ClusterIssuerSpecAcmeSolversDns01> {\n const dnsProvider = await toPromise(dnsProviderInput)\n\n const implName = `create${capitalize(dnsProvider.type)}Dns01Solver`\n const implModule = (await import(`@highstate/${dnsProvider.type}`)) as Record<string, unknown>\n\n const implFunction = implModule[implName] as (\n dnsProvider: dns.Provider,\n provider: Provider,\n ) => types.input.cert_manager.v1.ClusterIssuerSpecAcmeSolversDns01\n\n return implFunction(dnsProvider, provider)\n}\n"],"mappings":";;;;;AAAA,SAAS,WAAW;AACpB,SAAS,SAAS,gBAAgB;AAClC,SAAS,oBAAoB;;;ACE7B,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAE1B,eAAsB,kBACpB,kBACAA,WACwE;AACxE,QAAM,cAAc,MAAM,UAAU,gBAAgB;AAEpD,QAAM,WAAW,SAAS,WAAW,YAAY,IAAI,CAAC;AACtD,QAAM,aAAc,MAAM,OAAO,cAAc,YAAY,IAAI;AAE/D,QAAM,eAAe,WAAW,QAAQ;AAKxC,SAAO,aAAa,aAAaA,SAAQ;AAC3C;;;ADhBA,IAAM,EAAE,MAAM,QAAQ,QAAQ,IAAI,QAAQ,IAAI,cAAc;AAE5D,IAAM,WAAW,MAAM,YAAY,OAAO,UAAU;AACpD,IAAM,cAAc,MAAM,kBAAkB,OAAO,aAAa,QAAQ;AAExE,IAAI,aAAa,GAAG;AAAA,EAClB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR;AAAA,IACF;AAAA,IACA,MAAM;AAAA,MACJ,MAAM;AAAA,QACJ,QAAQ;AAAA,QACR,SAAS;AAAA,UACP;AAAA,YACE,OAAO;AAAA,YACP,UAAU,EAAE,UAAU,CAAC,OAAO,YAAY,MAAM,EAAE;AAAA,UACpD;AAAA,QACF;AAAA,QACA,qBAAqB;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,EAAE,SAAS;AACb;AAEA,IAAO,uBAAQ,QAAQ;AAAA,EACrB,WAAW;AAAA,IACT,aAAa,SAAS,OAAO,WAAW,IAAI;AAAA,IAC5C,mBAAmB;AAAA,EACrB;AACF,CAAC;","names":["provider"]}
1
+ {"version":3,"sources":["../../../src/units/dns01-issuer/index.ts","../../../src/units/dns01-issuer/solver.ts"],"sourcesContent":["import { k8s } from \"@highstate/library\"\nimport { forUnit, unsecret } from \"@highstate/pulumi\"\nimport { cert_manager } from \"@highstate/cert-manager\"\nimport { getProvider } from \"../../shared\"\nimport { createDns01Solver } from \"./solver\"\n\nconst { name, inputs, outputs } = forUnit(k8s.dns01TlsIssuer)\n\nconst provider = await getProvider(inputs.k8sCluster)\n\nnew cert_manager.v1.ClusterIssuer(\n name,\n {\n metadata: {\n name,\n },\n spec: {\n acme: {\n server: \"https://acme-v02.api.letsencrypt.org/directory\",\n solvers: inputs.dnsProviders.apply(dnsProviders =>\n dnsProviders.map(dnsProvider => {\n return {\n dns01: createDns01Solver(dnsProvider, provider),\n selector: { dnsZones: [dnsProvider.domain] },\n }\n }),\n ),\n privateKeySecretRef: {\n name,\n },\n },\n },\n },\n { provider },\n)\n\nexport default outputs({\n tlsIssuer: {\n clusterInfo: unsecret(inputs.k8sCluster.info),\n clusterIssuerName: name,\n },\n})\n","import type { dns } from \"@highstate/library\"\nimport type { types } from \"@highstate/cert-manager\"\nimport type { Input } from \"@pulumi/pulumi\"\nimport type { Provider } from \"@pulumi/kubernetes\"\nimport { capitalize } from \"remeda\"\nimport { toPromise } from \"@highstate/pulumi\"\n\nexport async function createDns01Solver(\n dnsProviderInput: Input<dns.Provider>,\n provider: Provider,\n): Promise<types.input.cert_manager.v1.ClusterIssuerSpecAcmeSolversDns01> {\n const dnsProvider = await toPromise(dnsProviderInput)\n\n const implName = `create${capitalize(dnsProvider.type)}Dns01Solver`\n const implModule = (await import(`@highstate/${dnsProvider.type}`)) as Record<string, unknown>\n\n const implFunction = implModule[implName] as (\n dnsProvider: dns.Provider,\n provider: Provider,\n ) => types.input.cert_manager.v1.ClusterIssuerSpecAcmeSolversDns01\n\n return implFunction(dnsProvider, provider)\n}\n"],"mappings":";;;;;AAAA,SAAS,WAAW;AACpB,SAAS,SAAS,gBAAgB;AAClC,SAAS,oBAAoB;;;ACE7B,SAAS,kBAAkB;AAC3B,SAAS,iBAAiB;AAE1B,eAAsB,kBACpB,kBACAA,WACwE;AACxE,QAAM,cAAc,MAAM,UAAU,gBAAgB;AAEpD,QAAM,WAAW,SAAS,WAAW,YAAY,IAAI,CAAC;AACtD,QAAM,aAAc,MAAM,OAAO,cAAc,YAAY,IAAI;AAE/D,QAAM,eAAe,WAAW,QAAQ;AAKxC,SAAO,aAAa,aAAaA,SAAQ;AAC3C;;;ADhBA,IAAM,EAAE,MAAM,QAAQ,QAAQ,IAAI,QAAQ,IAAI,cAAc;AAE5D,IAAM,WAAW,MAAM,YAAY,OAAO,UAAU;AAEpD,IAAI,aAAa,GAAG;AAAA,EAClB;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR;AAAA,IACF;AAAA,IACA,MAAM;AAAA,MACJ,MAAM;AAAA,QACJ,QAAQ;AAAA,QACR,SAAS,OAAO,aAAa;AAAA,UAAM,kBACjC,aAAa,IAAI,iBAAe;AAC9B,mBAAO;AAAA,cACL,OAAO,kBAAkB,aAAa,QAAQ;AAAA,cAC9C,UAAU,EAAE,UAAU,CAAC,YAAY,MAAM,EAAE;AAAA,YAC7C;AAAA,UACF,CAAC;AAAA,QACH;AAAA,QACA,qBAAqB;AAAA,UACnB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,EAAE,SAAS;AACb;AAEA,IAAO,uBAAQ,QAAQ;AAAA,EACrB,WAAW;AAAA,IACT,aAAa,SAAS,OAAO,WAAW,IAAI;AAAA,IAC5C,mBAAmB;AAAA,EACrB;AACF,CAAC;","names":["provider"]}
@@ -27,14 +27,19 @@ var existing_cluster_default = outputs({
27
27
  id: kubeSystem.metadata.uid,
28
28
  name,
29
29
  cni,
30
- externalIps
30
+ externalIps,
31
+ tunDevicePolicy: args.tunDevicePolicy
31
32
  },
32
33
  kubeconfig: secret(kubeconfigContent)
33
34
  },
34
35
  $terminals: [createK8sTerminal(kubeconfigContent)],
35
36
  $status: {
36
37
  clusterId: kubeSystem.metadata.uid,
37
- cni: cni ?? "unknown"
38
+ cni: cni ?? "unknown",
39
+ externalIps: {
40
+ value: externalIps.join(", "),
41
+ complementaryTo: "externalIps"
42
+ }
38
43
  }
39
44
  });
40
45
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/units/existing-cluster/index.ts"],"sourcesContent":["import { k8s } from \"@highstate/library\"\nimport { forUnit, secret, toPromise } from \"@highstate/pulumi\"\nimport { core, Provider } from \"@pulumi/kubernetes\"\nimport { KubeConfig, AppsV1Api } from \"@kubernetes/client-node\"\nimport { createK8sTerminal, detectExternalIps } from \"../../cluster\"\n\nconst { name, args, secrets, outputs } = forUnit(k8s.existingCluster)\n\nconst kubeconfigContent = await toPromise(secrets.kubeconfig.apply(JSON.stringify))\n\nconst provider = new Provider(name, { kubeconfig: kubeconfigContent })\n\nlet cni: string | undefined\n\nconst kubeConfig = new KubeConfig()\nkubeConfig.loadFromString(kubeconfigContent)\n\nconst appsApi = kubeConfig.makeApiClient(AppsV1Api)\n\nconst isCilium = await appsApi\n .readNamespacedDaemonSet({ name: \"cilium\", namespace: \"kube-system\" })\n .then(() => true)\n .catch(() => false)\n\nif (isCilium) {\n cni = \"cilium\"\n}\n\nconst externalIps = await detectExternalIps(kubeConfig, args.internalIpsPolicy)\n\nconst kubeSystem = core.v1.Namespace.get(\"kube-system\", \"kube-system\", { provider })\n\nexport default outputs({\n cluster: {\n info: {\n id: kubeSystem.metadata.uid,\n name,\n cni,\n externalIps,\n },\n kubeconfig: secret(kubeconfigContent),\n },\n\n $terminals: [createK8sTerminal(kubeconfigContent)],\n\n $status: {\n clusterId: kubeSystem.metadata.uid,\n cni: cni ?? \"unknown\",\n },\n})\n"],"mappings":";;;;;;AAAA,SAAS,WAAW;AACpB,SAAS,SAAS,QAAQ,iBAAiB;AAC3C,SAAS,MAAM,gBAAgB;AAC/B,SAAS,YAAY,iBAAiB;AAGtC,IAAM,EAAE,MAAM,MAAM,SAAS,QAAQ,IAAI,QAAQ,IAAI,eAAe;AAEpE,IAAM,oBAAoB,MAAM,UAAU,QAAQ,WAAW,MAAM,KAAK,SAAS,CAAC;AAElF,IAAM,WAAW,IAAI,SAAS,MAAM,EAAE,YAAY,kBAAkB,CAAC;AAErE,IAAI;AAEJ,IAAM,aAAa,IAAI,WAAW;AAClC,WAAW,eAAe,iBAAiB;AAE3C,IAAM,UAAU,WAAW,cAAc,SAAS;AAElD,IAAM,WAAW,MAAM,QACpB,wBAAwB,EAAE,MAAM,UAAU,WAAW,cAAc,CAAC,EACpE,KAAK,MAAM,IAAI,EACf,MAAM,MAAM,KAAK;AAEpB,IAAI,UAAU;AACZ,QAAM;AACR;AAEA,IAAM,cAAc,MAAM,kBAAkB,YAAY,KAAK,iBAAiB;AAE9E,IAAM,aAAa,KAAK,GAAG,UAAU,IAAI,eAAe,eAAe,EAAE,SAAS,CAAC;AAEnF,IAAO,2BAAQ,QAAQ;AAAA,EACrB,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,IAAI,WAAW,SAAS;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACA,YAAY,OAAO,iBAAiB;AAAA,EACtC;AAAA,EAEA,YAAY,CAAC,kBAAkB,iBAAiB,CAAC;AAAA,EAEjD,SAAS;AAAA,IACP,WAAW,WAAW,SAAS;AAAA,IAC/B,KAAK,OAAO;AAAA,EACd;AACF,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../../src/units/existing-cluster/index.ts"],"sourcesContent":["import { k8s } from \"@highstate/library\"\nimport { forUnit, secret, toPromise } from \"@highstate/pulumi\"\nimport { core, Provider } from \"@pulumi/kubernetes\"\nimport { KubeConfig, AppsV1Api } from \"@kubernetes/client-node\"\nimport { createK8sTerminal, detectExternalIps } from \"../../cluster\"\n\nconst { name, args, secrets, outputs } = forUnit(k8s.existingCluster)\n\nconst kubeconfigContent = await toPromise(secrets.kubeconfig.apply(JSON.stringify))\n\nconst provider = new Provider(name, { kubeconfig: kubeconfigContent })\n\nlet cni: string | undefined\n\nconst kubeConfig = new KubeConfig()\nkubeConfig.loadFromString(kubeconfigContent)\n\nconst appsApi = kubeConfig.makeApiClient(AppsV1Api)\n\nconst isCilium = await appsApi\n .readNamespacedDaemonSet({ name: \"cilium\", namespace: \"kube-system\" })\n .then(() => true)\n .catch(() => false)\n\nif (isCilium) {\n cni = \"cilium\"\n}\n\nconst externalIps = await detectExternalIps(kubeConfig, args.internalIpsPolicy)\n\nconst kubeSystem = core.v1.Namespace.get(\"kube-system\", \"kube-system\", { provider })\n\nexport default outputs({\n cluster: {\n info: {\n id: kubeSystem.metadata.uid,\n name,\n cni,\n externalIps,\n tunDevicePolicy: args.tunDevicePolicy,\n },\n kubeconfig: secret(kubeconfigContent),\n },\n\n $terminals: [createK8sTerminal(kubeconfigContent)],\n\n $status: {\n clusterId: kubeSystem.metadata.uid,\n cni: cni ?? \"unknown\",\n externalIps: {\n value: externalIps.join(\", \"),\n complementaryTo: \"externalIps\",\n },\n },\n})\n"],"mappings":";;;;;;AAAA,SAAS,WAAW;AACpB,SAAS,SAAS,QAAQ,iBAAiB;AAC3C,SAAS,MAAM,gBAAgB;AAC/B,SAAS,YAAY,iBAAiB;AAGtC,IAAM,EAAE,MAAM,MAAM,SAAS,QAAQ,IAAI,QAAQ,IAAI,eAAe;AAEpE,IAAM,oBAAoB,MAAM,UAAU,QAAQ,WAAW,MAAM,KAAK,SAAS,CAAC;AAElF,IAAM,WAAW,IAAI,SAAS,MAAM,EAAE,YAAY,kBAAkB,CAAC;AAErE,IAAI;AAEJ,IAAM,aAAa,IAAI,WAAW;AAClC,WAAW,eAAe,iBAAiB;AAE3C,IAAM,UAAU,WAAW,cAAc,SAAS;AAElD,IAAM,WAAW,MAAM,QACpB,wBAAwB,EAAE,MAAM,UAAU,WAAW,cAAc,CAAC,EACpE,KAAK,MAAM,IAAI,EACf,MAAM,MAAM,KAAK;AAEpB,IAAI,UAAU;AACZ,QAAM;AACR;AAEA,IAAM,cAAc,MAAM,kBAAkB,YAAY,KAAK,iBAAiB;AAE9E,IAAM,aAAa,KAAK,GAAG,UAAU,IAAI,eAAe,eAAe,EAAE,SAAS,CAAC;AAEnF,IAAO,2BAAQ,QAAQ;AAAA,EACrB,SAAS;AAAA,IACP,MAAM;AAAA,MACJ,IAAI,WAAW,SAAS;AAAA,MACxB;AAAA,MACA;AAAA,MACA;AAAA,MACA,iBAAiB,KAAK;AAAA,IACxB;AAAA,IACA,YAAY,OAAO,iBAAiB;AAAA,EACtC;AAAA,EAEA,YAAY,CAAC,kBAAkB,iBAAiB,CAAC;AAAA,EAEjD,SAAS;AAAA,IACP,WAAW,WAAW,SAAS;AAAA,IAC/B,KAAK,OAAO;AAAA,IACZ,aAAa;AAAA,MACX,OAAO,YAAY,KAAK,IAAI;AAAA,MAC5B,iBAAiB;AAAA,IACnB;AAAA,EACF;AACF,CAAC;","names":[]}
@@ -0,0 +1,24 @@
1
+ import {
2
+ getProvider
3
+ } from "../../chunk-T5Z2M4JE.js";
4
+
5
+ // src/units/gateway-api/index.ts
6
+ import { k8s } from "@highstate/library";
7
+ import { forUnit } from "@highstate/pulumi";
8
+ import { yaml } from "@pulumi/kubernetes";
9
+ var { inputs, outputs } = forUnit(k8s.gatewayApi);
10
+ var provider = await getProvider(inputs.k8sCluster);
11
+ new yaml.v2.ConfigFile(
12
+ "gateway-api",
13
+ {
14
+ file: "https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml"
15
+ },
16
+ { provider }
17
+ );
18
+ var gateway_api_default = outputs({
19
+ k8sCluster: inputs.k8sCluster
20
+ });
21
+ export {
22
+ gateway_api_default as default
23
+ };
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/units/gateway-api/index.ts"],"sourcesContent":["import { k8s } from \"@highstate/library\"\nimport { forUnit } from \"@highstate/pulumi\"\nimport { yaml } from \"@pulumi/kubernetes\"\nimport { getProvider } from \"../../shared\"\n\nconst { inputs, outputs } = forUnit(k8s.gatewayApi)\n\nconst provider = await getProvider(inputs.k8sCluster)\n\nnew yaml.v2.ConfigFile(\n \"gateway-api\",\n {\n file: \"https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml\",\n },\n { provider },\n)\n\nexport default outputs({\n k8sCluster: inputs.k8sCluster,\n})\n"],"mappings":";;;;;AAAA,SAAS,WAAW;AACpB,SAAS,eAAe;AACxB,SAAS,YAAY;AAGrB,IAAM,EAAE,QAAQ,QAAQ,IAAI,QAAQ,IAAI,UAAU;AAElD,IAAM,WAAW,MAAM,YAAY,OAAO,UAAU;AAEpD,IAAI,KAAK,GAAG;AAAA,EACV;AAAA,EACA;AAAA,IACE,MAAM;AAAA,EACR;AAAA,EACA,EAAE,SAAS;AACb;AAEA,IAAO,sBAAQ,QAAQ;AAAA,EACrB,YAAY,OAAO;AACrB,CAAC;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@highstate/k8s",
3
- "version": "0.7.11",
3
+ "version": "0.9.0",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -14,7 +14,8 @@
14
14
  "./units/access-point": "./dist/units/access-point/index.js",
15
15
  "./units/cert-manager": "./dist/units/cert-manager/index.js",
16
16
  "./units/dns01-issuer": "./dist/units/dns01-issuer/index.js",
17
- "./units/existing-cluster": "./dist/units/existing-cluster/index.js"
17
+ "./units/existing-cluster": "./dist/units/existing-cluster/index.js",
18
+ "./units/gateway-api": "./dist/units/gateway-api/index.js"
18
19
  },
19
20
  "publishConfig": {
20
21
  "access": "public"
@@ -25,11 +26,11 @@
25
26
  "generate-crds": "./scripts/generate-crds.sh"
26
27
  },
27
28
  "dependencies": {
28
- "@highstate/cert-manager": "^0.7.11",
29
- "@highstate/common": "^0.7.11",
30
- "@highstate/contract": "^0.7.11",
31
- "@highstate/gateway-api": "^0.7.11",
32
- "@highstate/pulumi": "^0.7.11",
29
+ "@highstate/cert-manager": "^0.9.0",
30
+ "@highstate/common": "^0.9.0",
31
+ "@highstate/contract": "^0.9.0",
32
+ "@highstate/gateway-api": "^0.9.0",
33
+ "@highstate/pulumi": "^0.9.0",
33
34
  "@kubernetes/client-node": "^1.1.0",
34
35
  "@pulumi/command": "^1.0.2",
35
36
  "@pulumi/kubernetes": "^4.18.0",
@@ -45,7 +46,7 @@
45
46
  "@highstate/library": "workspace:^0.4.4"
46
47
  },
47
48
  "devDependencies": {
48
- "@highstate/cli": "^0.7.11"
49
+ "@highstate/cli": "^0.9.0"
49
50
  },
50
- "gitHead": "f425f2be2d5800fdee3512c848129adab1b0186e"
51
+ "gitHead": "b64df0df33afcadf019936eaa2a2ca7ffc82940b"
51
52
  }
@@ -45,9 +45,9 @@ export function useAccessPoint(args: UseAccessPointArgs): Promise<UseAccessPoint
45
45
  gateway: args.accessPoint.gateway,
46
46
  })
47
47
 
48
- const dnsRecords = normalize(args.fqdn, args.fqdns).map(fqdn => {
49
- return DnsRecord.create(fqdn, {
50
- provider: args.accessPoint.dnsProvider,
48
+ const dnsRecords = normalize(args.fqdn, args.fqdns).flatMap(fqdn => {
49
+ return DnsRecord.createSet(fqdn, {
50
+ providers: args.accessPoint.dnsProviders,
51
51
  type: "A",
52
52
  value: args.accessPoint.gateway.ip,
53
53
  })
@@ -62,8 +62,8 @@ export function useAccessPoint(args: UseAccessPointArgs): Promise<UseAccessPoint
62
62
  NetworkPolicy.create(
63
63
  `allow-ingress-from-${getAppName(args.accessPoint.gateway.service.metadata)}`,
64
64
  {
65
- cni: args.accessPoint.gateway.service.clusterInfo.cni,
66
65
  namespace: args.namespace,
66
+ cluster: args.cluster,
67
67
 
68
68
  description: `Allow ingress traffic from the gateway "${displayName}".`,
69
69
 
@@ -78,8 +78,9 @@ export function useAccessPoint(args: UseAccessPointArgs): Promise<UseAccessPoint
78
78
  NetworkPolicy.create(
79
79
  `allow-egress-to-${namespaceName}`,
80
80
  {
81
- cni: args.accessPoint.gateway.service.clusterInfo.cni,
82
81
  namespace: args.accessPoint.gateway.service.metadata.namespace,
82
+ cluster: args.cluster,
83
+
83
84
  selector: args.accessPoint.gateway.service.spec.selector,
84
85
 
85
86
  description: `Allow egress traffic to the namespace "${namespaceName}".`,
@@ -95,7 +96,7 @@ export function useAccessPoint(args: UseAccessPointArgs): Promise<UseAccessPoint
95
96
 
96
97
  return output({
97
98
  gateway,
98
- dnsRecords,
99
+ dnsRecords: output(dnsRecords).apply(records => records.flat()),
99
100
  networkPolicies,
100
101
  })
101
102
  },
@@ -127,7 +128,7 @@ export function useStandardAcessPoint(
127
128
  fqdn: args.fqdn,
128
129
 
129
130
  accessPoint: inputs.accessPoint,
130
- clusterInfo: inputs.k8sCluster.info,
131
+ cluster: inputs.k8sCluster,
131
132
  provider,
132
133
  })
133
134
  }
@@ -141,13 +142,13 @@ export type CreateGatewayArgs = {
141
142
  fqdns?: InputArray<string>
142
143
 
143
144
  gateway: Input<k8s.Gateway>
144
- clusterInfo: Input<k8s.ClusterInfo>
145
+ cluster: Input<k8s.Cluster>
145
146
  provider: Provider
146
147
  }
147
148
 
148
149
  export function createGateway(args: CreateGatewayArgs): Output<gateway.v1.Gateway> {
149
150
  return output(args).apply(args => {
150
- if (args.clusterInfo.id !== args.gateway.clusterInfo.id) {
151
+ if (args.cluster.info.id !== args.gateway.clusterInfo.id) {
151
152
  throw new Error(
152
153
  "The provided Kubernetes cluster is different from the one where the gateway controller is deployed.",
153
154
  )
package/src/index.ts CHANGED
@@ -22,7 +22,6 @@ export {
22
22
  export { type StatefulSetArgs, StatefulSet } from "./stateful-set"
23
23
  export {
24
24
  type NetworkPolicyArgs,
25
- type FullNetworkPolicyArgs,
26
25
  type NormalizedNetworkPolicyArgs,
27
26
  type NormalizedRuleArgs,
28
27
  type NetworkPolicyPort,
@@ -310,14 +310,11 @@ export type NetworkPolicyArgs = CommonArgs & {
310
310
  * By default, `false`.
311
311
  */
312
312
  allowKubeDns?: Input<boolean>
313
- }
314
313
 
315
- export type FullNetworkPolicyArgs = NetworkPolicyArgs & {
316
314
  /**
317
- * The name of the CNI plugin to use for creating network policies.
318
- * If not provided or set to `unknown`, it will use the native `NetworkPolicy` resource.
315
+ * The cluster to create the network policy in.
319
316
  */
320
- cni?: Input<string | undefined>
317
+ cluster: Input<k8s.Cluster>
321
318
  }
322
319
 
323
320
  export type NormalizedRuleArgs = {
@@ -460,16 +457,18 @@ export abstract class NetworkPolicy extends ComponentResource {
460
457
 
461
458
  static create(
462
459
  name: string,
463
- args: FullNetworkPolicyArgs,
460
+ args: NetworkPolicyArgs,
464
461
  opts: ResourceOptions,
465
462
  ): Output<NetworkPolicy> {
466
463
  return output(args).apply(async args => {
467
- if (!args.cni || !NetworkPolicy.supportedCNIs.includes(args.cni)) {
464
+ const cni = args.cluster.info.cni
465
+
466
+ if (!cni || !NetworkPolicy.supportedCNIs.includes(cni)) {
468
467
  return new NativeNetworkPolicy(name, args, opts)
469
468
  }
470
469
 
471
- const implName = `${capitalize(args.cni)}NetworkPolicy`
472
- const implModule = (await import(`@highstate/${args.cni}`)) as Record<string, unknown>
470
+ const implName = `${capitalize(cni)}NetworkPolicy`
471
+ const implModule = (await import(`@highstate/${cni}`)) as Record<string, unknown>
473
472
 
474
473
  type NetworkPolicyFactory = new (
475
474
  name: string,
@@ -479,7 +478,7 @@ export abstract class NetworkPolicy extends ComponentResource {
479
478
 
480
479
  const implClass = implModule[implName] as NetworkPolicyFactory | undefined
481
480
  if (!implClass) {
482
- throw new Error(`No implementation found for ${args.cni}`)
481
+ throw new Error(`No implementation found for ${cni}`)
483
482
  }
484
483
 
485
484
  return new implClass(name, args, opts)
@@ -488,14 +487,14 @@ export abstract class NetworkPolicy extends ComponentResource {
488
487
 
489
488
  static allowInsideNamespace(
490
489
  namespace: Input<NamespaceLike>,
491
- k8sCluster: Input<k8s.Cluster>,
490
+ cluster: Input<k8s.Cluster>,
492
491
  opts: ResourceOptions,
493
492
  ): Output<NetworkPolicy> {
494
493
  return NetworkPolicy.create(
495
494
  "allow-inside-namespace",
496
495
  {
497
496
  namespace,
498
- cni: output(k8sCluster).info.cni,
497
+ cluster,
499
498
 
500
499
  description: "Allow all traffic inside the namespace.",
501
500
  selector: {},
@@ -509,14 +508,14 @@ export abstract class NetworkPolicy extends ComponentResource {
509
508
 
510
509
  static allowKubeApiServer(
511
510
  namespace: Input<NamespaceLike>,
512
- k8sCluster: Input<k8s.Cluster>,
511
+ cluster: Input<k8s.Cluster>,
513
512
  opts: ResourceOptions,
514
513
  ): Output<NetworkPolicy> {
515
514
  return NetworkPolicy.create(
516
515
  "allow-kube-api-server",
517
516
  {
518
517
  namespace,
519
- cni: output(k8sCluster).info.cni,
518
+ cluster,
520
519
 
521
520
  description: "Allow all traffic to the Kubernetes API server from the namespace.",
522
521
 
@@ -528,14 +527,14 @@ export abstract class NetworkPolicy extends ComponentResource {
528
527
 
529
528
  static allowKubeDns(
530
529
  namespace: Input<NamespaceLike>,
531
- k8sCluster: Input<k8s.Cluster>,
530
+ cluster: Input<k8s.Cluster>,
532
531
  opts: ResourceOptions,
533
532
  ): Output<NetworkPolicy> {
534
533
  return NetworkPolicy.create(
535
534
  "allow-kube-dns",
536
535
  {
537
536
  namespace,
538
- cni: output(k8sCluster).info.cni,
537
+ cluster,
539
538
 
540
539
  description: "Allow all traffic to the Kubernetes DNS server from the namespace.",
541
540
 
@@ -547,14 +546,14 @@ export abstract class NetworkPolicy extends ComponentResource {
547
546
 
548
547
  static allowAllEgress(
549
548
  namespace: Input<NamespaceLike>,
550
- k8sCluster: Input<k8s.Cluster>,
549
+ cluster: Input<k8s.Cluster>,
551
550
  opts: ResourceOptions,
552
551
  ): Output<NetworkPolicy> {
553
552
  return NetworkPolicy.create(
554
553
  "allow-all-egress",
555
554
  {
556
555
  namespace,
557
- cni: output(k8sCluster).info.cni,
556
+ cluster,
558
557
 
559
558
  description: "Allow all egress traffic from the namespace.",
560
559
 
@@ -630,8 +629,13 @@ export class NativeNetworkPolicy extends NetworkPolicy {
630
629
  const extraRules: types.input.networking.v1.NetworkPolicyEgressRule[] = []
631
630
 
632
631
  if (args.allowKubeApiServer) {
633
- // TODO: the "10.96.0.1" is not guaranteed to be the API server
634
- extraRules.push({ to: [{ ipBlock: { cidr: "10.96.0.1" } }] })
632
+ const apiServerIp = args.cluster.info.kubeApiServerIp ?? "10.96.0.1"
633
+ const apiServerPort = args.cluster.info.kubeApiServerPort ?? 443
634
+
635
+ extraRules.push({
636
+ to: [{ ipBlock: { cidr: `${apiServerIp}/32` } }],
637
+ ports: [{ port: apiServerPort, protocol: "TCP" }],
638
+ })
635
639
  }
636
640
 
637
641
  return args.egressRules
@@ -5,7 +5,7 @@ const { inputs, outputs } = forUnit(k8s.accessPoint)
5
5
 
6
6
  export default outputs({
7
7
  accessPoint: {
8
- dnsProvider: inputs.dnsProvider,
8
+ dnsProviders: inputs.dnsProviders,
9
9
  gateway: inputs.gateway,
10
10
  tlsIssuer: inputs.tlsIssuer,
11
11
  },
@@ -7,7 +7,6 @@ import { createDns01Solver } from "./solver"
7
7
  const { name, inputs, outputs } = forUnit(k8s.dns01TlsIssuer)
8
8
 
9
9
  const provider = await getProvider(inputs.k8sCluster)
10
- const dns01Solver = await createDns01Solver(inputs.dnsProvider, provider)
11
10
 
12
11
  new cert_manager.v1.ClusterIssuer(
13
12
  name,
@@ -18,12 +17,14 @@ new cert_manager.v1.ClusterIssuer(
18
17
  spec: {
19
18
  acme: {
20
19
  server: "https://acme-v02.api.letsencrypt.org/directory",
21
- solvers: [
22
- {
23
- dns01: dns01Solver,
24
- selector: { dnsZones: [inputs.dnsProvider.domain] },
25
- },
26
- ],
20
+ solvers: inputs.dnsProviders.apply(dnsProviders =>
21
+ dnsProviders.map(dnsProvider => {
22
+ return {
23
+ dns01: createDns01Solver(dnsProvider, provider),
24
+ selector: { dnsZones: [dnsProvider.domain] },
25
+ }
26
+ }),
27
+ ),
27
28
  privateKeySecretRef: {
28
29
  name,
29
30
  },
@@ -37,6 +37,7 @@ export default outputs({
37
37
  name,
38
38
  cni,
39
39
  externalIps,
40
+ tunDevicePolicy: args.tunDevicePolicy,
40
41
  },
41
42
  kubeconfig: secret(kubeconfigContent),
42
43
  },
@@ -46,5 +47,9 @@ export default outputs({
46
47
  $status: {
47
48
  clusterId: kubeSystem.metadata.uid,
48
49
  cni: cni ?? "unknown",
50
+ externalIps: {
51
+ value: externalIps.join(", "),
52
+ complementaryTo: "externalIps",
53
+ },
49
54
  },
50
55
  })
@@ -0,0 +1,20 @@
1
+ import { k8s } from "@highstate/library"
2
+ import { forUnit } from "@highstate/pulumi"
3
+ import { yaml } from "@pulumi/kubernetes"
4
+ import { getProvider } from "../../shared"
5
+
6
+ const { inputs, outputs } = forUnit(k8s.gatewayApi)
7
+
8
+ const provider = await getProvider(inputs.k8sCluster)
9
+
10
+ new yaml.v2.ConfigFile(
11
+ "gateway-api",
12
+ {
13
+ file: "https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.3.0/standard-install.yaml",
14
+ },
15
+ { provider },
16
+ )
17
+
18
+ export default outputs({
19
+ k8sCluster: inputs.k8sCluster,
20
+ })