@highstate/k8s 0.9.4 → 0.9.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/dist/chunk-DQSCJM5S.js +183 -0
  2. package/dist/chunk-DQSCJM5S.js.map +1 -0
  3. package/dist/chunk-FKNHHKOL.js +260 -0
  4. package/dist/chunk-FKNHHKOL.js.map +1 -0
  5. package/dist/chunk-HW3NS3MC.js +347 -0
  6. package/dist/chunk-HW3NS3MC.js.map +1 -0
  7. package/dist/chunk-OQ7UXASD.js +193 -0
  8. package/dist/chunk-OQ7UXASD.js.map +1 -0
  9. package/dist/chunk-QGHMLKTW.js +1123 -0
  10. package/dist/chunk-QGHMLKTW.js.map +1 -0
  11. package/dist/chunk-UNVSWG6D.js +214 -0
  12. package/dist/chunk-UNVSWG6D.js.map +1 -0
  13. package/dist/deployment-ZP3ASKPT.js +10 -0
  14. package/dist/deployment-ZP3ASKPT.js.map +1 -0
  15. package/dist/highstate.manifest.json +8 -6
  16. package/dist/index.js +291 -954
  17. package/dist/index.js.map +1 -1
  18. package/dist/stateful-set-2AH7RAF7.js +10 -0
  19. package/dist/stateful-set-2AH7RAF7.js.map +1 -0
  20. package/dist/units/access-point/index.js +6 -1
  21. package/dist/units/access-point/index.js.map +1 -1
  22. package/dist/units/cert-manager/index.js +19 -24
  23. package/dist/units/cert-manager/index.js.map +1 -1
  24. package/dist/units/cluster-dns/index.js +36 -0
  25. package/dist/units/cluster-dns/index.js.map +1 -0
  26. package/dist/units/cluster-patch/index.js +34 -0
  27. package/dist/units/cluster-patch/index.js.map +1 -0
  28. package/dist/units/dns01-issuer/index.js +2 -2
  29. package/dist/units/dns01-issuer/index.js.map +1 -1
  30. package/dist/units/existing-cluster/index.js +22 -14
  31. package/dist/units/existing-cluster/index.js.map +1 -1
  32. package/dist/units/gateway-api/index.js +1 -1
  33. package/package.json +12 -10
  34. package/src/access-point.ts +44 -39
  35. package/src/container.ts +54 -5
  36. package/src/cron-job.ts +14 -30
  37. package/src/deployment.ts +170 -127
  38. package/src/gateway/http-route.ts +7 -5
  39. package/src/helm.ts +57 -8
  40. package/src/index.ts +11 -4
  41. package/src/job.ts +14 -32
  42. package/src/namespace.ts +241 -0
  43. package/src/network-policy.ts +371 -87
  44. package/src/network.ts +41 -0
  45. package/src/pvc.ts +43 -25
  46. package/src/scripting/bundle.ts +125 -22
  47. package/src/scripting/container.ts +16 -11
  48. package/src/scripting/environment.ts +56 -6
  49. package/src/secret.ts +195 -0
  50. package/src/service.ts +209 -89
  51. package/src/shared.ts +42 -51
  52. package/src/stateful-set.ts +193 -88
  53. package/src/units/access-point/index.ts +8 -1
  54. package/src/units/cert-manager/index.ts +15 -20
  55. package/src/units/cluster-dns/index.ts +37 -0
  56. package/src/units/cluster-patch/index.ts +35 -0
  57. package/src/units/dns01-issuer/index.ts +1 -1
  58. package/src/units/existing-cluster/index.ts +24 -14
  59. package/src/workload.ts +342 -44
  60. package/dist/chunk-K4WKJ4L5.js +0 -455
  61. package/dist/chunk-K4WKJ4L5.js.map +0 -1
  62. package/dist/chunk-T5Z2M4JE.js +0 -103
  63. package/dist/chunk-T5Z2M4JE.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/pvc.ts","../src/secret.ts","../src/container.ts","../src/network-policy.ts","../src/workload.ts","../src/pod.ts"],"sourcesContent":["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 getProvider,\n mapMetadata,\n resourceIdToString,\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\nexport type CreateOrGetPersistentVolumeClaimArgs = PersistentVolumeClaimArgs & {\n existing: Input<k8s.PersistentVolumeClaim> | undefined\n}\n\nconst extraPersistentVolumeClaimArgs = [...commonExtraArgs, \"size\"] 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 where the PVC is created.\n */\n readonly cluster: Output<k8s.Cluster>,\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 PVC entity.\n */\n get entity(): Output<k8s.PersistentVolumeClaim> {\n return output({\n type: \"k8s.persistent-volume-claim\",\n clusterId: this.cluster.id,\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 cluster: Input<k8s.Cluster>,\n opts: ComponentResourceOptions,\n ): PersistentVolumeClaim {\n return new ExternalPersistentVolumeClaim(name, output(entity).metadata, cluster, opts)\n }\n\n static createOrGet(\n name: string,\n args: CreateOrGetPersistentVolumeClaimArgs,\n opts: ComponentResourceOptions,\n ): PersistentVolumeClaim {\n if (!args.existing) {\n return new CreatedPersistentVolumeClaim(name, args, opts)\n }\n\n return new ExternalPersistentVolumeClaim(\n name,\n output(args.existing).metadata,\n args.cluster,\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(async 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 {\n ...opts,\n parent: this,\n provider: await getProvider(args.cluster),\n },\n )\n })\n\n super(\n \"k8s:PersistentVolumeClaim\",\n name,\n args,\n opts,\n\n output(args.cluster),\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 cluster: Input<k8s.Cluster>,\n opts: ComponentResourceOptions,\n ) {\n const pvc = output(id).apply(async id => {\n return core.v1.PersistentVolumeClaim.get(\n //\n name,\n resourceIdToString(id),\n {\n ...opts,\n parent: this,\n provider: await getProvider(cluster),\n },\n )\n })\n\n super(\n \"highstate:k8s:ExternalPersistentVolumeClaim\",\n name,\n { id, cluster },\n opts,\n\n output(cluster),\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 { k8s } from \"@highstate/library\"\nimport { core, type types } from \"@pulumi/kubernetes\"\nimport {\n ComponentResource,\n output,\n Output,\n type ComponentResourceOptions,\n type Input,\n type Inputs,\n} from \"@pulumi/pulumi\"\nimport { getProvider, mapMetadata, withPatchName, type CommonArgs } from \"./shared\"\n\nexport type SecretArgs = CommonArgs &\n Omit<types.input.core.v1.Secret, \"kind\" | \"metadata\" | \"apiVersion\">\n\nexport type CreateOrPatchSecretArgs = SecretArgs & {\n /**\n * The resource to use to determine the name of the secret.\n *\n * If not provided, the secret will be created, otherwise it will be retrieved/patched.\n */\n existing: Input<k8s.Resource> | undefined\n}\n\nexport abstract class Secret extends ComponentResource {\n protected constructor(\n type: string,\n name: string,\n args: Inputs,\n opts: ComponentResourceOptions | undefined,\n\n /**\n * The cluster where the secret is created.\n */\n readonly cluster: Output<k8s.Cluster>,\n\n /**\n * The metadata of the underlying Kubernetes secret.\n */\n readonly metadata: Output<types.output.meta.v1.ObjectMeta>,\n\n /**\n * The data of the underlying Kubernetes secret.\n */\n readonly data: Output<Record<string, string>>,\n\n /**\n * The stringData of the underlying Kubernetes secret.\n */\n readonly stringData: Output<Record<string, string>>,\n ) {\n super(type, name, args, opts)\n }\n\n /**\n * Creates a new secret.\n */\n static create(name: string, args: SecretArgs, opts?: ComponentResourceOptions): Secret {\n return new CreatedSecret(name, args, opts)\n }\n\n /**\n * Creates a new secret or patches an existing one.\n *\n * Will throw an error if the secret does not exist when `args.resource` is provided.\n */\n static createOrPatch(\n name: string,\n args: CreateOrPatchSecretArgs,\n opts?: ComponentResourceOptions,\n ): Secret {\n if (!args.existing) {\n return new CreatedSecret(name, args, opts)\n }\n\n return new SecretPatch(\n name,\n {\n ...args,\n name: withPatchName(\"secret\", args.existing, args.cluster),\n namespace: output(args.existing).metadata.namespace,\n },\n opts,\n )\n }\n\n /**\n * Gets an existing secret.\n *\n * Will throw an error if the secret does not exist.\n */\n static get(\n name: string,\n id: Input<string>,\n cluster: Input<k8s.Cluster>,\n opts?: ComponentResourceOptions,\n ): Secret {\n return new ExternalSecret(name, id, cluster, opts)\n }\n}\n\nclass CreatedSecret extends Secret {\n constructor(name: string, args: SecretArgs, opts?: ComponentResourceOptions) {\n const secret = output(args).apply(async args => {\n return new core.v1.Secret(\n name,\n {\n metadata: mapMetadata(args, name),\n data: args.data,\n stringData: args.stringData,\n },\n {\n ...opts,\n parent: this,\n provider: await getProvider(args.cluster),\n },\n )\n })\n\n super(\n \"highstate:k8s:Secret\",\n name,\n args,\n opts,\n output(args.cluster),\n secret.metadata,\n secret.data,\n secret.stringData,\n )\n }\n}\n\nclass SecretPatch extends Secret {\n constructor(name: string, args: SecretArgs, opts?: ComponentResourceOptions) {\n const secret = output(args).apply(async args => {\n return new core.v1.SecretPatch(\n name,\n {\n metadata: mapMetadata(args, name),\n data: args.data,\n stringData: args.stringData,\n },\n {\n ...opts,\n parent: this,\n provider: await getProvider(args.cluster),\n },\n )\n })\n\n super(\n \"highstate:k8s:SecretPatch\",\n name,\n args,\n opts,\n output(args.cluster),\n secret.metadata,\n secret.data,\n secret.stringData,\n )\n }\n}\n\nclass ExternalSecret extends Secret {\n constructor(\n name: string,\n id: Input<string>,\n cluster: Input<k8s.Cluster>,\n opts?: ComponentResourceOptions,\n ) {\n const secret = output(id).apply(async realName => {\n return core.v1.Secret.get(\n //\n name,\n realName,\n {\n ...opts,\n parent: this,\n provider: await getProvider(cluster),\n },\n )\n })\n\n super(\n \"highstate:k8s:ExternalSecret\",\n name,\n { id, cluster },\n opts,\n output(cluster),\n secret.metadata,\n secret.data,\n secret.stringData,\n )\n }\n}\n","import type { PartialKeys } from \"@highstate/contract\"\nimport type { k8s, network } from \"@highstate/library\"\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\"\nimport { Secret } from \"./secret\"\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 /**\n * The list of endpoints that the container is allowed to access.\n *\n * This is used to generate a network policy.\n */\n allowedEndpoints?: InputArray<network.L34Endpoint>\n\n /**\n * Enable the TUN device in the container.\n *\n * All necessary security context settings will be applied to the container.\n */\n enableTun?: Input<boolean>\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 | 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 | Secret\n | core.v1.ConfigMap\n | core.v1.Secret\n\nexport function mapContainerToRaw(\n container: Unwrap<Container>,\n cluster: k8s.Cluster,\n fallbackName: string,\n): types.input.core.v1.Container {\n const containerName = container.name ?? fallbackName\n\n const spec = {\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 } as Unwrap<types.input.core.v1.Container>\n\n if (container.enableTun) {\n spec.securityContext ??= {}\n spec.securityContext.capabilities ??= {}\n spec.securityContext.capabilities.add = [\"NET_ADMIN\"]\n\n if (cluster.quirks?.tunDevicePolicy?.type === \"plugin\") {\n spec.resources ??= {}\n spec.resources.limits ??= {}\n spec.resources.limits[cluster.quirks.tunDevicePolicy.resourceName] =\n cluster.quirks.tunDevicePolicy.resourceValue\n } else {\n spec.volumeMounts ??= []\n spec.volumeMounts.push({\n name: \"tun-device\",\n mountPath: \"/dev/net/tun\",\n readOnly: false,\n })\n }\n }\n\n return spec\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 Secret) {\n return {\n name: volume.metadata.name,\n secret: {\n secretName: volume.metadata.name,\n },\n }\n }\n\n if (core.v1.PersistentVolumeClaim.isInstance(volume)) {\n return {\n name: volume.metadata.name,\n persistentVolumeClaim: {\n claimName: volume.metadata.name,\n },\n }\n }\n\n if (core.v1.ConfigMap.isInstance(volume)) {\n return {\n name: volume.metadata.name,\n configMap: {\n name: volume.metadata.name,\n },\n }\n }\n\n if (core.v1.Secret.isInstance(volume)) {\n return {\n name: volume.metadata.name,\n secret: {\n secretName: volume.metadata.name,\n },\n }\n }\n\n return volume\n}\n","import { networking, types, type core } from \"@pulumi/kubernetes\"\nimport {\n ComponentResource,\n interpolate,\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, groupBy, merge, mergeDeep, uniqueBy } from \"remeda\"\nimport { k8s, network } from \"@highstate/library\"\nimport {\n l34EndpointToString,\n l3EndpointToCidr,\n parseL34Endpoint,\n type InputL34Endpoint,\n} from \"@highstate/common\"\nimport {\n getProvider,\n mapMetadata,\n mapNamespaceLikeToNamespaceName,\n mapNamespaceNameToSelector,\n mapSelectorLikeToSelector,\n type CommonArgs,\n type NamespaceLike,\n type SelectorLike,\n} from \"./shared\"\nimport { getServiceMetadata, isFromCluster, 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 | string\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 list of allowed L3 or L4 endpoints for outgoing traffic.\n *\n * Just a syntactic sugar for `fromFqdn` and `fromService` for cases when the endpoint can be one of them + optional port/protocol.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n *\n * If a single endpoint also has a port/protocol/service metadata,\n * it will produce separate rule for it with them and ORed with the rest of the rules.\n */\n fromEndpoint?: Input<InputL34Endpoint>\n\n /**\n * The list of allowed L3 or L4 endpoints for incoming traffic.\n *\n * Just a syntactic sugar for `fromFqdn` and `fromService` for cases when the endpoint can be one of them + optional port/protocol.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n *\n * If a single endpoint also has a port/protocol/service metadata,\n * it will produce separate rule for it with them and ORed with the rest of the rules.\n */\n fromEndpoints?: InputArray<InputL34Endpoint>\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 * The L3 or L4 endpoint to allow outgoing traffic.\n *\n * Just a syntactic sugar for `toFqdn`, `toCidr` and `toService` for cases when the endpoint can be one of them + optional port/protocol.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n *\n * If a single endpoint also has a port/protocol/service metadata,\n * it will produce separate rule for it with them and ORed with the rest of the rules.\n */\n toEndpoint?: Input<InputL34Endpoint>\n\n /**\n * The list of allowed L3 or L4 endpoints for outgoing traffic.\n *\n * Just a syntactic sugar for `toFqdn`, `toCidr` and `toService` for cases when the endpoint can be one of them + optional port/protocol.\n *\n * Will be ORed with other conditions inside the same rule (except ports).\n *\n * If a single endpoint also has a port/protocol/service metadata,\n * it will produce separate rule for it with them and ORed with the rest of the rules.\n */\n toEndpoints?: InputArray<InputL34Endpoint>\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 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.flatMap(rule => {\n const endpoints = normalize(\n args.ingressRule?.fromEndpoint,\n args.ingressRule?.fromEndpoints,\n )\n const parsedEndpoints = endpoints.map(parseL34Endpoint)\n\n const endpointsByPortsAndNamespaces = groupBy(parsedEndpoints, endpoint => {\n const namespace = isFromCluster(endpoint, args.cluster)\n ? endpoint.metadata.k8sService.namespace\n : \"\"\n\n const port = isFromCluster(endpoint, args.cluster)\n ? endpoint.metadata.k8sService.targetPort\n : endpoint.port\n\n return `${port ?? \"0\"}:${namespace}`\n })\n\n const l3OnlyRule = endpointsByPortsAndNamespaces[\"0:\"]\n ? NetworkPolicy.getRuleFromEndpoint(\n undefined,\n endpointsByPortsAndNamespaces[\"0:\"],\n args.cluster,\n )\n : undefined\n\n const otherRules = Object.entries(endpointsByPortsAndNamespaces)\n .filter(([key]) => key !== \"0:\")\n .map(([key, endpoints]) => {\n const [port] = key.split(\":\")\n const portNumber = parseInt(port, 10)\n const portValue = isNaN(portNumber) ? port : portNumber\n\n return NetworkPolicy.getRuleFromEndpoint(portValue, endpoints, args.cluster)\n })\n\n return [\n {\n all: rule.fromAll ?? false,\n cidrs: normalize(rule.fromCidr, rule.fromCidrs).concat(l3OnlyRule?.cidrs ?? []),\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 } as NormalizedRuleArgs,\n\n ...otherRules,\n ].filter(rule => !NetworkPolicy.isEmptyRule(rule))\n }),\n\n egressRules: egressRules\n .flatMap(rule => {\n const endpoints = normalize(args.egressRule?.toEndpoint, args.egressRule?.toEndpoints)\n const parsedEndpoints = endpoints.map(parseL34Endpoint)\n\n const endpointsByPortsAnsNamespaces = groupBy(parsedEndpoints, endpoint => {\n const namespace = isFromCluster(endpoint, args.cluster)\n ? endpoint.metadata.k8sService.namespace\n : \"\"\n\n const port = isFromCluster(endpoint, args.cluster)\n ? endpoint.metadata.k8sService.targetPort\n : endpoint.port\n\n return `${port ?? \"0\"}:${namespace}`\n })\n\n const l3OnlyRule = endpointsByPortsAnsNamespaces[\"0:\"]\n ? NetworkPolicy.getRuleFromEndpoint(\n undefined,\n endpointsByPortsAnsNamespaces[\"0:\"],\n args.cluster,\n )\n : undefined\n\n const otherRules = Object.entries(endpointsByPortsAnsNamespaces)\n .filter(([key]) => key !== \"0:\")\n .map(([key, endpoints]) => {\n const [port] = key.split(\":\")\n const portNumber = parseInt(port, 10)\n const portValue = isNaN(portNumber) ? port : portNumber\n\n return NetworkPolicy.getRuleFromEndpoint(portValue, endpoints, args.cluster)\n })\n\n return [\n {\n all: rule.toAll ?? false,\n cidrs: normalize(rule.toCidr, rule.toCidrs).concat(l3OnlyRule?.cidrs ?? []),\n fqdns: normalize(rule.toFqdn, rule.toFqdns).concat(l3OnlyRule?.fqdns ?? []),\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 ...otherRules,\n ].filter(rule => !NetworkPolicy.isEmptyRule(rule))\n })\n .concat(extraEgressRules),\n }\n })\n\n this.networkPolicy = output(\n normalizedArgs.apply(async args => {\n return output(\n this.create(name, args as NormalizedNetworkPolicyArgs, {\n ...opts,\n parent: this,\n provider: await getProvider(args.cluster),\n }),\n )\n }),\n )\n }\n\n private static mapCidrFromEndpoint(\n this: void,\n result: network.L3Endpoint & { type: \"ipv4\" | \"ipv6\" },\n ): string {\n if (result.type === \"ipv4\") {\n return `${result.address}/32`\n }\n\n return `${result.address}/128`\n }\n\n private static getRuleFromEndpoint(\n port: number | string | undefined,\n endpoints: network.L34Endpoint[],\n cluster: k8s.Cluster,\n ): NormalizedRuleArgs {\n const ports: NetworkPolicyPort[] = port\n ? [{ port, protocol: endpoints[0].protocol?.toUpperCase() }]\n : []\n\n const cidrs = endpoints\n .filter(endpoint => !isFromCluster(endpoint, cluster))\n .filter(endpoint => endpoint.type === \"ipv4\" || endpoint.type === \"ipv6\")\n .map(NetworkPolicy.mapCidrFromEndpoint)\n\n const fqdns = endpoints\n .filter(endpoint => endpoint.type === \"hostname\")\n .map(endpoint => endpoint.hostname)\n\n const selectors = endpoints\n .filter(endpoint => isFromCluster(endpoint, cluster))\n .map(endpoint => endpoint.metadata.k8sService.selector)\n\n const namespace = endpoints\n .filter(endpoint => isFromCluster(endpoint, cluster))\n .map(endpoint => getServiceMetadata(endpoint)?.namespace)[0]\n\n return {\n all: false,\n cidrs,\n fqdns,\n services: [],\n namespaces: namespace ? [namespace] : [],\n selectors,\n ports,\n }\n }\n\n private static isEmptyRule(rule: NormalizedRuleArgs): boolean {\n return (\n !rule.all &&\n rule.cidrs.length === 0 &&\n rule.fqdns.length === 0 &&\n rule.services.length === 0 &&\n rule.namespaces.length === 0 &&\n rule.selectors.length === 0 &&\n rule.ports.length === 0\n )\n }\n\n protected abstract create(\n name: string,\n args: NormalizedNetworkPolicyArgs,\n opts?: ResourceOptions,\n ): Input<Resource>\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.cni\n\n if (cni === \"other\") {\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 isolate(\n namespace: Input<NamespaceLike>,\n cluster: Input<k8s.Cluster>,\n opts?: ResourceOptions,\n ) {\n return NetworkPolicy.create(\n \"isolate\",\n {\n namespace,\n cluster,\n\n description: \"By default, deny all traffic to/from the namespace.\",\n\n isolateEgress: true,\n isolateIngress: true,\n },\n 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 static allowAllIngress(\n namespace: Input<NamespaceLike>,\n cluster: Input<k8s.Cluster>,\n opts?: ResourceOptions,\n ): Output<NetworkPolicy> {\n return NetworkPolicy.create(\n \"allow-all-ingress\",\n {\n namespace,\n cluster,\n\n description: \"Allow all ingress traffic to the namespace.\",\n\n ingressRule: { fromAll: true },\n },\n opts,\n )\n }\n\n static allowEgressToEndpoint(\n endpoint: InputL34Endpoint,\n namespace: Input<NamespaceLike>,\n cluster: Input<k8s.Cluster>,\n opts?: ResourceOptions,\n ): Output<NetworkPolicy> {\n const parsedEndpoint = parseL34Endpoint(endpoint)\n\n return NetworkPolicy.create(\n `allow-egress-to-${l34EndpointToString(parsedEndpoint)}`,\n {\n namespace,\n cluster,\n\n description: interpolate`Allow egress traffic to \"${l34EndpointToString(parsedEndpoint)}\" from the namespace.`,\n\n egressRule: { toEndpoint: endpoint },\n },\n opts,\n )\n }\n\n static allowIngressFromEndpoint(\n endpoint: InputL34Endpoint,\n namespace: Input<NamespaceLike>,\n cluster: Input<k8s.Cluster>,\n opts?: ResourceOptions,\n ): Output<NetworkPolicy> {\n const parsedEndpoint = parseL34Endpoint(endpoint)\n\n return NetworkPolicy.create(\n `allow-ingress-from-${l34EndpointToString(parsedEndpoint)}`,\n {\n namespace,\n cluster,\n\n description: interpolate`Allow ingress traffic from \"${l34EndpointToString(parsedEndpoint)}\" to the namespace.`,\n\n ingressRule: { fromEndpoint: endpoint },\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 fallbackDnsRule: types.input.networking.v1.NetworkPolicyEgressRule = {\n to: [\n {\n namespaceSelector: { matchLabels: { \"kubernetes.io/metadata.name\": \"kube-system\" } },\n podSelector: { matchLabels: { \"k8s-app\": \"kube-dns\" } },\n },\n ],\n ports: [{ port: 53, protocol: \"UDP\" }],\n }\n\n private static createIngressRules(\n args: NormalizedNetworkPolicyArgs,\n ): types.input.networking.v1.NetworkPolicyIngressRule[] {\n return uniqueBy(\n args.ingressRules.map(rule => ({\n from: rule.all ? [] : NativeNetworkPolicy.createRulePeers(rule),\n ports: NativeNetworkPolicy.mapPorts(rule.ports),\n })),\n rule => JSON.stringify(rule),\n )\n }\n\n private static createEgressRules(\n args: NormalizedNetworkPolicyArgs,\n ): types.input.networking.v1.NetworkPolicyEgressRule[] {\n const extraRules: types.input.networking.v1.NetworkPolicyEgressRule[] = []\n\n const needKubeDns = args.egressRules.some(rule => rule.fqdns.length > 0)\n if (needKubeDns) {\n extraRules.push(NativeNetworkPolicy.fallbackDnsRule)\n }\n\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 =>\n rule.fqdns.some(fqdn => !fqdn.endsWith(\".cluster.local\")),\n )\n if (needFallback) {\n extraRules.push({ to: [{ ipBlock: NativeNetworkPolicy.fallbackIpBlock }] })\n }\n\n // apply fallback rules for kube-apiserver\n if (args.allowKubeApiServer) {\n const { quirks, apiEndpoints } = args.cluster\n\n if (quirks?.fallbackKubeApiAccess) {\n extraRules.push({\n to: [{ ipBlock: { cidr: `${quirks?.fallbackKubeApiAccess.serverIp}/32` } }],\n ports: [{ port: quirks?.fallbackKubeApiAccess.serverPort, protocol: \"TCP\" }],\n })\n } else {\n const rules = apiEndpoints\n .filter(endpoint => endpoint.type !== \"hostname\")\n .map(endpoint => ({\n to: [{ ipBlock: { cidr: l3EndpointToCidr(endpoint) } }],\n ports: [{ port: endpoint.port, protocol: \"TCP\" }],\n }))\n\n extraRules.push(...rules)\n }\n }\n\n return uniqueBy(\n args.egressRules\n .map(rule => {\n return {\n to: rule.all ? [] : NativeNetworkPolicy.createRulePeers(rule),\n ports: NativeNetworkPolicy.mapPorts(rule.ports),\n } as types.input.networking.v1.NetworkPolicyEgressRule\n })\n .filter(rule => rule.to !== undefined)\n .concat(extraRules),\n rule => JSON.stringify(rule),\n )\n }\n\n private static createRulePeers(\n this: void,\n args: NormalizedRuleArgs,\n ): types.input.networking.v1.NetworkPolicyPeer[] | undefined {\n const peers = uniqueBy(\n [\n ...NativeNetworkPolicy.createCidrPeers(args),\n ...NativeNetworkPolicy.createServicePeers(args),\n ...NativeNetworkPolicy.createSelectorPeers(args),\n ],\n peer => JSON.stringify(peer),\n )\n\n return peers.length > 0 ? peers : undefined\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 { DeploymentArgs } from \"./deployment\"\nimport type { StatefulSetArgs } from \"./stateful-set\"\nimport type { types } from \"@pulumi/kubernetes\"\nimport {\n normalize,\n type ComponentResourceOptions,\n type InputArray,\n type InstanceTerminal,\n} from \"@highstate/pulumi\"\nimport {\n ComponentResource,\n interpolate,\n Output,\n output,\n type CustomResourceOptions,\n type Input,\n} from \"@pulumi/pulumi\"\nimport { uniqueBy } from \"remeda\"\nimport { deepmerge } from \"deepmerge-ts\"\nimport { commonExtraArgs, getProvider, 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\"\nimport { NetworkPolicy } from \"./network-policy\"\nimport { podSpecDefaults } from \"./pod\"\n\nexport type WorkloadArgs = CommonArgs & {\n container?: Input<Container>\n containers?: InputArray<Container>\n\n /**\n * The shell to use in the terminal.\n *\n * By default, `bash` is used.\n */\n terminalShell?: string\n}\n\nexport const workloadExtraArgs = [...commonExtraArgs, \"container\", \"containers\"] as const\n\nexport type ExposableWorkloadArgs = WorkloadArgs & {\n service?: Input<Omit<ServiceArgs, \"cluster\" | \"namespace\">>\n httpRoute?: Input<Omit<HttpRouteArgs, \"cluster\" | \"namespace\">>\n\n /**\n * The existing workload to patch.\n */\n existing?: Input<k8s.ExposableWorkload>\n}\n\nexport const exposableWorkloadExtraArgs = [...workloadExtraArgs, \"service\", \"httpRoute\"] as const\n\nexport type ExposableWorkloadType = \"Deployment\" | \"StatefulSet\"\n\nexport type GenericExposableWorkloadArgs = Omit<ExposableWorkloadArgs, \"existing\"> & {\n /**\n * The type of workload to create.\n *\n * Will be ignored if the `existing` argument is provided.\n */\n type: ExposableWorkloadType\n\n /**\n * The existing workload to patch.\n */\n existing: Input<k8s.ExposableWorkload | undefined>\n\n /**\n * The args specific to the \"Deployment\" workload type.\n *\n * Will be ignored for other workload types.\n */\n deployment?: Input<DeploymentArgs>\n\n /**\n * The args specific to the \"StatefulSet\" workload type.\n *\n * Will be ignored for other workload types.\n */\n statefulSet?: Input<StatefulSetArgs>\n}\n\nexport function getWorkloadComponents(\n name: string,\n args: WorkloadArgs,\n parent: () => ComponentResource,\n opts: ComponentResourceOptions | undefined,\n) {\n const labels = {\n \"app.kubernetes.io/name\": name,\n }\n\n const containers = output(args).apply(args => normalize(args.container, args.containers))\n\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 output([...containerVolumes, ...containerVolumeMounts]).apply(\n uniqueBy(volume => volume.name),\n )\n })\n\n const podSpec = output({ args, containers, volumes }).apply(({ args, containers, volumes }) => {\n const spec = {\n volumes,\n containers: containers.map(container => mapContainerToRaw(container, args.cluster, name)),\n ...podSpecDefaults,\n } satisfies types.input.core.v1.PodSpec\n\n if (\n containers.some(container => container.enableTun) &&\n args.cluster.quirks?.tunDevicePolicy?.type !== \"plugin\"\n ) {\n spec.volumes = output(spec.volumes).apply(volumes => [\n ...(volumes ?? []),\n {\n name: \"tun-device\",\n hostPath: {\n path: \"/dev/net/tun\",\n },\n },\n ])\n }\n\n return spec\n })\n\n const podTemplate = podSpec.apply(podSpec => {\n return {\n metadata: { labels },\n spec: podSpec,\n } satisfies types.input.core.v1.PodTemplateSpec\n })\n\n const networkPolicy = containers.apply(containers => {\n const allowedEndpoints = containers.flatMap(container => container.allowedEndpoints ?? [])\n\n if (allowedEndpoints.length === 0) {\n return undefined\n }\n\n return NetworkPolicy.create(\n name,\n {\n cluster: args.cluster,\n namespace: args.namespace,\n selector: labels,\n\n egressRule: {\n toEndpoints: allowedEndpoints,\n },\n },\n { ...opts, parent: parent() },\n )\n }) as Output<NetworkPolicy | undefined>\n\n return { labels, containers, volumes, podSpec, podTemplate, networkPolicy }\n}\n\nexport function getExposableWorkloadComponents(\n name: string,\n args: ExposableWorkloadArgs,\n parent: () => ComponentResource,\n opts: ComponentResourceOptions | undefined,\n) {\n const { labels, containers, volumes, podSpec, podTemplate, networkPolicy } =\n getWorkloadComponents(name, args, parent, opts)\n\n const service = output({ args, containers }).apply(async ({ args, containers }) => {\n if (!args.service && !args.httpRoute) {\n return undefined\n }\n\n if (args.existing?.service) {\n return Service.of(name, args.existing.service, args.cluster, { ...opts, parent: parent() })\n }\n\n if (args.existing) {\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 {\n ...opts,\n parent: parent(),\n provider: await getProvider(args.cluster),\n },\n )\n })\n\n const httpRoute = output({\n args,\n service,\n }).apply(async ({ args, service }) => {\n if (!args.httpRoute || !service) {\n return undefined\n }\n\n if (args.existing) {\n return undefined\n }\n\n return new HttpRoute(\n name,\n {\n ...args.httpRoute,\n cluster: args.cluster,\n rule: {\n backend: service,\n },\n },\n {\n ...opts,\n parent: parent(),\n provider: await getProvider(args.cluster),\n },\n )\n })\n\n return { labels, containers, volumes, podSpec, podTemplate, networkPolicy, service, httpRoute }\n}\n\nexport abstract class Workload extends ComponentResource {\n protected constructor(\n type: string,\n protected readonly name: string,\n private readonly args: WorkloadArgs,\n opts: ComponentResourceOptions | undefined,\n\n protected readonly resourceType: string,\n\n /**\n * The cluster where the workload is created.\n */\n readonly cluster: Output<k8s.Cluster>,\n\n /**\n * The metadata of the underlying Kubernetes workload.\n */\n readonly metadata: Output<types.output.meta.v1.ObjectMeta>,\n\n /**\n * The network policy associated with the workload.\n *\n * Will be created if one or more containers have `allowedEndpoints` defined.\n */\n readonly networkPolicy: Output<NetworkPolicy | undefined>,\n ) {\n super(type, name, args, opts)\n }\n\n /**\n * The instance terminal to interact with the deployment.\n */\n get terminal(): Output<InstanceTerminal> {\n const containerName = output(this.args).apply(args => {\n const containers = normalize(args.container, args.containers)\n\n return containers[0]?.name ?? this.name\n })\n\n return output({\n name: this.metadata.name,\n title: this.metadata.name,\n image: \"ghcr.io/exeteres/highstate/terminal-kubectl\",\n command: [\n \"exec\",\n \"kubectl\",\n \"exec\",\n \"-it\",\n \"-n\",\n this.metadata.namespace,\n interpolate`${this.resourceType}/${this.metadata.name}`,\n \"-c\",\n containerName,\n \"--\",\n this.args.terminalShell ?? \"bash\",\n ],\n files: {\n \"/kubeconfig\": this.cluster.kubeconfig,\n },\n env: {\n KUBECONFIG: \"/kubeconfig\",\n },\n })\n }\n}\n\nexport abstract class ExposableWorkload extends Workload {\n protected constructor(\n type: string,\n protected readonly name: string,\n args: ExposableWorkloadArgs,\n opts: ComponentResourceOptions | undefined,\n\n resourceType: string,\n cluster: Output<k8s.Cluster>,\n metadata: Output<types.output.meta.v1.ObjectMeta>,\n networkPolicy: Output<NetworkPolicy | undefined>,\n\n protected readonly _service: Output<Service | undefined>,\n protected readonly _httpRoute: Output<HttpRoute | undefined>,\n ) {\n super(type, name, args, opts, resourceType, cluster, metadata, networkPolicy)\n }\n\n /**\n * The service associated with the workload.\n */\n get optionalService(): Output<Service | undefined> {\n return this._service\n }\n\n /**\n * The HTTP route associated with the workload.\n */\n get optionalHttpRoute(): Output<HttpRoute | undefined> {\n return this._httpRoute\n }\n\n /**\n * The service associated with the workload.\n *\n * Will throw an error if the service is not available.\n */\n get service(): Output<Service> {\n return this._service.apply(service => {\n if (!service) {\n throw new Error(`The service of the workload \"${this.name}\" is not available.`)\n }\n\n return service\n })\n }\n\n /**\n * The HTTP route associated with the workload.\n *\n * Will throw an error if the HTTP route is not available.\n */\n get httpRoute(): Output<HttpRoute> {\n return this._httpRoute.apply(httpRoute => {\n if (!httpRoute) {\n throw new Error(`The HTTP route of the workload \"${this.name}\" is not available.`)\n }\n\n return httpRoute\n })\n }\n\n /**\n * The entity of the workload.\n */\n abstract get entity(): Output<k8s.ExposableWorkload>\n\n /**\n * The sped of the underlying Kubernetes workload.\n */\n abstract get spec(): Output<\n types.output.apps.v1.DeploymentSpec | types.output.apps.v1.StatefulSetSpec\n >\n\n /**\n * Creates a generic workload or patches the existing one.\n */\n static createOrPatchGeneric(\n name: string,\n args: GenericExposableWorkloadArgs,\n opts?: CustomResourceOptions,\n ): Output<ExposableWorkload> {\n return output(args).apply(async args => {\n if (args.existing?.type === \"k8s.deployment\") {\n const { Deployment } = await import(\"./deployment\")\n\n return Deployment.patch(\n name,\n {\n ...deepmerge(args, args.deployment),\n name: args.existing.metadata.name,\n namespace: args.existing.metadata.namespace,\n },\n opts,\n )\n }\n\n if (args.existing?.type === \"k8s.stateful-set\") {\n const { StatefulSet } = await import(\"./stateful-set\")\n\n return StatefulSet.patch(\n name,\n {\n ...deepmerge(args, args.statefulSet),\n name: args.existing.metadata.name,\n namespace: args.existing.metadata.namespace,\n },\n opts,\n )\n }\n\n if (args.type === \"Deployment\") {\n const { Deployment } = await import(\"./deployment\")\n\n return Deployment.create(name, deepmerge(args, args.deployment), opts)\n }\n\n if (args.type === \"StatefulSet\") {\n const { StatefulSet } = await import(\"./stateful-set\")\n\n return StatefulSet.create(name, deepmerge(args, args.statefulSet), opts)\n }\n\n throw new Error(`Unknown workload type: ${args.type as string}`)\n })\n }\n}\n","import type { types } from \"@pulumi/kubernetes\"\n\nexport const podSpecDefaults: Partial<types.input.core.v1.PodSpec> = {\n automountServiceAccountToken: false,\n}\n"],"mappings":"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","names":["args","id","core","ComponentResource","output","ComponentResource","output","args","core","core","output","omit","omit","output","core","ComponentResource","normalize","output","ComponentResource","output","args","normalize","endpoints","rule","normalize","ComponentResource","interpolate","output","uniqueBy","deepmerge","output","args","normalize","containers","uniqueBy","volumes","podSpec","service","ComponentResource","interpolate","deepmerge"]}
@@ -0,0 +1,214 @@
1
+ import {
2
+ HttpRoute,
3
+ Service,
4
+ getServiceType
5
+ } from "./chunk-HW3NS3MC.js";
6
+ import {
7
+ getProvider,
8
+ mapNamespaceLikeToNamespaceName
9
+ } from "./chunk-FKNHHKOL.js";
10
+
11
+ // src/helm.ts
12
+ import { resolve } from "node:path";
13
+ import { mkdir, readFile, unlink } from "node:fs/promises";
14
+ import { toPromise } from "@highstate/pulumi";
15
+ import { core, helm } from "@pulumi/kubernetes";
16
+ import {
17
+ ComponentResource,
18
+ output
19
+ } from "@pulumi/pulumi";
20
+ import spawn from "nano-spawn";
21
+ import { sha256 } from "crypto-hash";
22
+ import { omit } from "remeda";
23
+ import { local } from "@pulumi/command";
24
+ import { glob } from "glob";
25
+ var Chart = class extends ComponentResource {
26
+ constructor(name, args, opts) {
27
+ super("highstate:k8s:Chart", name, args, opts);
28
+ this.name = name;
29
+ this.args = args;
30
+ this.opts = opts;
31
+ const namespace = output(args.namespace).apply(
32
+ (namespace2) => output(namespace2 ? mapNamespaceLikeToNamespaceName(namespace2) : "default")
33
+ );
34
+ this.chart = output({ args, namespace }).apply(async ({ args: args2, namespace: namespace2 }) => {
35
+ return new helm.v4.Chart(
36
+ name,
37
+ omit(
38
+ {
39
+ ...args2,
40
+ chart: resolveHelmChart(args2.chart),
41
+ namespace: namespace2
42
+ },
43
+ ["httpRoute"]
44
+ ),
45
+ {
46
+ ...opts,
47
+ parent: this,
48
+ provider: await getProvider(args2.cluster),
49
+ transforms: [
50
+ ...opts?.transforms ?? [],
51
+ (resourceArgs) => {
52
+ const serviceName = args2.serviceName ?? name;
53
+ const expectedName = `${name}:${namespace2}/${serviceName}`;
54
+ if (resourceArgs.type === "kubernetes:core/v1:Service" && resourceArgs.name === expectedName) {
55
+ const spec = resourceArgs.props.spec;
56
+ return {
57
+ props: {
58
+ ...resourceArgs.props,
59
+ spec: {
60
+ ...spec,
61
+ ...args2.service ?? {},
62
+ type: getServiceType(args2.service, args2.cluster),
63
+ externalIPs: args2.service?.externalIPs ?? args2.cluster.externalIps ?? spec.externalIPs
64
+ }
65
+ },
66
+ opts: resourceArgs.opts
67
+ };
68
+ }
69
+ return void 0;
70
+ }
71
+ ]
72
+ }
73
+ );
74
+ });
75
+ this.httpRoute = output(args.httpRoute).apply((httpRoute) => {
76
+ if (!httpRoute) {
77
+ return void 0;
78
+ }
79
+ return new HttpRoute(
80
+ name,
81
+ {
82
+ ...httpRoute,
83
+ rule: {
84
+ backend: this.service
85
+ }
86
+ },
87
+ { ...opts, parent: this }
88
+ );
89
+ });
90
+ this.registerOutputs({ chart: this.chart });
91
+ }
92
+ /**
93
+ * The underlying Helm chart.
94
+ */
95
+ chart;
96
+ /**
97
+ * The HTTP route associated with the deployment.
98
+ */
99
+ httpRoute;
100
+ get service() {
101
+ return this.getServiceOutput(void 0);
102
+ }
103
+ services = /* @__PURE__ */ new Map();
104
+ getServiceOutput(name) {
105
+ return output({ args: this.args, chart: this.chart }).apply(({ args, chart }) => {
106
+ const resolvedName = name ?? args.serviceName ?? this.name;
107
+ const existingService = this.services.get(resolvedName);
108
+ if (existingService) {
109
+ return existingService;
110
+ }
111
+ const service = getChartServiceOutput(chart, resolvedName);
112
+ const wrappedService = Service.wrap(
113
+ //
114
+ resolvedName,
115
+ service,
116
+ args.cluster,
117
+ { ...this.opts, parent: this }
118
+ );
119
+ this.services.set(resolvedName, wrappedService);
120
+ return wrappedService;
121
+ });
122
+ }
123
+ getService(name) {
124
+ return toPromise(this.getServiceOutput(name));
125
+ }
126
+ };
127
+ var RenderedChart = class extends ComponentResource {
128
+ /**
129
+ * The rendered manifest of the Helm chart.
130
+ */
131
+ manifest;
132
+ /**
133
+ * The underlying command used to render the chart.
134
+ */
135
+ command;
136
+ constructor(name, args, opts) {
137
+ super("highstate:k8s:RenderedChart", name, args, opts);
138
+ this.command = output(args).apply((args2) => {
139
+ const values = args2.values ? Object.entries(args2.values).flatMap(([key, value]) => ["--set", `${key}="${value}"`]) : [];
140
+ return new local.Command(
141
+ name,
142
+ {
143
+ create: output([
144
+ "helm",
145
+ "template",
146
+ resolveHelmChart(args2.chart),
147
+ ...args2.namespace ? ["--namespace", mapNamespaceLikeToNamespaceName(args2.namespace)] : [],
148
+ ...values
149
+ ]).apply((command) => command.join(" ")),
150
+ logging: "stderr"
151
+ },
152
+ { parent: this, ...opts }
153
+ );
154
+ });
155
+ this.manifest = this.command.stdout;
156
+ this.registerOutputs({ manifest: this.manifest, command: this.command });
157
+ }
158
+ };
159
+ async function resolveHelmChart(manifest) {
160
+ if (!process.env.HIGHSTATE_CACHE_DIR) {
161
+ throw new Error("Environment variable HIGHSTATE_CACHE_DIR is not set");
162
+ }
163
+ const chartsDir = resolve(process.env.HIGHSTATE_CACHE_DIR, "charts");
164
+ await mkdir(chartsDir, { recursive: true });
165
+ const globPattern = `${manifest.name}-*.tgz`;
166
+ const targetFileName = `${manifest.name}-${manifest.version}.tgz`;
167
+ const files = await glob(globPattern, { cwd: chartsDir });
168
+ if (files.includes(targetFileName)) {
169
+ return resolve(chartsDir, targetFileName);
170
+ }
171
+ for (const file of files) {
172
+ await unlink(resolve(chartsDir, file));
173
+ }
174
+ await spawn("helm", [
175
+ "pull",
176
+ manifest.name,
177
+ "--version",
178
+ manifest.version,
179
+ "--repo",
180
+ manifest.repo,
181
+ "--destination",
182
+ chartsDir
183
+ ]);
184
+ const content = await readFile(resolve(chartsDir, targetFileName));
185
+ const actualSha256 = await sha256(content);
186
+ if (actualSha256 !== manifest.sha256) {
187
+ throw new Error(`SHA256 mismatch for chart '${manifest.name}'`);
188
+ }
189
+ return resolve(chartsDir, targetFileName);
190
+ }
191
+ function getChartServiceOutput(chart, name) {
192
+ const services = chart.resources.apply((resources) => {
193
+ return resources.filter((r) => core.v1.Service.isInstance(r)).map((service) => ({ name: service.metadata.name, service }));
194
+ });
195
+ return output(services).apply((services2) => {
196
+ const service = services2.find((s) => s.name === name)?.service;
197
+ if (!service) {
198
+ throw new Error(`Service with name '${name}' not found in the chart resources`);
199
+ }
200
+ return service;
201
+ });
202
+ }
203
+ function getChartService(chart, name) {
204
+ return toPromise(getChartServiceOutput(chart, name));
205
+ }
206
+
207
+ export {
208
+ Chart,
209
+ RenderedChart,
210
+ resolveHelmChart,
211
+ getChartServiceOutput,
212
+ getChartService
213
+ };
214
+ //# sourceMappingURL=chunk-UNVSWG6D.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/helm.ts"],"sourcesContent":["import type { k8s } from \"@highstate/library\"\nimport { resolve } from \"node:path\"\nimport { mkdir, readFile, unlink } from \"node:fs/promises\"\nimport { toPromise, type InputMap } from \"@highstate/pulumi\"\nimport { core, helm, types } from \"@pulumi/kubernetes\"\nimport {\n ComponentResource,\n output,\n type ComponentResourceOptions,\n type Input,\n type Output,\n} from \"@pulumi/pulumi\"\nimport spawn from \"nano-spawn\"\nimport { sha256 } from \"crypto-hash\"\nimport { omit } from \"remeda\"\nimport { local } from \"@pulumi/command\"\nimport { glob } from \"glob\"\nimport { HttpRoute, type HttpRouteArgs } from \"./gateway\"\nimport { getProvider, mapNamespaceLikeToNamespaceName, type NamespaceLike } from \"./shared\"\nimport { getServiceType, Service, type ServiceArgs } from \"./service\"\n\nexport type ChartArgs = Omit<\n helm.v4.ChartArgs,\n \"chart\" | \"version\" | \"repositoryOpts\" | \"namespace\"\n> & {\n /**\n * The namespace to deploy the chart into.\n */\n namespace?: Input<NamespaceLike>\n\n /**\n * The custom name of the primary service exposed by the chart.\n *\n * By default, it is the same as the chart name.\n */\n serviceName?: string\n\n /**\n * The extra args to pass to the main service of the chart.\n *\n * Will be patched via transformations.\n */\n service?: Partial<ServiceArgs>\n\n /**\n * The manifest of the chart to resolve.\n */\n chart: ChartManifest\n\n /**\n * The cluster to create the resource in.\n */\n cluster: Input<k8s.Cluster>\n\n /**\n * The http route args to bind the service to.\n */\n httpRoute?: Input<HttpRouteArgs>\n}\n\nexport class Chart extends ComponentResource {\n /**\n * The underlying Helm chart.\n */\n public readonly chart: Output<helm.v4.Chart>\n\n /**\n * The HTTP route associated with the deployment.\n */\n public readonly httpRoute: Output<HttpRoute | undefined>\n\n constructor(\n private readonly name: string,\n private readonly args: ChartArgs,\n private readonly opts?: ComponentResourceOptions,\n ) {\n super(\"highstate:k8s:Chart\", name, args, opts)\n\n const namespace = output(args.namespace).apply(namespace =>\n output(namespace ? mapNamespaceLikeToNamespaceName(namespace) : \"default\"),\n )\n\n this.chart = output({ args, namespace }).apply(async ({ args, namespace }) => {\n return new helm.v4.Chart(\n name,\n omit(\n {\n ...args,\n chart: resolveHelmChart(args.chart),\n namespace,\n },\n [\"httpRoute\"],\n ),\n {\n ...opts,\n parent: this,\n provider: await getProvider(args.cluster),\n\n transforms: [\n ...(opts?.transforms ?? []),\n\n resourceArgs => {\n const serviceName = args.serviceName ?? name\n const expectedName = `${name}:${namespace}/${serviceName}`\n\n if (\n resourceArgs.type === \"kubernetes:core/v1:Service\" &&\n resourceArgs.name === expectedName\n ) {\n const spec = resourceArgs.props.spec as types.input.core.v1.ServiceSpec\n\n return {\n props: {\n ...resourceArgs.props,\n spec: {\n ...spec,\n ...(args.service ?? {}),\n\n type: getServiceType(args.service, args.cluster),\n\n externalIPs:\n args.service?.externalIPs ?? args.cluster.externalIps ?? spec.externalIPs,\n },\n },\n opts: resourceArgs.opts,\n }\n }\n\n return undefined\n },\n ],\n },\n )\n })\n\n this.httpRoute = output(args.httpRoute).apply(httpRoute => {\n if (!httpRoute) {\n return undefined\n }\n\n return new HttpRoute(\n name,\n {\n ...httpRoute,\n rule: {\n backend: this.service,\n },\n },\n { ...opts, parent: this },\n )\n })\n\n this.registerOutputs({ chart: this.chart })\n }\n\n get service(): Output<Service> {\n return this.getServiceOutput(undefined)\n }\n\n private readonly services = new Map<string, Service>()\n\n getServiceOutput(name: string | undefined): Output<Service> {\n return output({ args: this.args, chart: this.chart }).apply(({ args, chart }) => {\n const resolvedName = name ?? args.serviceName ?? this.name\n const existingService = this.services.get(resolvedName)\n\n if (existingService) {\n return existingService\n }\n\n const service = getChartServiceOutput(chart, resolvedName)\n\n const wrappedService = Service.wrap(\n //\n resolvedName,\n service,\n args.cluster,\n { ...this.opts, parent: this },\n )\n\n this.services.set(resolvedName, wrappedService)\n return wrappedService\n })\n }\n\n getService(name?: string): Promise<Service> {\n return toPromise(this.getServiceOutput(name))\n }\n}\n\nexport type RenderedChartArgs = {\n /**\n * The namespace to deploy the chart into.\n */\n namespace?: Input<NamespaceLike>\n\n /**\n * The manifest of the chart to resolve.\n */\n chart: ChartManifest\n\n /**\n * The values to pass to the chart.\n */\n values?: InputMap<string>\n}\n\nexport class RenderedChart extends ComponentResource {\n /**\n * The rendered manifest of the Helm chart.\n */\n public readonly manifest: Output<string>\n\n /**\n * The underlying command used to render the chart.\n */\n public readonly command: Output<local.Command>\n\n constructor(name: string, args: RenderedChartArgs, opts?: ComponentResourceOptions) {\n super(\"highstate:k8s:RenderedChart\", name, args, opts)\n\n this.command = output(args).apply(args => {\n const values = args.values\n ? Object.entries(args.values).flatMap(([key, value]) => [\"--set\", `${key}=\"${value}\"`])\n : []\n\n return new local.Command(\n name,\n {\n create: output([\n \"helm\",\n \"template\",\n resolveHelmChart(args.chart),\n\n ...(args.namespace\n ? [\"--namespace\", mapNamespaceLikeToNamespaceName(args.namespace)]\n : []),\n\n ...values,\n ]).apply(command => command.join(\" \")),\n\n logging: \"stderr\",\n },\n { parent: this, ...opts },\n )\n })\n\n this.manifest = this.command.stdout\n\n this.registerOutputs({ manifest: this.manifest, command: this.command })\n }\n}\n\nexport type ChartManifest = {\n repo: string\n name: string\n version: string\n sha256: string\n}\n\n/**\n * Downloads or reuses the Helm chart according to the charts.json file.\n * Returns the full path to the chart's .tgz file.\n *\n * @param manifest The manifest of the Helm chart.\n */\nexport async function resolveHelmChart(manifest: ChartManifest): Promise<string> {\n if (!process.env.HIGHSTATE_CACHE_DIR) {\n throw new Error(\"Environment variable HIGHSTATE_CACHE_DIR is not set\")\n }\n\n const chartsDir = resolve(process.env.HIGHSTATE_CACHE_DIR, \"charts\")\n await mkdir(chartsDir, { recursive: true })\n\n const globPattern = `${manifest.name}-*.tgz`\n const targetFileName = `${manifest.name}-${manifest.version}.tgz`\n\n // find all matching files\n const files = await glob(globPattern, { cwd: chartsDir })\n\n if (files.includes(targetFileName)) {\n return resolve(chartsDir, targetFileName)\n }\n\n // delete old versions\n for (const file of files) {\n await unlink(resolve(chartsDir, file))\n }\n\n // download the chart\n await spawn(\"helm\", [\n \"pull\",\n manifest.name,\n \"--version\",\n manifest.version,\n \"--repo\",\n manifest.repo,\n \"--destination\",\n chartsDir,\n ])\n\n // check the SHA256\n const content = await readFile(resolve(chartsDir, targetFileName))\n const actualSha256 = await sha256(content)\n\n if (actualSha256 !== manifest.sha256) {\n throw new Error(`SHA256 mismatch for chart '${manifest.name}'`)\n }\n\n return resolve(chartsDir, targetFileName)\n}\n\n/**\n * Extracts the service with the given name from the chart resources.\n * Throws an error if the service is not found.\n *\n * @param chart The Helm chart.\n * @param name The name of the service.\n */\nexport function getChartServiceOutput(chart: helm.v4.Chart, name: string): Output<core.v1.Service> {\n const services = chart.resources.apply(resources => {\n return resources\n .filter(r => core.v1.Service.isInstance(r))\n .map(service => ({ name: service.metadata.name, service }))\n })\n\n return output(services).apply(services => {\n const service = services.find(s => s.name === name)?.service\n\n if (!service) {\n throw new Error(`Service with name '${name}' not found in the chart resources`)\n }\n\n return service\n })\n}\n\n/**\n * Extracts the service with the given name from the chart resources.\n * Throws an error if the service is not found.\n *\n * @param chart The Helm chart.\n * @param name The name of the service.\n */\nexport function getChartService(chart: helm.v4.Chart, name: string): Promise<core.v1.Service> {\n return toPromise(getChartServiceOutput(chart, name))\n}\n"],"mappings":"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","names":["namespace","args","services"]}
@@ -0,0 +1,10 @@
1
+ import {
2
+ Deployment
3
+ } from "./chunk-DQSCJM5S.js";
4
+ import "./chunk-QGHMLKTW.js";
5
+ import "./chunk-HW3NS3MC.js";
6
+ import "./chunk-FKNHHKOL.js";
7
+ export {
8
+ Deployment
9
+ };
10
+ //# sourceMappingURL=deployment-ZP3ASKPT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
@@ -1,10 +1,12 @@
1
1
  {
2
2
  "sourceHashes": {
3
- "./dist/index.js": "1fd051bc2c5f4f4fdbb4f6f8594e79c986ead0a4380d3afbbb5556d407a9bc9b",
4
- "./dist/units/access-point/index.js": "573732604825cdef60f5797a45147738182b87e45455bec147912cc6c5bd7d83",
5
- "./dist/units/cert-manager/index.js": "bfc6cc8a1641b086bb87c817a05961c31bb5f51e9b9353ec19903b0157412491",
6
- "./dist/units/dns01-issuer/index.js": "c3c7952df173b4f1dbb6e7247260f2d26042b91c121d857aaafead0f53c1852d",
7
- "./dist/units/existing-cluster/index.js": "f1b8d23e15962ad5c38d4875814602b01beca1eb7e47f498ab43f09afbe6604d",
8
- "./dist/units/gateway-api/index.js": "2f3026f0f7d58ee79acab62421e6713c4d4c0ccee5297160f7305f0f92278014"
3
+ "./dist/index.js": "90e098c13cf27b872fb00d96bd088e3d3139fd7e075b7e0b5831438c82ab5d2e",
4
+ "./dist/units/access-point/index.js": "6aca16c67e51282ea15891fa4ec5e53aea1c128623ad3c13ca0e298a7a2ca4f5",
5
+ "./dist/units/cert-manager/index.js": "c753aae386ae6918fc9268a4e709f7fe0377f225566506c0614445aa3ad8931e",
6
+ "./dist/units/cluster-patch/index.js": "4f56d6e882afcef37507aa56bdf501c2fccd0138b8f80ebe96d68a8a31cd59f8",
7
+ "./dist/units/cluster-dns/index.js": "63123d3024350dfa390a2ba7e496e5a88acb1ff02a4dba9b15d5358b1ee74a44",
8
+ "./dist/units/dns01-issuer/index.js": "b1db32eec83e75203706f7bb7adb34a1a989ec819d9e053ee3d0be8307a01968",
9
+ "./dist/units/existing-cluster/index.js": "a4e26cd710b4a3c992b064c31580ce294e58feda74f150dcd27662f3fe737f77",
10
+ "./dist/units/gateway-api/index.js": "7f4e1a01265ce6905e933d98152af24edc956ec1bf69470058d3b6877e007746"
9
11
  }
10
12
  }