@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.
- package/dist/highstate.manifest.json +6 -5
- package/dist/index.js +31 -25
- package/dist/index.js.map +1 -1
- package/dist/units/access-point/index.js +1 -1
- package/dist/units/access-point/index.js.map +1 -1
- package/dist/units/dns01-issuer/index.js +8 -7
- package/dist/units/dns01-issuer/index.js.map +1 -1
- package/dist/units/existing-cluster/index.js +7 -2
- package/dist/units/existing-cluster/index.js.map +1 -1
- package/dist/units/gateway-api/index.js +24 -0
- package/dist/units/gateway-api/index.js.map +1 -0
- package/package.json +10 -9
- package/src/access-point.ts +10 -9
- package/src/index.ts +0 -1
- package/src/network-policy.ts +24 -20
- package/src/units/access-point/index.ts +1 -1
- package/src/units/dns01-issuer/index.ts +8 -7
- package/src/units/existing-cluster/index.ts +5 -0
- package/src/units/gateway-api/index.ts +20 -0
@@ -1,9 +1,10 @@
|
|
1
1
|
{
|
2
2
|
"sourceHashes": {
|
3
|
-
"./dist/index.js": "
|
4
|
-
"./dist/units/access-point/index.js": "
|
5
|
-
"./dist/units/cert-manager/index.js": "
|
6
|
-
"./dist/units/dns01-issuer/index.js": "
|
7
|
-
"./dist/units/existing-cluster/index.js": "
|
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
|
-
|
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(
|
672
|
-
const implModule = await import(`@highstate/${
|
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 ${
|
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,
|
681
|
+
static allowInsideNamespace(namespace, cluster, opts) {
|
681
682
|
return _NetworkPolicy.create(
|
682
683
|
"allow-inside-namespace",
|
683
684
|
{
|
684
685
|
namespace,
|
685
|
-
|
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,
|
695
|
+
static allowKubeApiServer(namespace, cluster, opts) {
|
695
696
|
return _NetworkPolicy.create(
|
696
697
|
"allow-kube-api-server",
|
697
698
|
{
|
698
699
|
namespace,
|
699
|
-
|
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,
|
707
|
+
static allowKubeDns(namespace, cluster, opts) {
|
707
708
|
return _NetworkPolicy.create(
|
708
709
|
"allow-kube-dns",
|
709
710
|
{
|
710
711
|
namespace,
|
711
|
-
|
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,
|
719
|
+
static allowAllEgress(namespace, cluster, opts) {
|
719
720
|
return _NetworkPolicy.create(
|
720
721
|
"allow-all-egress",
|
721
722
|
{
|
722
723
|
namespace,
|
723
|
-
|
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
|
-
|
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).
|
861
|
-
return DnsRecord.
|
862
|
-
|
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
|
-
|
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.
|
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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;AAAA,EACE,UAAAA;AAAA,EAIA,qBAAAC;AAAA,EAKA;AAAA,OACK;AACP,SAAS,YAAmB;AAC5B,SAAS,QAAAC,aAAY;AACrB,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,uBAAuB;;;ACjBhC,SAAS,QAAAC,aAAwB;AACjC,SAAS,WAAW,UAAAC,eAAwD;AAC5E,SAAS,QAAQ,KAAK,QAAAC,aAAY;;;ACFlC,SAAS,YAAwB;AACjC;AAAA,EACE;AAAA,EAEA;AAAA,OAKK;AACP,SAAS,iBAAiB;AAC1B,SAAS,YAAY;AAyBrB,IAAM,iCAAiC,CAAC,GAAG,iBAAiB,QAAQ,SAAS;AAEtE,IAAe,wBAAf,cAA6C,kBAAkB;AAAA,EAC1D,YACR,MACA,MACA,MACA,MAKS,aAKA,UAKA,MAKA,QACT;AACA,UAAM,MAAM,MAAM,MAAM,IAAI;AAjBnB;AAKA;AAKA;AAKA;AAAA,EAGX;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAA4C;AAC9C,WAAO,OAAO;AAAA,MACZ,MAAM;AAAA,MACN,aAAa,KAAK;AAAA,MAClB,UAAU,KAAK;AAAA,IACjB,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,OACL,MACA,MACA,MACuB;AACvB,WAAO,IAAI,6BAA6B,MAAM,MAAM,IAAI;AAAA,EAC1D;AAAA,EAEA,OAAO,GACL,MACA,QACA,MACuB;AACvB,WAAO,IAAI;AAAA,MACT;AAAA,MACA,OAAO,MAAM,EAAE;AAAA,MACf,OAAO,MAAM,EAAE;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,+BAAN,cAA2C,sBAAsB;AAAA,EACtE,YAAY,MAAc,MAAiC,MAA6B;AACtF,UAAM,MAAM,OAAO,IAAI,EAAE,MAAM,CAAAC,UAAQ;AACrC,aAAO,IAAI,KAAK,GAAG;AAAA,QACjB;AAAA,QACA;AAAA,UACE,UAAU,YAAYA,OAAM,IAAI;AAAA,UAChC,MAAM;AAAA,YACJ;AAAA,cACE,aAAa,CAAC,eAAe;AAAA,cAC7B,WAAW;AAAA,gBACT,UAAU;AAAA,kBACR,SAASA,MAAK,QAAQ;AAAA,gBACxB;AAAA,cACF;AAAA,YACF;AAAA,YACA,KAAKA,OAAM,8BAA8B;AAAA,UAC3C;AAAA,QACF;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAED;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEA,OAAO,KAAK,OAAO,EAAE;AAAA,MACrB,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AACF;AAEO,IAAM,gCAAN,cAA4C,sBAAsB;AAAA,EACvE,YACE,MACA,IACA,aACA,MACA;AACA,UAAM,MAAM,OAAO,EAAE,EAAE,MAAM,OAAMC,QAAM;AACvC,YAAM,eAAe,KAAK,UAAU,KAAK,WAAW;AAEpD,aAAO,KAAK,GAAG,sBAAsB;AAAA;AAAA,QAEnC;AAAA,QACA,mBAAmBA,GAAE;AAAA,QACrB,EAAE,QAAQ,MAAM,UAAU,KAAK,SAAS;AAAA,MAC1C;AAAA,IACF,CAAC;AAED;AAAA,MACE;AAAA,MACA;AAAA,MACA,EAAE,IAAI,YAAY;AAAA,MAClB;AAAA,MAEA,OAAO,WAAW;AAAA,MAClB,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AACF;;;ADlHA,IAAM,qBAAqB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAqDO,SAAS,kBACd,WACA,cAC+B;AAC/B,QAAM,gBAAgB,UAAU,QAAQ;AAExC,SAAO;AAAA,IACL,GAAGC,MAAK,WAAW,kBAAkB;AAAA,IAErC,MAAM;AAAA,IACN,OAAO,UAAU,UAAU,MAAM,UAAU,KAAK;AAAA,IAEhD,cAAc,IAAI,UAAU,UAAU,aAAa,UAAU,YAAY,GAAG,cAAc;AAAA,IAE1F,KAAK;AAAA,MACH,UAAU,cAAc,wBAAwB,UAAU,WAAW,IAAI,CAAC;AAAA,MAC1E,UAAU,OAAO,CAAC;AAAA,IACpB;AAAA,IAEA,SAAS;AAAA,MACP;AAAA,QACE,UAAU,UAAU,mBAAmB,UAAU,kBAAkB;AAAA,QACnE;AAAA,MACF;AAAA,MACA,UAAU,WAAW,CAAC;AAAA,IACxB;AAAA,EACF;AACF;AAEO,SAAS,wBACd,aAC8B;AAC9B,QAAM,UAAwC,CAAC;AAE/C,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,WAAW,GAAG;AACvD,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AAEA,QAAI,OAAO,UAAU,UAAU;AAC7B,cAAQ,KAAK,EAAE,MAAM,MAAM,CAAC;AAC5B;AAAA,IACF;AAEA,QAAI,YAAY,OAAO;AACrB,cAAQ,KAAK;AAAA,QACX;AAAA,QACA,WAAW;AAAA,UACT,cAAc;AAAA,YACZ,MAAM,MAAM,OAAO,SAAS;AAAA,YAC5B,KAAK,MAAM;AAAA,UACb;AAAA,QACF;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAEA,QAAI,eAAe,OAAO;AACxB,cAAQ,KAAK;AAAA,QACX;AAAA,QACA,WAAW;AAAA,UACT,iBAAiB;AAAA,YACf,MAAM,MAAM,UAAU,SAAS;AAAA,YAC/B,KAAK,MAAM;AAAA,UACb;AAAA,QACF;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAEA,YAAQ,KAAK,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,EACzC;AAEA,SAAO;AACT;AAEO,SAAS,eAAe,aAAoE;AACjG,MAAI,YAAY,aAAa;AAC3B,WAAOA;AAAA,MACL;AAAA,QACE,GAAG;AAAA,QACH,MAAMC,QAAO,YAAY,MAAM,EAC5B,MAAM,iBAAiB,EACvB,MAAM,YAAUA,QAAO,OAAO,IAAI,CAAC;AAAA,MACxC;AAAA,MACA,CAAC,QAAQ;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM,YAAY;AAAA,EACpB;AACF;AAEO,SAAS,qBACd,SACmC;AACnC,MAAI,mBAAmBC,MAAK,GAAG,WAAW;AACxC,WAAO;AAAA,MACL,cAAc;AAAA,QACZ,MAAM,QAAQ,SAAS;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,mBAAmBA,MAAK,GAAG,QAAQ;AACrC,WAAO;AAAA,MACL,WAAW;AAAA,QACT,MAAM,QAAQ,SAAS;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,kBAAkB,QAAwB;AACxD,MAAI,kBAAkB,uBAAuB;AAC3C,WAAO;AAAA,MACL,MAAM,OAAO,SAAS;AAAA,MACtB,uBAAuB;AAAA,QACrB,WAAW,OAAO,SAAS;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAEA,MAAI,kBAAkBA,MAAK,GAAG,uBAAuB;AACnD,WAAO;AAAA,MACL,MAAM,OAAO,SAAS;AAAA,MACtB,uBAAuB;AAAA,QACrB,WAAW,OAAO,SAAS;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAEA,MAAI,kBAAkBA,MAAK,GAAG,WAAW;AACvC,WAAO;AAAA,MACL,MAAM,OAAO,SAAS;AAAA,MACtB,WAAW;AAAA,QACT,MAAM,OAAO,SAAS;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,kBAAkBA,MAAK,GAAG,QAAQ;AACpC,WAAO;AAAA,MACL,MAAM,OAAO,SAAS;AAAA,MACtB,QAAQ;AAAA,QACN,YAAY,OAAO,SAAS;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AE5QA,SAAS,aAAAC,kBAAiE;AAC1E,SAAS,qBAAAC,oBAAmB,UAAAC,eAAuC;AACnE,SAAS,gBAAgB;AAqBlB,IAAM,oBAAoB,CAAC,GAAG,iBAAiB,aAAa,YAAY;AA6BxE,IAAM,0BAA0B,CAAC,GAAG,mBAAmB,WAAW,WAAW;AAE7E,SAAS,sBAAsB,MAAc,MAAoB;AACtE,QAAM,SAAS;AAAA,IACb,0BAA0B;AAAA,EAC5B;AAEA,QAAM,aAAaC,QAAO,IAAI,EAAE,MAAM,CAAAC,UAAQC,WAAUD,MAAK,WAAWA,MAAK,UAAU,CAAC;AACxF,QAAM,UAAU,WAAW,MAAM,CAAAE,gBAAc;AAC7C,UAAM,mBAAmBA,YACtB,QAAQ,eAAaD,WAAU,UAAU,QAAQ,UAAU,OAAO,CAAC,EACnE,IAAI,iBAAiB;AAExB,UAAM,wBAAwBC,YAC3B,QAAQ,eAAa;AACpB,aAAOD,WAAU,UAAU,aAAa,UAAU,YAAY,EAC3D,IAAI,iBAAe;AAClB,eAAO,YAAY,cAAc,YAAY,SAAS;AAAA,MACxD,CAAC,EACA,OAAO,OAAO;AAAA,IACnB,CAAC,EACA,IAAI,iBAAiB;AAExB,WAAO,SAAS,CAAC,GAAG,kBAAkB,GAAG,qBAAqB,GAAG,YAAU,OAAO,IAAI;AAAA,EACxF,CAAC;AAED,SAAO,EAAE,QAAQ,YAAY,QAAQ;AACvC;AAEO,SAAS,4BACd,MACA,MACA,QACA,MACA;AACA,QAAM,EAAE,QAAQ,YAAY,QAAQ,IAAI,sBAAsB,MAAM,IAAI;AAExE,QAAM,UAAUF,QAAO,EAAE,MAAM,WAAW,CAAC,EAAE,MAAM,CAAC,EAAE,MAAAC,OAAM,YAAAE,YAAW,MAAM;AAC3E,QAAI,CAACF,MAAK,WAAW,CAACA,MAAK,WAAW;AACpC,aAAO;AAAA,IACT;AAEA,QAAIA,MAAK,OAAO,SAAS;AACvB,aAAO,QAAQ,GAAG,MAAMA,MAAK,MAAM,SAAS,EAAE,QAAQ,OAAO,GAAG,GAAG,KAAK,CAAC;AAAA,IAC3E;AAEA,QAAIA,MAAK,OAAO;AACd,aAAO;AAAA,IACT;AAEA,UAAM,QAAQE,YAAW,QAAQ,eAAaD,WAAU,UAAU,MAAM,UAAU,KAAK,CAAC;AAExF,WAAO,QAAQ;AAAA,MACb;AAAA,MACA;AAAA,QACE,GAAGD,MAAK;AAAA,QACR,UAAU;AAAA,QACV,SAASA,MAAK;AAAA,QACd,WAAWA,MAAK;AAAA,QAEhB;AAAA;AAAA,UAEE,CAACA,MAAK,SAAS,QAAQ,CAACA,MAAK,SAAS,QAClC,MAAM,IAAI,6BAA6B,IACvCA,MAAK,SAAS;AAAA;AAAA,MACtB;AAAA,MACA,EAAE,QAAQ,OAAO,GAAG,GAAG,KAAK;AAAA,IAC9B;AAAA,EACF,CAAC;AAED,QAAM,YAAYD,QAAO;AAAA,IACvB;AAAA,IACA;AAAA,EACF,CAAC,EAAE,MAAM,CAAC,EAAE,MAAAC,OAAM,SAAAG,SAAQ,MAAM;AAC9B,QAAI,CAACH,MAAK,aAAa,CAACG,UAAS;AAC/B,aAAO;AAAA,IACT;AAEA,QAAIH,MAAK,OAAO;AACd,aAAO;AAAA,IACT;AAEA,WAAO,IAAI;AAAA,MACT;AAAA,MACA;AAAA,QACE,GAAGA,MAAK;AAAA,QACR,MAAM;AAAA,UACJ,SAASG;AAAA,QACX;AAAA,MACF;AAAA,MACA,EAAE,QAAQ,OAAO,GAAG,GAAG,KAAK;AAAA,IAC9B;AAAA,EACF,CAAC;AAED,SAAO,EAAE,QAAQ,YAAY,SAAS,SAAS,UAAU;AAC3D;;;AH1GO,IAAe,aAAf,cAAkCC,mBAAkB;AAAA,EAC/C,YACR,MACA,MACiB,MACjB,MAKS,SAKA,UAKA,MAKA,QAEQ,UACA,YAKR,WACT;AACA,UAAM,MAAM,MAAM,MAAM,IAAI;AA/BX;AAMR;AAKA;AAKA;AAKA;AAEQ;AACA;AAKR;AAAA,EAGX;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAiC;AACnC,WAAOC,QAAO;AAAA,MACZ,MAAM;AAAA,MACN,aAAa,KAAK,QAAQ;AAAA,MAC1B,UAAU,KAAK;AAAA,MACf,MAAM,KAAK;AAAA,MACX,SAAS,KAAK,SAAS,MAAM,aAAW,SAAS,MAAM;AAAA,IACzD,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,kBAA+C;AACjD,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAA2B;AAC7B,WAAO,KAAK,SAAS,MAAM,aAAW;AACpC,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,+BAA+B;AAAA,MACjD;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,YAA+B;AACjC,WAAO,KAAK,WAAW,MAAM,eAAa;AACxC,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,kCAAkC;AAAA,MACpD;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,WAAqC;AACvC,WAAOA,QAAO;AAAA,MACZ,MAAM,KAAK,SAAS;AAAA,MACpB,OAAO,KAAK,SAAS;AAAA,MACrB,OAAO;AAAA,MACP,SAAS,CAAC,UAAU,MAAM,MAAM,uBAAuB,WAAW;AAAA,MAClE,OAAO;AAAA,QACL,eAAe,KAAK,QAAQ;AAAA,QAE5B,uBAAuB;AAAA,UACrB,MAAM;AAAA,UACN,SAAS;AAAA;AAAA;AAAA,uCAGoB,KAAK,SAAS,SAAS,eAAe,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,iBAAiB,MAAM;AAAA,YAC3H,MAAM,eAAe;AAAA,QACzB;AAAA,MACF;AAAA,MACA,KAAK;AAAA,QACH,YAAY;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,OAAO,MAAc,MAAsB,MAA4C;AAC5F,WAAO,IAAI,kBAAkB,MAAM,MAAM,IAAI;AAAA,EAC/C;AACF;AAEA,IAAM,oBAAN,cAAgC,WAAW;AAAA,EACzC,YAAY,MAAc,MAAsB,MAAgC;AAC9E,UAAM,EAAE,QAAQ,YAAY,SAAS,SAAS,UAAU,IAAI;AAAA,MAC1D;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN;AAAA,IACF;AAEA,UAAM,aAAaA,QAAO,EAAE,MAAM,YAAY,QAAQ,CAAC,EAAE;AAAA,MACvD,OAAO,EAAE,MAAAC,OAAM,YAAAC,aAAY,SAAAC,SAAQ,MAAM;AACvC,cAAM,eAAe,KAAK,UAAUF,MAAK,QAAQ,IAAI;AAErD,eAAO,KAAKA,MAAK,QAAQ,KAAK,GAAG,kBAAkB,KAAK,GAAG;AAAA,UACzD;AAAA,UACA;AAAA,YACE,UAAU,YAAYA,MAAK,OAAO,YAAYA,OAAM,IAAI;AAAA,YACxD,MAAMG;AAAA,cACJ;AAAA,gBACE,UAAU;AAAA,kBACR,UAAU,CAACH,MAAK,QAAQ,EAAE,OAAO,IAAI;AAAA,kBACrC,MAAM;AAAA,oBACJ,YAAYC,YAAW,IAAI,eAAa,kBAAkB,WAAW,IAAI,CAAC;AAAA,oBAC1E,SAAAC;AAAA,kBACF;AAAA,gBACF;AAAA,gBACA,UAAU,CAACF,MAAK,QAAQ,EAAE,aAAa,OAAO,IAAI;AAAA,cACpD;AAAA,cACAI,MAAKJ,OAAM,uBAAuB;AAAA,YACpC;AAAA,UACF;AAAA,UACA,EAAE,QAAQ,MAAM,GAAG,KAAK;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEAD,QAAO,KAAK,OAAO;AAAA,MACnB,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,MAEX;AAAA,MACA;AAAA,MAEA,CAAC,UAAU;AAAA,IACb;AAAA,EACF;AACF;;;AI9MA;AAAA,EACE,UAAAM;AAAA,EAEA,qBAAAC;AAAA,OAIK;AACP,SAAS,QAAAC,aAAwB;AACjC,SAAS,QAAAC,aAAY;AACrB,SAAS,aAAAC,kBAAiB;AAanB,IAAe,cAAf,cAAmCC,mBAAkB;AAAA,EAChD,YACR,MACA,MACA,MACA,MAKS,aAKA,UAKA,MAKA,QAEQ,UACA,YACjB;AACA,UAAM,MAAM,MAAM,MAAM,IAAI;AApBnB;AAKA;AAKA;AAKA;AAEQ;AACA;AAAA,EAGnB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAkC;AACpC,WAAOC,QAAO;AAAA,MACZ,MAAM;AAAA,MACN,aAAa,KAAK;AAAA,MAClB,UAAU,KAAK;AAAA,MACf,SAAS,KAAK,QAAQ;AAAA,IACxB,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,kBAA+C;AACjD,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAA2B;AAC7B,WAAO,KAAK,SAAS,MAAM,aAAW;AACpC,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,+BAA+B;AAAA,MACjD;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,YAA+B;AACjC,WAAO,KAAK,WAAW,MAAM,eAAa;AACxC,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,kCAAkC;AAAA,MACpD;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,OAAO,MAAc,MAAuB,MAA6C;AAC9F,WAAO,IAAI,mBAAmB,MAAM,MAAM,IAAI;AAAA,EAChD;AACF;AAEA,IAAM,qBAAN,cAAiC,YAAY;AAAA,EAC3C,YAAY,MAAc,MAAuB,MAAgC;AAC/E,UAAM,EAAE,YAAY,SAAS,QAAQ,SAAS,UAAU,IAAI;AAAA,MAC1D;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN;AAAA,IACF;AAEA,UAAM,cAAcA,QAAO,EAAE,MAAM,YAAY,SAAS,QAAQ,CAAC,EAAE;AAAA,MACjE,OAAO,EAAE,MAAAC,OAAM,YAAAC,aAAY,SAAAC,UAAS,SAAAC,SAAQ,MAAM;AAChD,cAAM,eAAe,KAAK,UAAUH,MAAK,SAAS,IAAI;AAEtD,eAAO,KAAKA,MAAK,QAAQI,MAAK,GAAG,mBAAmBA,MAAK,GAAG;AAAA,UAC1D;AAAA,UACA;AAAA,YACE,UAAU,YAAYJ,MAAK,OAAO,YAAYA,OAAM,IAAI;AAAA,YACxD,MAAMK;AAAA,cACJ;AAAA,gBACE,aAAaF,UAAS,SAAS,QAAQ;AAAA,gBACvC,UAAU;AAAA,kBACR,UAAU,CAACH,MAAK,QAAQ,EAAE,OAAO,IAAI;AAAA,kBACrC,MAAM;AAAA,oBACJ,YAAYC,YAAW,IAAI,eAAa,kBAAkB,WAAW,IAAI,CAAC;AAAA,oBAC1E,SAAAC;AAAA,kBACF;AAAA,gBACF;AAAA,gBACA,UAAU,CAACF,MAAK,QAAQ,EAAE,aAAa,OAAO,IAAI;AAAA,cACpD;AAAA,cACAM,MAAKN,OAAM,uBAAuB;AAAA,YACpC;AAAA,UACF;AAAA,UACA,EAAE,QAAQ,MAAM,GAAG,KAAK;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEAD,QAAO,KAAK,OAAO,EAAE;AAAA,MACrB,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MAEZ;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AC9JA,SAAS,kBAAoC;AAC7C;AAAA,EACE,qBAAAQ;AAAA,EACA,aAAAC;AAAA,EACA,UAAAC;AAAA,OAOK;AACP,SAAS,YAAY,MAAM,OAAO,iBAAiB;AACnD,SAAS,aAAa,uBAA2C;AACjE,OAAoB;AA2Vb,IAAe,gBAAf,MAAe,uBAAsBC,mBAAkB;AAAA;AAAA;AAAA;AAAA,EAI5C;AAAA,EAEN,YAAY,MAAc,MAAiC,MAAwB;AAC3F,UAAM,sBAAsB,MAAM,MAAM,IAAI;AAE5C,UAAM,iBAAiBC,QAAO,IAAI,EAAE,MAAM,CAAAC,UAAQ;AAChD,YAAM,eAAeC,WAAUD,MAAK,aAAaA,MAAK,YAAY;AAClE,YAAM,cAAcC,WAAUD,MAAK,YAAYA,MAAK,WAAW;AAE/D,YAAM,YAAYC,WAAUD,MAAK,YAAY,YAAYA,MAAK,YAAY,WAAW;AACrF,YAAM,kBAAkB,UAAU,IAAI,cAAY,YAAY,QAAQ,CAAC;AAEvE,YAAM,qBAAqB,gBACxB,OAAO,YAAU,OAAO,SAAS,gBAAgB,EAAE,EACnD,IAAI,YAAU,eAAc,oBAAoB,MAAM,CAAC;AAE1D,YAAM,qBAAqB,gBACxB,OAAO,YAAU,OAAO,SAAS,gBAAgB,OAAO,EACxD,IAAI,YAAU,OAAO,QAAQ;AAEhC,YAAM,mBAAyC,CAAC;AAEhD,UAAIA,MAAK,cAAc;AACrB,yBAAiB,KAAK;AAAA,UACpB,YAAY,CAAC,aAAa;AAAA,UAC1B,WAAW,CAAC,EAAE,aAAa,EAAE,WAAW,WAAW,EAAE,CAAC;AAAA,UACtD,OAAO,CAAC,EAAE,MAAM,IAAI,UAAU,MAAM,CAAC;AAAA,UACrC,KAAK;AAAA,UACL,OAAO,CAAC;AAAA,UACR,OAAO,CAAC;AAAA,UACR,UAAU,CAAC;AAAA,QACb,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,QACL,GAAGA;AAAA,QAEH,aAAaA,MAAK,WAAW,0BAA0BA,MAAK,QAAQ,IAAI,CAAC;AAAA,QAEzE,eAAeA,MAAK,iBAAiB;AAAA,QACrC,gBAAgBA,MAAK,kBAAkB;AAAA,QAEvC,oBAAoBA,MAAK,sBAAsB;AAAA,QAE/C,cAAc,aAAa,IAAI,WAAS;AAAA,UACtC,KAAK,KAAK,WAAW;AAAA,UACrB,OAAOC,WAAU,KAAK,UAAU,KAAK,SAAS;AAAA,UAC9C,OAAO,CAAC;AAAA,UACR,UAAUA,WAAU,KAAK,aAAa,KAAK,YAAY;AAAA,UACvD,YAAYA,WAAU,KAAK,eAAe,KAAK,cAAc;AAAA,UAC7D,WAAWA,WAAU,KAAK,cAAc,KAAK,aAAa;AAAA,UAC1D,OAAOA,WAAU,KAAK,QAAQ,KAAK,OAAO;AAAA,QAC5C,EAAE;AAAA,QAEF,aAAa,YACV,IAAI,UAAQ;AACX,iBAAO;AAAA,YACL,KAAK,KAAK,SAAS;AAAA,YACnB,OAAOA,WAAU,KAAK,QAAQ,KAAK,OAAO,EAAE,OAAO,kBAAkB;AAAA,YACrE,OAAOA,WAAU,KAAK,QAAQ,KAAK,OAAO,EAAE,OAAO,kBAAkB;AAAA,YACrE,UAAUA,WAAU,KAAK,WAAW,KAAK,UAAU;AAAA,YACnD,YAAYA,WAAU,KAAK,aAAa,KAAK,YAAY;AAAA,YACzD,WAAWA,WAAU,KAAK,YAAY,KAAK,WAAW;AAAA,YACtD,OAAOA,WAAU,KAAK,QAAQ,KAAK,OAAO;AAAA,UAC5C;AAAA,QACF,CAAC,EACA,OAAO,gBAAgB;AAAA,MAC5B;AAAA,IACF,CAAC;AAED,SAAK,gBAAgB,eAAe,MAAM,CAAAD,UAAQ;AAChD,aAAOD;AAAA,QACL,KAAK,OAAO,MAAMC,OAAqC,EAAE,GAAG,MAAM,QAAQ,KAAK,CAAC;AAAA,MAClF;AAAA,IACF,CAAC;AAED,SAAK,gBAAgB,EAAE,eAAe,KAAK,cAAc,CAAC;AAAA,EAC5D;AAAA,EAEA,OAAe,oBAAoB,QAA+B;AAChE,QAAI,OAAO,cAAc,GAAG;AAC1B,aAAO,GAAG,OAAO,QAAQ;AAAA,IAC3B;AAEA,WAAO,GAAG,OAAO,QAAQ;AAAA,EAC3B;AAAA,EAQA,OAAwB,gBAAgB,CAAC,QAAQ;AAAA,EAEjD,OAAO,OACL,MACA,MACA,MACuB;AACvB,WAAOD,QAAO,IAAI,EAAE,MAAM,OAAMC,UAAQ;AACtC,UAAI,CAACA,MAAK,OAAO,CAAC,eAAc,cAAc,SAASA,MAAK,GAAG,GAAG;AAChE,eAAO,IAAI,oBAAoB,MAAMA,OAAM,IAAI;AAAA,MACjD;AAEA,YAAM,WAAW,GAAG,WAAWA,MAAK,GAAG,CAAC;AACxC,YAAM,aAAc,MAAM,OAAO,cAAcA,MAAK,GAAG;AAQvD,YAAM,YAAY,WAAW,QAAQ;AACrC,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,+BAA+BA,MAAK,GAAG,EAAE;AAAA,MAC3D;AAEA,aAAO,IAAI,UAAU,MAAMA,OAAM,IAAI;AAAA,IACvC,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,qBACL,WACA,YACA,MACuB;AACvB,WAAO,eAAc;AAAA,MACnB;AAAA,MACA;AAAA,QACE;AAAA,QACA,KAAKD,QAAO,UAAU,EAAE,KAAK;AAAA,QAE7B,aAAa;AAAA,QACb,UAAU,CAAC;AAAA,QAEX,aAAa,EAAE,eAAe,UAAU;AAAA,QACxC,YAAY,EAAE,aAAa,UAAU;AAAA,MACvC;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,mBACL,WACA,YACA,MACuB;AACvB,WAAO,eAAc;AAAA,MACnB;AAAA,MACA;AAAA,QACE;AAAA,QACA,KAAKA,QAAO,UAAU,EAAE,KAAK;AAAA,QAE7B,aAAa;AAAA,QAEb,oBAAoB;AAAA,MACtB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,aACL,WACA,YACA,MACuB;AACvB,WAAO,eAAc;AAAA,MACnB;AAAA,MACA;AAAA,QACE;AAAA,QACA,KAAKA,QAAO,UAAU,EAAE,KAAK;AAAA,QAE7B,aAAa;AAAA,QAEb,cAAc;AAAA,MAChB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,eACL,WACA,YACA,MACuB;AACvB,WAAO,eAAc;AAAA,MACnB;AAAA,MACA;AAAA,QACE;AAAA,QACA,KAAKA,QAAO,UAAU,EAAE,KAAK;AAAA,QAE7B,aAAa;AAAA,QAEb,YAAY,EAAE,OAAO,KAAK;AAAA,MAC5B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,sBAAN,MAAM,6BAA4B,cAAc;AAAA,EAC3C,OACR,MACA,MACA,MACU;AACV,UAAM,UAAU,qBAAoB,mBAAmB,IAAI;AAC3D,UAAM,SAAS,qBAAoB,kBAAkB,IAAI;AAEzD,UAAM,cAAwB,CAAC;AAE/B,QAAI,QAAQ,SAAS,KAAK,KAAK,gBAAgB;AAC7C,kBAAY,KAAK,SAAS;AAAA,IAC5B;AAEA,QAAI,OAAO,SAAS,KAAK,KAAK,eAAe;AAC3C,kBAAY,KAAK,QAAQ;AAAA,IAC3B;AAEA,WAAO,IAAI,WAAW,GAAG;AAAA,MACvB;AAAA,MACA;AAAA,QACE,UAAU,UAAU,YAAY,MAAM,IAAI,GAAG;AAAA,UAC3C,aAAa,KAAK,cACd,EAAE,6BAA6B,KAAK,YAAY,IAChD;AAAA,QACN,CAAC;AAAA,QACD,MAAM;AAAA,UACJ,aAAa,KAAK;AAAA,UAClB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAe,kBAAqD;AAAA,IAClE,MAAM;AAAA,IACN,QAAQ,CAAC,cAAc,iBAAiB,gBAAgB;AAAA,EAC1D;AAAA,EAEA,OAAe,mBACb,MACsD;AACtD,WAAO,KAAK,aAAa,IAAI,WAAS;AAAA,MACpC,MAAM,KAAK,MAAM,SAAY,qBAAoB,gBAAgB,IAAI;AAAA,MACrE,OAAO,qBAAoB,SAAS,KAAK,KAAK;AAAA,IAChD,EAAE;AAAA,EACJ;AAAA,EAEA,OAAe,kBACb,MACqD;AAGrD,UAAM,eAAe,KAAK,YAAY,KAAK,UAAQ,KAAK,MAAM,SAAS,CAAC;AACxE,QAAI,cAAc;AAChB,aAAO,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,qBAAoB,gBAAgB,CAAC,EAAE,CAAC;AAAA,IACpE;AAEA,UAAM,aAAkE,CAAC;AAEzE,QAAI,KAAK,oBAAoB;AAE3B,iBAAW,KAAK,EAAE,IAAI,CAAC,EAAE,SAAS,EAAE,MAAM,YAAY,EAAE,CAAC,EAAE,CAAC;AAAA,IAC9D;AAEA,WAAO,KAAK,YACT,IAAI,UAAQ;AACX,aAAO;AAAA,QACL,IAAI,KAAK,MAAM,SAAY,qBAAoB,gBAAgB,IAAI;AAAA,QACnE,OAAO,qBAAoB,SAAS,KAAK,KAAK;AAAA,MAChD;AAAA,IACF,CAAC,EACA,OAAO,UAAU;AAAA,EACtB;AAAA,EAEA,OAAe,gBAEb,MAC+C;AAC/C,WAAO;AAAA,MACL,GAAG,qBAAoB,gBAAgB,IAAI;AAAA,MAC3C,GAAG,qBAAoB,mBAAmB,IAAI;AAAA,MAC9C,GAAG,qBAAoB,oBAAoB,IAAI;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,OAAe,gBACb,MAC+C;AAC/C,WAAO,KAAK,MAAM,IAAI,WAAS,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE;AAAA,EACvD;AAAA,EAEA,OAAe,mBACb,MAC+C;AAC/C,WAAO,KAAK,SAAS,IAAI,aAAW;AAClC,YAAM,WAAW,0BAA0B,OAAO;AAElD,aAAO;AAAA,QACL,mBAAmB,2BAA2B,QAAQ,SAAS,SAAS;AAAA,QACxE,aAAa;AAAA,MACf;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,OAAe,oBACb,MAC+C;AAC/C,UAAM,gBAAgB,KAAK,UAAU,IAAI,eAAa;AAAA,MACpD,aAAa,0BAA0B,QAAQ;AAAA,IACjD,EAAE;AAEF,UAAM,iBAAiB,KAAK,WAAW,IAAI,qBAAoB,mBAAmB;AAElF,QAAI,eAAe,WAAW,GAAG;AAE/B,aAAO;AAAA,IACT;AAEA,QAAI,cAAc,WAAW,GAAG;AAE9B,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,MACL,cAAc,IAAI,kBAAgB;AAChC,eAAO,eAAe,IAAI,mBAAiB,MAAM,cAAc,aAAa,CAAC;AAAA,MAC/E,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,OAAe,oBAEb,WAC6C;AAC7C,UAAM,gBAAgB,gCAAgC,SAAS;AAC/D,UAAM,oBAAoB,2BAA2B,aAAa;AAElE,WAAO,EAAE,kBAAkB;AAAA,EAC7B;AAAA,EAEA,OAAe,SACb,OAC+C;AAC/C,WAAO,MAAM,IAAI,UAAQ;AACvB,UAAI,UAAU,MAAM;AAClB,eAAO;AAAA,UACL,MAAM,KAAK;AAAA,UACX,UAAU,KAAK,YAAY;AAAA,QAC7B;AAAA,MACF;AAEA,aAAO;AAAA,QACL,MAAM,KAAK,MAAM,CAAC;AAAA,QAClB,SAAS,KAAK,MAAM,CAAC;AAAA,QACrB,UAAU,KAAK,YAAY;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACztBA,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AACxB;AAAA,EACE,aAAAG;AAAA,EAEA,UAAAC;AAAA,EACA;AAAA,OAGK;AAyBA,SAAS,eAAe,MAAyD;AACtF,QAAM,SAASC,QAAO,EAAE,MAAM,eAAeA,QAAO,KAAK,SAAS,EAAE,SAAS,KAAK,CAAC,EAAE;AAAA,IACnF,CAAC,EAAE,MAAAC,OAAM,cAAc,MAAM;AAC3B,YAAMC,WAAU,cAAc;AAAA,QAC5B,GAAGD;AAAA,QACH,aAAa;AAAA,UACX,kCAAkCA,MAAK,YAAY,UAAU;AAAA,QAC/D;AAAA,QACA,SAASA,MAAK,YAAY;AAAA,MAC5B,CAAC;AAED,YAAM,aAAaE,WAAUF,MAAK,MAAMA,MAAK,KAAK,EAAE,IAAI,UAAQ;AAC9D,eAAO,UAAU,OAAO,MAAM;AAAA,UAC5B,UAAUA,MAAK,YAAY;AAAA,UAC3B,MAAM;AAAA,UACN,OAAOA,MAAK,YAAY,QAAQ;AAAA,QAClC,CAAC;AAAA,MACH,CAAC;AAED,YAAM,kBAA2C,CAAC;AAElD,UAAIA,MAAK,YAAY,QAAQ,SAAS;AACpC,cAAM,cAAc,kBAAkBA,MAAK,YAAY,QAAQ,QAAQ,QAAQ;AAE/E,wBAAgB;AAAA,UACd,cAAc;AAAA,YACZ,sBAAsB,WAAWA,MAAK,YAAY,QAAQ,QAAQ,QAAQ,CAAC;AAAA,YAC3E;AAAA,cACE,KAAKA,MAAK,YAAY,QAAQ,QAAQ,YAAY;AAAA,cAClD,WAAWA,MAAK;AAAA,cAEhB,aAAa,2CAA2C,WAAW;AAAA,cAEnE,aAAa;AAAA,gBACX,eAAeA,MAAK,YAAY,QAAQ,QAAQ,SAAS;AAAA,gBACzD,cAAcA,MAAK,YAAY,QAAQ,QAAQ,KAAK;AAAA,cACtD;AAAA,YACF;AAAA,YACA,EAAE,UAAUA,MAAK,SAAS;AAAA,UAC5B;AAAA,UAEA,cAAc;AAAA,YACZ,mBAAmB,aAAa;AAAA,YAChC;AAAA,cACE,KAAKA,MAAK,YAAY,QAAQ,QAAQ,YAAY;AAAA,cAClD,WAAWA,MAAK,YAAY,QAAQ,QAAQ,SAAS;AAAA,cACrD,UAAUA,MAAK,YAAY,QAAQ,QAAQ,KAAK;AAAA,cAEhD,aAAa,0CAA0C,aAAa;AAAA,cAEpE,YAAY;AAAA,gBACV,aAAaA,MAAK;AAAA,cACpB;AAAA,YACF;AAAA,YACA,EAAE,UAAUA,MAAK,SAAS;AAAA,UAC5B;AAAA,QACF;AAAA,MACF;AAEA,aAAOD,QAAO;AAAA,QACZ,SAAAE;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO,UAAU,MAAM;AACzB;AAWO,SAAS,sBACd,SACA,WACA,MACA,QACA,UAC+B;AAC/B,SAAO,eAAe;AAAA,IACpB,MAAM;AAAA,IACN;AAAA,IAEA,MAAM,KAAK;AAAA,IAEX,aAAa,OAAO;AAAA,IACpB,aAAa,OAAO,WAAW;AAAA,IAC/B;AAAA,EACF,CAAC;AACH;AAeO,SAAS,cAAc,MAAqD;AACjF,SAAOF,QAAO,IAAI,EAAE,MAAM,CAAAC,UAAQ;AAChC,QAAIA,MAAK,YAAY,OAAOA,MAAK,QAAQ,YAAY,IAAI;AACvD,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,WAAO,IAAI,QAAQ,GAAG;AAAA,MACpBA,MAAK;AAAA,MACL;AAAA,QACE,UAAU;AAAA,UACR,MAAMA,MAAK;AAAA,UACX,WAAW,gCAAgCA,MAAK,SAAS;AAAA,UACzD,aAAaA,MAAK;AAAA,QACpB;AAAA,QACA,MAAM;AAAA,UACJ,kBAAkBD,QAAOC,MAAK,OAAO,EAAE;AAAA,UACvC,WAAWE,WAAUF,MAAK,MAAMA,MAAK,KAAK,EAAE,IAAI,UAAQ;AACtD,kBAAM,iBAAiB,KAAK,QAAQ,OAAO,UAAU;AAErD,mBAAO;AAAA,cACL,MAAM,SAAS,cAAc;AAAA,cAC7B,MAAMD,QAAOC,MAAK,OAAO,EAAE;AAAA,cAC3B,UAAU;AAAA,cACV,UAAU;AAAA,cACV,KAAK;AAAA,gBACH,MAAM;AAAA,gBACN,iBAAiB,CAAC,EAAE,MAAM,eAAe,CAAC;AAAA,cAC5C;AAAA,YACF;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,MACA,EAAE,UAAUA,MAAK,UAAU,aAAaA,MAAK,UAAU;AAAA,IACzD;AAAA,EACF,CAAC;AACH;;;ACvLA,SAAS,QAAAG,aAAY;AACrB,SAAS,OAAO,aAAAC,kBAAkC;AAClD;AAAA,EACE,qBAAAC;AAAA,EACA,UAAAC;AAAA,OAKK;AACP,SAAS,YAAY;AACrB,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,MAAM,mBAAAC,wBAAuB;;;ACkDtC,IAAM,+BAAkE;AAAA,EACtE,oBAAoB,CAAC;AAAA,EACrB,mBAAmB,CAAC;AAAA,EACpB,UAAU,CAAC;AACb;AAEO,IAAM,yBAAoD;AAAA,EAC/D,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,cAAc,CAAC;AAAA,EACf,gBAAgB,CAAC;AAAA,EACjB,SAAS,CAAC;AAAA,EACV,SAAS,CAAC;AAAA,EACV,cAAc,CAAC;AAAA,EACf,aAAa,CAAC;AAChB;;;ADvCO,IAAM,eAAN,cAA2BC,mBAAkB;AAAA;AAAA;AAAA;AAAA,EAIzC;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,EAET,YAAY,MAAc,MAAwB,MAAiC;AACjF,UAAM,8BAA8B,MAAM,MAAM,IAAI;AAEpD,UAAM,oBAAoB;AAAA,MACxBC,QAAO,IAAI;AAAA,MACX,MAAM,CAAAC,UAAQC,WAAUD,MAAK,aAAaA,MAAK,YAAY,CAAC;AAAA,MAC5D,MAAM,CAAAA,UAAQE,WAAU,wBAAwB,GAAGF,KAAI,CAAC;AAAA,IAC1D;AAEA,SAAK,eAAe,KAAK;AACzB,SAAK,cAAc,kBAAkB;AAErC,SAAK,YAAYD,QAAO,EAAE,mBAAmB,KAAK,CAAC,EAAE,MAAM,CAAC,EAAE,mBAAAI,oBAAmB,MAAAH,MAAK,MAAM;AAC1F,aAAO,IAAII,MAAK,GAAG;AAAA,QACjB;AAAA,QACA;AAAA,UACE,UAAU,YAAYJ,OAAM,IAAI;AAAA,UAChC,MAAM,iBAAiB,KAAK,cAAcG,kBAAiB;AAAA,QAC7D;AAAA,QACA,EAAE,GAAG,MAAM,QAAQ,KAAK;AAAA,MAC1B;AAAA,IACF,CAAC;AAED,SAAK,UAAU,kBAAkB,QAAQ,MAAM,aAAW;AACxD,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,UACE,MAAM,KAAK,UAAU,SAAS;AAAA,UAE9B,WAAW;AAAA,YACT,MAAM,KAAK,UAAU,SAAS;AAAA,YAC9B,aAAa;AAAA;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,SAAK,eAAe,kBAAkB,aAAa,MAAM,kBAAgB;AACvE,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,UACE,QAAQ,KAAK;AAAA,UACb,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF,CAAC;AAED,SAAK,gBAAgB;AAAA,MACnB,WAAW,KAAK;AAAA,MAChB,SAAS,KAAK;AAAA,MACd,cAAc,KAAK;AAAA,MACnB,aAAa,KAAK;AAAA,IACpB,CAAC;AAAA,EACH;AACF;AAEA,SAAS,iBACP,cACA,aACwB;AACxB,QAAM,aAAqC,CAAC;AAC5C,QAAM,UAAoB,CAAC;AAE3B,QAAM,0BAA0B,YAAY,YAAY;AAExD,MAAI,wBAAwB,mBAAmB,SAAS,GAAG;AACzD,eAAW,yBAAyB,IAAI;AAAA,MACtC;AAAA,MACA,wBAAwB;AAAA,IAC1B;AAEA,YAAQ,KAAK;AAAA;AAAA;AAAA;AAAA,KAIZ;AAAA,EACH;AAEA,MAAI,OAAO,KAAK,wBAAwB,iBAAiB,EAAE,SAAS,GAAG;AACrE,eAAW,OAAO,wBAAwB,mBAAmB;AAC3D,iBAAW,eAAe,GAAG,EAAE,IAAI,wBAAwB,kBAAkB,GAAG;AAEhF,cAAQ,KAAK;AAAA,8CAC2B,GAAG;AAAA,+BAClB,GAAG;AAAA,sCACI,GAAG;AAAA,OAClC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,wBAAwB,SAAS,SAAS,GAAG;AAC/C,eAAW,qBAAqB,IAAI;AAAA,MAClC;AAAA,MACA,wBAAwB;AAAA,IAC1B;AAEA,YAAQ,KAAK;AAAA;AAAA;AAAA;AAAA,KAIZ;AAAA,EACH;AAEA,MAAI,OAAO,KAAK,YAAY,YAAY,EAAE,SAAS,GAAG;AACpD,eAAW,OAAO,YAAY,cAAc;AAC1C,iBAAW,SAAS,GAAG,EAAE,IAAI,YAAY,aAAa,GAAG;AAEzD,cAAQ,KAAK;AAAA,wCACqB,GAAG;AAAA,yBAClB,GAAG;AAAA,gCACI,GAAG;AAAA,OAC5B;AAAA,IACH;AAAA,EACF;AAEA,MAAI,OAAO,KAAK,YAAY,cAAc,EAAE,SAAS,GAAG;AACtD,UAAM,iBAA2B,CAAC;AAElC,eAAW,OAAO,YAAY,gBAAgB;AAC5C,iBAAW,WAAW,GAAG,EAAE,IAAI,YAAY,eAAe,GAAG;AAE7D,qBAAe,KAAK;AAAA,0CACgB,GAAG;AAAA,2BAClB,GAAG;AAAA,kCACI,GAAG;AAAA,OAC9B;AAAA,IACH;AAEA,YAAQ,KAAK;AAAA;AAAA,QAET,eAAe,IAAI,OAAK,EAAE,KAAK,CAAC,EAAE,KAAK,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,KAKjD;AAAA,EACH;AAEA,aAAW,OAAO,YAAY,SAAS;AACrC,eAAW,GAAG,IAAI,YAAY,QAAQ,GAAG;AAAA,EAC3C;AAEA,aAAW,eAAe,IAAIE,iBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAS5C,QAAQ,IAAI,OAAK,EAAE,KAAK,CAAC,EAAE,KAAK,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,GAKxC;AAED,SAAO;AACT;AAEA,SAAS,yBAAyB,cAAkC,UAA4B;AAC9F,MAAI,iBAAiB,UAAU;AAC7B,WAAO;AAAA;AAAA;AAAA;AAAA,2BAIgB,SAAS,KAAK,GAAG,CAAC;AAAA;AAAA,EAE3C,OAAO;AACL,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA,2BAKgB,SAAS,KAAK,GAAG,CAAC;AAAA;AAAA,EAE3C;AACF;;;AEjPA,SAAiB,UAAAC,eAA0B;AAC3C,SAAS,SAAAC,cAAa;AAsBf,SAAS,sBAAsB,SAA6C;AACjF,SAAOD,QAAO,OAAO,EAAE,MAAM,CAAAE,aAAW;AACtC,UAAM,QACJA,SAAQ,OAAO,iBAAiB,WAC5B,mFACA;AAEN,WAAO;AAAA,MACL;AAAA,MACA,SAAS,CAAC,0BAA0B,YAAYA,SAAQ,IAAI,EAAE;AAAA,MAE9D,GAAGA;AAAA,MAEH,cAAcD,OAAMC,SAAQ,OAAO,cAAcA,SAAQ,YAAY;AAAA,MACrE,SAASD,OAAMC,SAAQ,OAAO,SAASA,SAAQ,OAAO;AAAA,MACtD,aAAaD,OAAMC,SAAQ,OAAO,aAAaA,SAAQ,WAAW;AAAA,IACpE;AAAA,EACF,CAAC;AACH;;;AC3CA,SAAS,aAAyB;AAClC;AAAA,EACE,qBAAAC;AAAA,EACA,aAAAC;AAAA,EAEA,UAAAC;AAAA,OAIK;AACP,SAAS,aAAAC,YAAW,QAAAC,aAAY;AAchC,IAAM,eAAe,CAAC,GAAG,iBAAiB,aAAa,YAAY;AAE5D,IAAM,MAAN,cAAkBC,mBAAkB;AAAA;AAAA;AAAA;AAAA,EAIzB;AAAA,EAEhB,YAAY,MAAc,MAAe,MAAiC;AACxE,UAAM,qBAAqB,MAAM,MAAM,IAAI;AAE3C,SAAK,MAAMC,SAAO,IAAI,EAAE,MAAM,CAAAC,UAAQ;AACpC,YAAM,aAAaC,WAAUD,MAAK,WAAWA,MAAK,UAAU;AAE5D,aAAO,IAAI,MAAM,GAAG;AAAA,QAClB;AAAA,QACA;AAAA,UACE,UAAU,YAAYA,OAAM,IAAI;AAAA,UAChC,MAAME;AAAA,YACJ;AAAA,cACE,UAAU;AAAA,gBACR,MAAM;AAAA,kBACJ,YAAY,WAAW,IAAI,eAAa,kBAAkB,WAAW,IAAI,CAAC;AAAA,kBAE1E,SAAS,WACN,QAAQ,eAAaD,WAAU,UAAU,QAAQ,UAAU,OAAO,CAAC,EACnE,IAAI,iBAAiB;AAAA,kBAExB,eAAe;AAAA,gBACjB;AAAA,cACF;AAAA,YACF;AAAA,YACAE,MAAKH,OAAM,YAAY;AAAA,UACzB;AAAA,QACF;AAAA,QACA,EAAE,QAAQ,MAAM,GAAG,KAAK;AAAA,MAC1B;AAAA,IACF,CAAC;AAED,SAAK,gBAAgB,EAAE,KAAK,KAAK,IAAI,CAAC;AAAA,EACxC;AACF;;;AChEA,SAAS,SAAAI,cAAyB;AAClC;AAAA,EACE,qBAAAC;AAAA,EACA,aAAAC;AAAA,EAEA,UAAAC;AAAA,OAIK;AACP,SAAS,aAAAC,YAAW,QAAAC,aAAY;AAmBhC,IAAM,mBAAmB,CAAC,GAAG,iBAAiB,aAAa,YAAY;AAEhE,IAAM,UAAN,cAAsBC,mBAAkB;AAAA;AAAA;AAAA;AAAA,EAI7B;AAAA,EAEhB,YAAY,MAAc,MAAmB,MAAiC;AAC5E,UAAM,yBAAyB,MAAM,MAAM,IAAI;AAE/C,SAAK,UAAUC,SAAO,IAAI,EAAE,MAAM,CAAAC,UAAQ;AACxC,YAAM,aAAaC,WAAUD,MAAK,WAAWA,MAAK,UAAU;AAE5D,aAAO,IAAIE,OAAM,GAAG;AAAA,QAClB;AAAA,QACA;AAAA,UACE,UAAU,YAAYF,OAAM,IAAI;AAAA,UAEhC,MAAMG;AAAA,YACJ;AAAA,cACE,aAAa;AAAA,gBACX,MAAM;AAAA,kBACJ,UAAU;AAAA,oBACR,MAAM;AAAA,sBACJ,YAAY,WAAW,IAAI,eAAa,kBAAkB,WAAW,IAAI,CAAC;AAAA,sBAE1E,SAAS,WACN,QAAQ,eAAaF,WAAU,UAAU,QAAQ,UAAU,OAAO,CAAC,EACnE,IAAI,iBAAiB;AAAA,oBAC1B;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,cAEA,UAAUD,MAAK;AAAA,YACjB;AAAA,YACAI,MAAKJ,OAAM,gBAAgB;AAAA,UAC7B;AAAA,QACF;AAAA,QACA,EAAE,QAAQ,MAAM,GAAG,KAAK;AAAA,MAC1B;AAAA,IACF,CAAC;AAED,SAAK,gBAAgB,EAAE,SAAS,KAAK,QAAQ,CAAC;AAAA,EAChD;AACF;","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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAGA;AAAA,EACE,UAAAA;AAAA,EAIA,qBAAAC;AAAA,EAKA;AAAA,OACK;AACP,SAAS,YAAmB;AAC5B,SAAS,QAAAC,aAAY;AACrB,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,uBAAuB;;;ACjBhC,SAAS,QAAAC,aAAwB;AACjC,SAAS,WAAW,UAAAC,eAAwD;AAC5E,SAAS,QAAQ,KAAK,QAAAC,aAAY;;;ACFlC,SAAS,YAAwB;AACjC;AAAA,EACE;AAAA,EAEA;AAAA,OAKK;AACP,SAAS,iBAAiB;AAC1B,SAAS,YAAY;AAyBrB,IAAM,iCAAiC,CAAC,GAAG,iBAAiB,QAAQ,SAAS;AAEtE,IAAe,wBAAf,cAA6C,kBAAkB;AAAA,EAC1D,YACR,MACA,MACA,MACA,MAKS,aAKA,UAKA,MAKA,QACT;AACA,UAAM,MAAM,MAAM,MAAM,IAAI;AAjBnB;AAKA;AAKA;AAKA;AAAA,EAGX;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAA4C;AAC9C,WAAO,OAAO;AAAA,MACZ,MAAM;AAAA,MACN,aAAa,KAAK;AAAA,MAClB,UAAU,KAAK;AAAA,IACjB,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,OACL,MACA,MACA,MACuB;AACvB,WAAO,IAAI,6BAA6B,MAAM,MAAM,IAAI;AAAA,EAC1D;AAAA,EAEA,OAAO,GACL,MACA,QACA,MACuB;AACvB,WAAO,IAAI;AAAA,MACT;AAAA,MACA,OAAO,MAAM,EAAE;AAAA,MACf,OAAO,MAAM,EAAE;AAAA,MACf;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,+BAAN,cAA2C,sBAAsB;AAAA,EACtE,YAAY,MAAc,MAAiC,MAA6B;AACtF,UAAM,MAAM,OAAO,IAAI,EAAE,MAAM,CAAAC,UAAQ;AACrC,aAAO,IAAI,KAAK,GAAG;AAAA,QACjB;AAAA,QACA;AAAA,UACE,UAAU,YAAYA,OAAM,IAAI;AAAA,UAChC,MAAM;AAAA,YACJ;AAAA,cACE,aAAa,CAAC,eAAe;AAAA,cAC7B,WAAW;AAAA,gBACT,UAAU;AAAA,kBACR,SAASA,MAAK,QAAQ;AAAA,gBACxB;AAAA,cACF;AAAA,YACF;AAAA,YACA,KAAKA,OAAM,8BAA8B;AAAA,UAC3C;AAAA,QACF;AAAA,QACA;AAAA,MACF;AAAA,IACF,CAAC;AAED;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEA,OAAO,KAAK,OAAO,EAAE;AAAA,MACrB,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AACF;AAEO,IAAM,gCAAN,cAA4C,sBAAsB;AAAA,EACvE,YACE,MACA,IACA,aACA,MACA;AACA,UAAM,MAAM,OAAO,EAAE,EAAE,MAAM,OAAMC,QAAM;AACvC,YAAM,eAAe,KAAK,UAAU,KAAK,WAAW;AAEpD,aAAO,KAAK,GAAG,sBAAsB;AAAA;AAAA,QAEnC;AAAA,QACA,mBAAmBA,GAAE;AAAA,QACrB,EAAE,QAAQ,MAAM,UAAU,KAAK,SAAS;AAAA,MAC1C;AAAA,IACF,CAAC;AAED;AAAA,MACE;AAAA,MACA;AAAA,MACA,EAAE,IAAI,YAAY;AAAA,MAClB;AAAA,MAEA,OAAO,WAAW;AAAA,MAClB,IAAI;AAAA,MACJ,IAAI;AAAA,MACJ,IAAI;AAAA,IACN;AAAA,EACF;AACF;;;ADlHA,IAAM,qBAAqB;AAAA,EACzB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAqDO,SAAS,kBACd,WACA,cAC+B;AAC/B,QAAM,gBAAgB,UAAU,QAAQ;AAExC,SAAO;AAAA,IACL,GAAGC,MAAK,WAAW,kBAAkB;AAAA,IAErC,MAAM;AAAA,IACN,OAAO,UAAU,UAAU,MAAM,UAAU,KAAK;AAAA,IAEhD,cAAc,IAAI,UAAU,UAAU,aAAa,UAAU,YAAY,GAAG,cAAc;AAAA,IAE1F,KAAK;AAAA,MACH,UAAU,cAAc,wBAAwB,UAAU,WAAW,IAAI,CAAC;AAAA,MAC1E,UAAU,OAAO,CAAC;AAAA,IACpB;AAAA,IAEA,SAAS;AAAA,MACP;AAAA,QACE,UAAU,UAAU,mBAAmB,UAAU,kBAAkB;AAAA,QACnE;AAAA,MACF;AAAA,MACA,UAAU,WAAW,CAAC;AAAA,IACxB;AAAA,EACF;AACF;AAEO,SAAS,wBACd,aAC8B;AAC9B,QAAM,UAAwC,CAAC;AAE/C,aAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,WAAW,GAAG;AACvD,QAAI,CAAC,OAAO;AACV;AAAA,IACF;AAEA,QAAI,OAAO,UAAU,UAAU;AAC7B,cAAQ,KAAK,EAAE,MAAM,MAAM,CAAC;AAC5B;AAAA,IACF;AAEA,QAAI,YAAY,OAAO;AACrB,cAAQ,KAAK;AAAA,QACX;AAAA,QACA,WAAW;AAAA,UACT,cAAc;AAAA,YACZ,MAAM,MAAM,OAAO,SAAS;AAAA,YAC5B,KAAK,MAAM;AAAA,UACb;AAAA,QACF;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAEA,QAAI,eAAe,OAAO;AACxB,cAAQ,KAAK;AAAA,QACX;AAAA,QACA,WAAW;AAAA,UACT,iBAAiB;AAAA,YACf,MAAM,MAAM,UAAU,SAAS;AAAA,YAC/B,KAAK,MAAM;AAAA,UACb;AAAA,QACF;AAAA,MACF,CAAC;AACD;AAAA,IACF;AAEA,YAAQ,KAAK,EAAE,MAAM,WAAW,MAAM,CAAC;AAAA,EACzC;AAEA,SAAO;AACT;AAEO,SAAS,eAAe,aAAoE;AACjG,MAAI,YAAY,aAAa;AAC3B,WAAOA;AAAA,MACL;AAAA,QACE,GAAG;AAAA,QACH,MAAMC,QAAO,YAAY,MAAM,EAC5B,MAAM,iBAAiB,EACvB,MAAM,YAAUA,QAAO,OAAO,IAAI,CAAC;AAAA,MACxC;AAAA,MACA,CAAC,QAAQ;AAAA,IACX;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,MAAM,YAAY;AAAA,EACpB;AACF;AAEO,SAAS,qBACd,SACmC;AACnC,MAAI,mBAAmBC,MAAK,GAAG,WAAW;AACxC,WAAO;AAAA,MACL,cAAc;AAAA,QACZ,MAAM,QAAQ,SAAS;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,mBAAmBA,MAAK,GAAG,QAAQ;AACrC,WAAO;AAAA,MACL,WAAW;AAAA,QACT,MAAM,QAAQ,SAAS;AAAA,MACzB;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;AAEO,SAAS,kBAAkB,QAAwB;AACxD,MAAI,kBAAkB,uBAAuB;AAC3C,WAAO;AAAA,MACL,MAAM,OAAO,SAAS;AAAA,MACtB,uBAAuB;AAAA,QACrB,WAAW,OAAO,SAAS;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAEA,MAAI,kBAAkBA,MAAK,GAAG,uBAAuB;AACnD,WAAO;AAAA,MACL,MAAM,OAAO,SAAS;AAAA,MACtB,uBAAuB;AAAA,QACrB,WAAW,OAAO,SAAS;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAEA,MAAI,kBAAkBA,MAAK,GAAG,WAAW;AACvC,WAAO;AAAA,MACL,MAAM,OAAO,SAAS;AAAA,MACtB,WAAW;AAAA,QACT,MAAM,OAAO,SAAS;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,kBAAkBA,MAAK,GAAG,QAAQ;AACpC,WAAO;AAAA,MACL,MAAM,OAAO,SAAS;AAAA,MACtB,QAAQ;AAAA,QACN,YAAY,OAAO,SAAS;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;;;AE5QA,SAAS,aAAAC,kBAAiE;AAC1E,SAAS,qBAAAC,oBAAmB,UAAAC,eAAuC;AACnE,SAAS,gBAAgB;AAqBlB,IAAM,oBAAoB,CAAC,GAAG,iBAAiB,aAAa,YAAY;AA6BxE,IAAM,0BAA0B,CAAC,GAAG,mBAAmB,WAAW,WAAW;AAE7E,SAAS,sBAAsB,MAAc,MAAoB;AACtE,QAAM,SAAS;AAAA,IACb,0BAA0B;AAAA,EAC5B;AAEA,QAAM,aAAaC,QAAO,IAAI,EAAE,MAAM,CAAAC,UAAQC,WAAUD,MAAK,WAAWA,MAAK,UAAU,CAAC;AACxF,QAAM,UAAU,WAAW,MAAM,CAAAE,gBAAc;AAC7C,UAAM,mBAAmBA,YACtB,QAAQ,eAAaD,WAAU,UAAU,QAAQ,UAAU,OAAO,CAAC,EACnE,IAAI,iBAAiB;AAExB,UAAM,wBAAwBC,YAC3B,QAAQ,eAAa;AACpB,aAAOD,WAAU,UAAU,aAAa,UAAU,YAAY,EAC3D,IAAI,iBAAe;AAClB,eAAO,YAAY,cAAc,YAAY,SAAS;AAAA,MACxD,CAAC,EACA,OAAO,OAAO;AAAA,IACnB,CAAC,EACA,IAAI,iBAAiB;AAExB,WAAO,SAAS,CAAC,GAAG,kBAAkB,GAAG,qBAAqB,GAAG,YAAU,OAAO,IAAI;AAAA,EACxF,CAAC;AAED,SAAO,EAAE,QAAQ,YAAY,QAAQ;AACvC;AAEO,SAAS,4BACd,MACA,MACA,QACA,MACA;AACA,QAAM,EAAE,QAAQ,YAAY,QAAQ,IAAI,sBAAsB,MAAM,IAAI;AAExE,QAAM,UAAUF,QAAO,EAAE,MAAM,WAAW,CAAC,EAAE,MAAM,CAAC,EAAE,MAAAC,OAAM,YAAAE,YAAW,MAAM;AAC3E,QAAI,CAACF,MAAK,WAAW,CAACA,MAAK,WAAW;AACpC,aAAO;AAAA,IACT;AAEA,QAAIA,MAAK,OAAO,SAAS;AACvB,aAAO,QAAQ,GAAG,MAAMA,MAAK,MAAM,SAAS,EAAE,QAAQ,OAAO,GAAG,GAAG,KAAK,CAAC;AAAA,IAC3E;AAEA,QAAIA,MAAK,OAAO;AACd,aAAO;AAAA,IACT;AAEA,UAAM,QAAQE,YAAW,QAAQ,eAAaD,WAAU,UAAU,MAAM,UAAU,KAAK,CAAC;AAExF,WAAO,QAAQ;AAAA,MACb;AAAA,MACA;AAAA,QACE,GAAGD,MAAK;AAAA,QACR,UAAU;AAAA,QACV,SAASA,MAAK;AAAA,QACd,WAAWA,MAAK;AAAA,QAEhB;AAAA;AAAA,UAEE,CAACA,MAAK,SAAS,QAAQ,CAACA,MAAK,SAAS,QAClC,MAAM,IAAI,6BAA6B,IACvCA,MAAK,SAAS;AAAA;AAAA,MACtB;AAAA,MACA,EAAE,QAAQ,OAAO,GAAG,GAAG,KAAK;AAAA,IAC9B;AAAA,EACF,CAAC;AAED,QAAM,YAAYD,QAAO;AAAA,IACvB;AAAA,IACA;AAAA,EACF,CAAC,EAAE,MAAM,CAAC,EAAE,MAAAC,OAAM,SAAAG,SAAQ,MAAM;AAC9B,QAAI,CAACH,MAAK,aAAa,CAACG,UAAS;AAC/B,aAAO;AAAA,IACT;AAEA,QAAIH,MAAK,OAAO;AACd,aAAO;AAAA,IACT;AAEA,WAAO,IAAI;AAAA,MACT;AAAA,MACA;AAAA,QACE,GAAGA,MAAK;AAAA,QACR,MAAM;AAAA,UACJ,SAASG;AAAA,QACX;AAAA,MACF;AAAA,MACA,EAAE,QAAQ,OAAO,GAAG,GAAG,KAAK;AAAA,IAC9B;AAAA,EACF,CAAC;AAED,SAAO,EAAE,QAAQ,YAAY,SAAS,SAAS,UAAU;AAC3D;;;AH1GO,IAAe,aAAf,cAAkCC,mBAAkB;AAAA,EAC/C,YACR,MACA,MACiB,MACjB,MAKS,SAKA,UAKA,MAKA,QAEQ,UACA,YAKR,WACT;AACA,UAAM,MAAM,MAAM,MAAM,IAAI;AA/BX;AAMR;AAKA;AAKA;AAKA;AAEQ;AACA;AAKR;AAAA,EAGX;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAiC;AACnC,WAAOC,QAAO;AAAA,MACZ,MAAM;AAAA,MACN,aAAa,KAAK,QAAQ;AAAA,MAC1B,UAAU,KAAK;AAAA,MACf,MAAM,KAAK;AAAA,MACX,SAAS,KAAK,SAAS,MAAM,aAAW,SAAS,MAAM;AAAA,IACzD,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,kBAA+C;AACjD,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAA2B;AAC7B,WAAO,KAAK,SAAS,MAAM,aAAW;AACpC,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,+BAA+B;AAAA,MACjD;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,YAA+B;AACjC,WAAO,KAAK,WAAW,MAAM,eAAa;AACxC,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,kCAAkC;AAAA,MACpD;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,WAAqC;AACvC,WAAOA,QAAO;AAAA,MACZ,MAAM,KAAK,SAAS;AAAA,MACpB,OAAO,KAAK,SAAS;AAAA,MACrB,OAAO;AAAA,MACP,SAAS,CAAC,UAAU,MAAM,MAAM,uBAAuB,WAAW;AAAA,MAClE,OAAO;AAAA,QACL,eAAe,KAAK,QAAQ;AAAA,QAE5B,uBAAuB;AAAA,UACrB,MAAM;AAAA,UACN,SAAS;AAAA;AAAA;AAAA,uCAGoB,KAAK,SAAS,SAAS,eAAe,KAAK,SAAS,IAAI,OAAO,KAAK,KAAK,iBAAiB,MAAM;AAAA,YAC3H,MAAM,eAAe;AAAA,QACzB;AAAA,MACF;AAAA,MACA,KAAK;AAAA,QACH,YAAY;AAAA,MACd;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,OAAO,MAAc,MAAsB,MAA4C;AAC5F,WAAO,IAAI,kBAAkB,MAAM,MAAM,IAAI;AAAA,EAC/C;AACF;AAEA,IAAM,oBAAN,cAAgC,WAAW;AAAA,EACzC,YAAY,MAAc,MAAsB,MAAgC;AAC9E,UAAM,EAAE,QAAQ,YAAY,SAAS,SAAS,UAAU,IAAI;AAAA,MAC1D;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN;AAAA,IACF;AAEA,UAAM,aAAaA,QAAO,EAAE,MAAM,YAAY,QAAQ,CAAC,EAAE;AAAA,MACvD,OAAO,EAAE,MAAAC,OAAM,YAAAC,aAAY,SAAAC,SAAQ,MAAM;AACvC,cAAM,eAAe,KAAK,UAAUF,MAAK,QAAQ,IAAI;AAErD,eAAO,KAAKA,MAAK,QAAQ,KAAK,GAAG,kBAAkB,KAAK,GAAG;AAAA,UACzD;AAAA,UACA;AAAA,YACE,UAAU,YAAYA,MAAK,OAAO,YAAYA,OAAM,IAAI;AAAA,YACxD,MAAMG;AAAA,cACJ;AAAA,gBACE,UAAU;AAAA,kBACR,UAAU,CAACH,MAAK,QAAQ,EAAE,OAAO,IAAI;AAAA,kBACrC,MAAM;AAAA,oBACJ,YAAYC,YAAW,IAAI,eAAa,kBAAkB,WAAW,IAAI,CAAC;AAAA,oBAC1E,SAAAC;AAAA,kBACF;AAAA,gBACF;AAAA,gBACA,UAAU,CAACF,MAAK,QAAQ,EAAE,aAAa,OAAO,IAAI;AAAA,cACpD;AAAA,cACAI,MAAKJ,OAAM,uBAAuB;AAAA,YACpC;AAAA,UACF;AAAA,UACA,EAAE,QAAQ,MAAM,GAAG,KAAK;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEAD,QAAO,KAAK,OAAO;AAAA,MACnB,WAAW;AAAA,MACX,WAAW;AAAA,MACX,WAAW;AAAA,MAEX;AAAA,MACA;AAAA,MAEA,CAAC,UAAU;AAAA,IACb;AAAA,EACF;AACF;;;AI9MA;AAAA,EACE,UAAAM;AAAA,EAEA,qBAAAC;AAAA,OAIK;AACP,SAAS,QAAAC,aAAwB;AACjC,SAAS,QAAAC,aAAY;AACrB,SAAS,aAAAC,kBAAiB;AAanB,IAAe,cAAf,cAAmCC,mBAAkB;AAAA,EAChD,YACR,MACA,MACA,MACA,MAKS,aAKA,UAKA,MAKA,QAEQ,UACA,YACjB;AACA,UAAM,MAAM,MAAM,MAAM,IAAI;AApBnB;AAKA;AAKA;AAKA;AAEQ;AACA;AAAA,EAGnB;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,SAAkC;AACpC,WAAOC,QAAO;AAAA,MACZ,MAAM;AAAA,MACN,aAAa,KAAK;AAAA,MAClB,UAAU,KAAK;AAAA,MACf,SAAS,KAAK,QAAQ;AAAA,IACxB,CAAC;AAAA,EACH;AAAA,EAEA,IAAI,kBAA+C;AACjD,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,UAA2B;AAC7B,WAAO,KAAK,SAAS,MAAM,aAAW;AACpC,UAAI,CAAC,SAAS;AACZ,cAAM,IAAI,MAAM,+BAA+B;AAAA,MACjD;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,IAAI,YAA+B;AACjC,WAAO,KAAK,WAAW,MAAM,eAAa;AACxC,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,kCAAkC;AAAA,MACpD;AAEA,aAAO;AAAA,IACT,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,OAAO,MAAc,MAAuB,MAA6C;AAC9F,WAAO,IAAI,mBAAmB,MAAM,MAAM,IAAI;AAAA,EAChD;AACF;AAEA,IAAM,qBAAN,cAAiC,YAAY;AAAA,EAC3C,YAAY,MAAc,MAAuB,MAAgC;AAC/E,UAAM,EAAE,YAAY,SAAS,QAAQ,SAAS,UAAU,IAAI;AAAA,MAC1D;AAAA,MACA;AAAA,MACA,MAAM;AAAA,MACN;AAAA,IACF;AAEA,UAAM,cAAcA,QAAO,EAAE,MAAM,YAAY,SAAS,QAAQ,CAAC,EAAE;AAAA,MACjE,OAAO,EAAE,MAAAC,OAAM,YAAAC,aAAY,SAAAC,UAAS,SAAAC,SAAQ,MAAM;AAChD,cAAM,eAAe,KAAK,UAAUH,MAAK,SAAS,IAAI;AAEtD,eAAO,KAAKA,MAAK,QAAQI,MAAK,GAAG,mBAAmBA,MAAK,GAAG;AAAA,UAC1D;AAAA,UACA;AAAA,YACE,UAAU,YAAYJ,MAAK,OAAO,YAAYA,OAAM,IAAI;AAAA,YACxD,MAAMK;AAAA,cACJ;AAAA,gBACE,aAAaF,UAAS,SAAS,QAAQ;AAAA,gBACvC,UAAU;AAAA,kBACR,UAAU,CAACH,MAAK,QAAQ,EAAE,OAAO,IAAI;AAAA,kBACrC,MAAM;AAAA,oBACJ,YAAYC,YAAW,IAAI,eAAa,kBAAkB,WAAW,IAAI,CAAC;AAAA,oBAC1E,SAAAC;AAAA,kBACF;AAAA,gBACF;AAAA,gBACA,UAAU,CAACF,MAAK,QAAQ,EAAE,aAAa,OAAO,IAAI;AAAA,cACpD;AAAA,cACAM,MAAKN,OAAM,uBAAuB;AAAA,YACpC;AAAA,UACF;AAAA,UACA,EAAE,QAAQ,MAAM,GAAG,KAAK;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAEA;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MAEAD,QAAO,KAAK,OAAO,EAAE;AAAA,MACrB,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,YAAY;AAAA,MAEZ;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;;;AC9JA,SAAS,kBAAoC;AAC7C;AAAA,EACE,qBAAAQ;AAAA,EACA,aAAAC;AAAA,EACA,UAAAC;AAAA,OAOK;AACP,SAAS,YAAY,MAAM,OAAO,iBAAiB;AACnD,SAAS,aAAa,uBAA2C;AACjE,OAAoB;AAwVb,IAAe,gBAAf,MAAe,uBAAsBC,mBAAkB;AAAA;AAAA;AAAA;AAAA,EAI5C;AAAA,EAEN,YAAY,MAAc,MAAiC,MAAwB;AAC3F,UAAM,sBAAsB,MAAM,MAAM,IAAI;AAE5C,UAAM,iBAAiBC,QAAO,IAAI,EAAE,MAAM,CAAAC,UAAQ;AAChD,YAAM,eAAeC,WAAUD,MAAK,aAAaA,MAAK,YAAY;AAClE,YAAM,cAAcC,WAAUD,MAAK,YAAYA,MAAK,WAAW;AAE/D,YAAM,YAAYC,WAAUD,MAAK,YAAY,YAAYA,MAAK,YAAY,WAAW;AACrF,YAAM,kBAAkB,UAAU,IAAI,cAAY,YAAY,QAAQ,CAAC;AAEvE,YAAM,qBAAqB,gBACxB,OAAO,YAAU,OAAO,SAAS,gBAAgB,EAAE,EACnD,IAAI,YAAU,eAAc,oBAAoB,MAAM,CAAC;AAE1D,YAAM,qBAAqB,gBACxB,OAAO,YAAU,OAAO,SAAS,gBAAgB,OAAO,EACxD,IAAI,YAAU,OAAO,QAAQ;AAEhC,YAAM,mBAAyC,CAAC;AAEhD,UAAIA,MAAK,cAAc;AACrB,yBAAiB,KAAK;AAAA,UACpB,YAAY,CAAC,aAAa;AAAA,UAC1B,WAAW,CAAC,EAAE,aAAa,EAAE,WAAW,WAAW,EAAE,CAAC;AAAA,UACtD,OAAO,CAAC,EAAE,MAAM,IAAI,UAAU,MAAM,CAAC;AAAA,UACrC,KAAK;AAAA,UACL,OAAO,CAAC;AAAA,UACR,OAAO,CAAC;AAAA,UACR,UAAU,CAAC;AAAA,QACb,CAAC;AAAA,MACH;AAEA,aAAO;AAAA,QACL,GAAGA;AAAA,QAEH,aAAaA,MAAK,WAAW,0BAA0BA,MAAK,QAAQ,IAAI,CAAC;AAAA,QAEzE,eAAeA,MAAK,iBAAiB;AAAA,QACrC,gBAAgBA,MAAK,kBAAkB;AAAA,QAEvC,oBAAoBA,MAAK,sBAAsB;AAAA,QAE/C,cAAc,aAAa,IAAI,WAAS;AAAA,UACtC,KAAK,KAAK,WAAW;AAAA,UACrB,OAAOC,WAAU,KAAK,UAAU,KAAK,SAAS;AAAA,UAC9C,OAAO,CAAC;AAAA,UACR,UAAUA,WAAU,KAAK,aAAa,KAAK,YAAY;AAAA,UACvD,YAAYA,WAAU,KAAK,eAAe,KAAK,cAAc;AAAA,UAC7D,WAAWA,WAAU,KAAK,cAAc,KAAK,aAAa;AAAA,UAC1D,OAAOA,WAAU,KAAK,QAAQ,KAAK,OAAO;AAAA,QAC5C,EAAE;AAAA,QAEF,aAAa,YACV,IAAI,UAAQ;AACX,iBAAO;AAAA,YACL,KAAK,KAAK,SAAS;AAAA,YACnB,OAAOA,WAAU,KAAK,QAAQ,KAAK,OAAO,EAAE,OAAO,kBAAkB;AAAA,YACrE,OAAOA,WAAU,KAAK,QAAQ,KAAK,OAAO,EAAE,OAAO,kBAAkB;AAAA,YACrE,UAAUA,WAAU,KAAK,WAAW,KAAK,UAAU;AAAA,YACnD,YAAYA,WAAU,KAAK,aAAa,KAAK,YAAY;AAAA,YACzD,WAAWA,WAAU,KAAK,YAAY,KAAK,WAAW;AAAA,YACtD,OAAOA,WAAU,KAAK,QAAQ,KAAK,OAAO;AAAA,UAC5C;AAAA,QACF,CAAC,EACA,OAAO,gBAAgB;AAAA,MAC5B;AAAA,IACF,CAAC;AAED,SAAK,gBAAgB,eAAe,MAAM,CAAAD,UAAQ;AAChD,aAAOD;AAAA,QACL,KAAK,OAAO,MAAMC,OAAqC,EAAE,GAAG,MAAM,QAAQ,KAAK,CAAC;AAAA,MAClF;AAAA,IACF,CAAC;AAED,SAAK,gBAAgB,EAAE,eAAe,KAAK,cAAc,CAAC;AAAA,EAC5D;AAAA,EAEA,OAAe,oBAAoB,QAA+B;AAChE,QAAI,OAAO,cAAc,GAAG;AAC1B,aAAO,GAAG,OAAO,QAAQ;AAAA,IAC3B;AAEA,WAAO,GAAG,OAAO,QAAQ;AAAA,EAC3B;AAAA,EAQA,OAAwB,gBAAgB,CAAC,QAAQ;AAAA,EAEjD,OAAO,OACL,MACA,MACA,MACuB;AACvB,WAAOD,QAAO,IAAI,EAAE,MAAM,OAAMC,UAAQ;AACtC,YAAM,MAAMA,MAAK,QAAQ,KAAK;AAE9B,UAAI,CAAC,OAAO,CAAC,eAAc,cAAc,SAAS,GAAG,GAAG;AACtD,eAAO,IAAI,oBAAoB,MAAMA,OAAM,IAAI;AAAA,MACjD;AAEA,YAAM,WAAW,GAAG,WAAW,GAAG,CAAC;AACnC,YAAM,aAAc,MAAM,OAAO,cAAc,GAAG;AAQlD,YAAM,YAAY,WAAW,QAAQ;AACrC,UAAI,CAAC,WAAW;AACd,cAAM,IAAI,MAAM,+BAA+B,GAAG,EAAE;AAAA,MACtD;AAEA,aAAO,IAAI,UAAU,MAAMA,OAAM,IAAI;AAAA,IACvC,CAAC;AAAA,EACH;AAAA,EAEA,OAAO,qBACL,WACA,SACA,MACuB;AACvB,WAAO,eAAc;AAAA,MACnB;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,QAEA,aAAa;AAAA,QACb,UAAU,CAAC;AAAA,QAEX,aAAa,EAAE,eAAe,UAAU;AAAA,QACxC,YAAY,EAAE,aAAa,UAAU;AAAA,MACvC;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,mBACL,WACA,SACA,MACuB;AACvB,WAAO,eAAc;AAAA,MACnB;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,QAEA,aAAa;AAAA,QAEb,oBAAoB;AAAA,MACtB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,aACL,WACA,SACA,MACuB;AACvB,WAAO,eAAc;AAAA,MACnB;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,QAEA,aAAa;AAAA,QAEb,cAAc;AAAA,MAChB;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAO,eACL,WACA,SACA,MACuB;AACvB,WAAO,eAAc;AAAA,MACnB;AAAA,MACA;AAAA,QACE;AAAA,QACA;AAAA,QAEA,aAAa;AAAA,QAEb,YAAY,EAAE,OAAO,KAAK;AAAA,MAC5B;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACF;AAEO,IAAM,sBAAN,MAAM,6BAA4B,cAAc;AAAA,EAC3C,OACR,MACA,MACA,MACU;AACV,UAAM,UAAU,qBAAoB,mBAAmB,IAAI;AAC3D,UAAM,SAAS,qBAAoB,kBAAkB,IAAI;AAEzD,UAAM,cAAwB,CAAC;AAE/B,QAAI,QAAQ,SAAS,KAAK,KAAK,gBAAgB;AAC7C,kBAAY,KAAK,SAAS;AAAA,IAC5B;AAEA,QAAI,OAAO,SAAS,KAAK,KAAK,eAAe;AAC3C,kBAAY,KAAK,QAAQ;AAAA,IAC3B;AAEA,WAAO,IAAI,WAAW,GAAG;AAAA,MACvB;AAAA,MACA;AAAA,QACE,UAAU,UAAU,YAAY,MAAM,IAAI,GAAG;AAAA,UAC3C,aAAa,KAAK,cACd,EAAE,6BAA6B,KAAK,YAAY,IAChD;AAAA,QACN,CAAC;AAAA,QACD,MAAM;AAAA,UACJ,aAAa,KAAK;AAAA,UAClB;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA,EAEA,OAAe,kBAAqD;AAAA,IAClE,MAAM;AAAA,IACN,QAAQ,CAAC,cAAc,iBAAiB,gBAAgB;AAAA,EAC1D;AAAA,EAEA,OAAe,mBACb,MACsD;AACtD,WAAO,KAAK,aAAa,IAAI,WAAS;AAAA,MACpC,MAAM,KAAK,MAAM,SAAY,qBAAoB,gBAAgB,IAAI;AAAA,MACrE,OAAO,qBAAoB,SAAS,KAAK,KAAK;AAAA,IAChD,EAAE;AAAA,EACJ;AAAA,EAEA,OAAe,kBACb,MACqD;AAGrD,UAAM,eAAe,KAAK,YAAY,KAAK,UAAQ,KAAK,MAAM,SAAS,CAAC;AACxE,QAAI,cAAc;AAChB,aAAO,CAAC,EAAE,IAAI,CAAC,EAAE,SAAS,qBAAoB,gBAAgB,CAAC,EAAE,CAAC;AAAA,IACpE;AAEA,UAAM,aAAkE,CAAC;AAEzE,QAAI,KAAK,oBAAoB;AAC3B,YAAM,cAAc,KAAK,QAAQ,KAAK,mBAAmB;AACzD,YAAM,gBAAgB,KAAK,QAAQ,KAAK,qBAAqB;AAE7D,iBAAW,KAAK;AAAA,QACd,IAAI,CAAC,EAAE,SAAS,EAAE,MAAM,GAAG,WAAW,MAAM,EAAE,CAAC;AAAA,QAC/C,OAAO,CAAC,EAAE,MAAM,eAAe,UAAU,MAAM,CAAC;AAAA,MAClD,CAAC;AAAA,IACH;AAEA,WAAO,KAAK,YACT,IAAI,UAAQ;AACX,aAAO;AAAA,QACL,IAAI,KAAK,MAAM,SAAY,qBAAoB,gBAAgB,IAAI;AAAA,QACnE,OAAO,qBAAoB,SAAS,KAAK,KAAK;AAAA,MAChD;AAAA,IACF,CAAC,EACA,OAAO,UAAU;AAAA,EACtB;AAAA,EAEA,OAAe,gBAEb,MAC+C;AAC/C,WAAO;AAAA,MACL,GAAG,qBAAoB,gBAAgB,IAAI;AAAA,MAC3C,GAAG,qBAAoB,mBAAmB,IAAI;AAAA,MAC9C,GAAG,qBAAoB,oBAAoB,IAAI;AAAA,IACjD;AAAA,EACF;AAAA,EAEA,OAAe,gBACb,MAC+C;AAC/C,WAAO,KAAK,MAAM,IAAI,WAAS,EAAE,SAAS,EAAE,KAAK,EAAE,EAAE;AAAA,EACvD;AAAA,EAEA,OAAe,mBACb,MAC+C;AAC/C,WAAO,KAAK,SAAS,IAAI,aAAW;AAClC,YAAM,WAAW,0BAA0B,OAAO;AAElD,aAAO;AAAA,QACL,mBAAmB,2BAA2B,QAAQ,SAAS,SAAS;AAAA,QACxE,aAAa;AAAA,MACf;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,OAAe,oBACb,MAC+C;AAC/C,UAAM,gBAAgB,KAAK,UAAU,IAAI,eAAa;AAAA,MACpD,aAAa,0BAA0B,QAAQ;AAAA,IACjD,EAAE;AAEF,UAAM,iBAAiB,KAAK,WAAW,IAAI,qBAAoB,mBAAmB;AAElF,QAAI,eAAe,WAAW,GAAG;AAE/B,aAAO;AAAA,IACT;AAEA,QAAI,cAAc,WAAW,GAAG;AAE9B,aAAO;AAAA,IACT;AAGA,WAAO;AAAA,MACL,cAAc,IAAI,kBAAgB;AAChC,eAAO,eAAe,IAAI,mBAAiB,MAAM,cAAc,aAAa,CAAC;AAAA,MAC/E,CAAC;AAAA,IACH;AAAA,EACF;AAAA,EAEA,OAAe,oBAEb,WAC6C;AAC7C,UAAM,gBAAgB,gCAAgC,SAAS;AAC/D,UAAM,oBAAoB,2BAA2B,aAAa;AAElE,WAAO,EAAE,kBAAkB;AAAA,EAC7B;AAAA,EAEA,OAAe,SACb,OAC+C;AAC/C,WAAO,MAAM,IAAI,UAAQ;AACvB,UAAI,UAAU,MAAM;AAClB,eAAO;AAAA,UACL,MAAM,KAAK;AAAA,UACX,UAAU,KAAK,YAAY;AAAA,QAC7B;AAAA,MACF;AAEA,aAAO;AAAA,QACL,MAAM,KAAK,MAAM,CAAC;AAAA,QAClB,SAAS,KAAK,MAAM,CAAC;AAAA,QACrB,UAAU,KAAK,YAAY;AAAA,MAC7B;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AC7tBA,SAAS,iBAAiB;AAC1B,SAAS,eAAe;AACxB;AAAA,EACE,aAAAE;AAAA,EAEA,UAAAC;AAAA,EACA;AAAA,OAGK;AAyBA,SAAS,eAAe,MAAyD;AACtF,QAAM,SAASC,QAAO,EAAE,MAAM,eAAeA,QAAO,KAAK,SAAS,EAAE,SAAS,KAAK,CAAC,EAAE;AAAA,IACnF,CAAC,EAAE,MAAAC,OAAM,cAAc,MAAM;AAC3B,YAAMC,WAAU,cAAc;AAAA,QAC5B,GAAGD;AAAA,QACH,aAAa;AAAA,UACX,kCAAkCA,MAAK,YAAY,UAAU;AAAA,QAC/D;AAAA,QACA,SAASA,MAAK,YAAY;AAAA,MAC5B,CAAC;AAED,YAAM,aAAaE,WAAUF,MAAK,MAAMA,MAAK,KAAK,EAAE,QAAQ,UAAQ;AAClE,eAAO,UAAU,UAAU,MAAM;AAAA,UAC/B,WAAWA,MAAK,YAAY;AAAA,UAC5B,MAAM;AAAA,UACN,OAAOA,MAAK,YAAY,QAAQ;AAAA,QAClC,CAAC;AAAA,MACH,CAAC;AAED,YAAM,kBAA2C,CAAC;AAElD,UAAIA,MAAK,YAAY,QAAQ,SAAS;AACpC,cAAM,cAAc,kBAAkBA,MAAK,YAAY,QAAQ,QAAQ,QAAQ;AAE/E,wBAAgB;AAAA,UACd,cAAc;AAAA,YACZ,sBAAsB,WAAWA,MAAK,YAAY,QAAQ,QAAQ,QAAQ,CAAC;AAAA,YAC3E;AAAA,cACE,WAAWA,MAAK;AAAA,cAChB,SAASA,MAAK;AAAA,cAEd,aAAa,2CAA2C,WAAW;AAAA,cAEnE,aAAa;AAAA,gBACX,eAAeA,MAAK,YAAY,QAAQ,QAAQ,SAAS;AAAA,gBACzD,cAAcA,MAAK,YAAY,QAAQ,QAAQ,KAAK;AAAA,cACtD;AAAA,YACF;AAAA,YACA,EAAE,UAAUA,MAAK,SAAS;AAAA,UAC5B;AAAA,UAEA,cAAc;AAAA,YACZ,mBAAmB,aAAa;AAAA,YAChC;AAAA,cACE,WAAWA,MAAK,YAAY,QAAQ,QAAQ,SAAS;AAAA,cACrD,SAASA,MAAK;AAAA,cAEd,UAAUA,MAAK,YAAY,QAAQ,QAAQ,KAAK;AAAA,cAEhD,aAAa,0CAA0C,aAAa;AAAA,cAEpE,YAAY;AAAA,gBACV,aAAaA,MAAK;AAAA,cACpB;AAAA,YACF;AAAA,YACA,EAAE,UAAUA,MAAK,SAAS;AAAA,UAC5B;AAAA,QACF;AAAA,MACF;AAEA,aAAOD,QAAO;AAAA,QACZ,SAAAE;AAAA,QACA,YAAYF,QAAO,UAAU,EAAE,MAAM,aAAW,QAAQ,KAAK,CAAC;AAAA,QAC9D;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO,UAAU,MAAM;AACzB;AAWO,SAAS,sBACd,SACA,WACA,MACA,QACA,UAC+B;AAC/B,SAAO,eAAe;AAAA,IACpB,MAAM;AAAA,IACN;AAAA,IAEA,MAAM,KAAK;AAAA,IAEX,aAAa,OAAO;AAAA,IACpB,SAAS,OAAO;AAAA,IAChB;AAAA,EACF,CAAC;AACH;AAeO,SAAS,cAAc,MAAqD;AACjF,SAAOA,QAAO,IAAI,EAAE,MAAM,CAAAC,UAAQ;AAChC,QAAIA,MAAK,QAAQ,KAAK,OAAOA,MAAK,QAAQ,YAAY,IAAI;AACxD,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAEA,WAAO,IAAI,QAAQ,GAAG;AAAA,MACpBA,MAAK;AAAA,MACL;AAAA,QACE,UAAU;AAAA,UACR,MAAMA,MAAK;AAAA,UACX,WAAW,gCAAgCA,MAAK,SAAS;AAAA,UACzD,aAAaA,MAAK;AAAA,QACpB;AAAA,QACA,MAAM;AAAA,UACJ,kBAAkBD,QAAOC,MAAK,OAAO,EAAE;AAAA,UACvC,WAAWE,WAAUF,MAAK,MAAMA,MAAK,KAAK,EAAE,IAAI,UAAQ;AACtD,kBAAM,iBAAiB,KAAK,QAAQ,OAAO,UAAU;AAErD,mBAAO;AAAA,cACL,MAAM,SAAS,cAAc;AAAA,cAC7B,MAAMD,QAAOC,MAAK,OAAO,EAAE;AAAA,cAC3B,UAAU;AAAA,cACV,UAAU;AAAA,cACV,KAAK;AAAA,gBACH,MAAM;AAAA,gBACN,iBAAiB,CAAC,EAAE,MAAM,eAAe,CAAC;AAAA,cAC5C;AAAA,YACF;AAAA,UACF,CAAC;AAAA,QACH;AAAA,MACF;AAAA,MACA,EAAE,UAAUA,MAAK,UAAU,aAAaA,MAAK,UAAU;AAAA,IACzD;AAAA,EACF,CAAC;AACH;;;ACxLA,SAAS,QAAAG,aAAY;AACrB,SAAS,OAAO,aAAAC,kBAAkC;AAClD;AAAA,EACE,qBAAAC;AAAA,EACA,UAAAC;AAAA,OAKK;AACP,SAAS,YAAY;AACrB,SAAS,aAAAC,kBAAiB;AAC1B,SAAS,MAAM,mBAAAC,wBAAuB;;;ACkDtC,IAAM,+BAAkE;AAAA,EACtE,oBAAoB,CAAC;AAAA,EACrB,mBAAmB,CAAC;AAAA,EACpB,UAAU,CAAC;AACb;AAEO,IAAM,yBAAoD;AAAA,EAC/D,QAAQ;AAAA,EACR,QAAQ;AAAA,EACR,cAAc,CAAC;AAAA,EACf,gBAAgB,CAAC;AAAA,EACjB,SAAS,CAAC;AAAA,EACV,SAAS,CAAC;AAAA,EACV,cAAc,CAAC;AAAA,EACf,aAAa,CAAC;AAChB;;;ADvCO,IAAM,eAAN,cAA2BC,mBAAkB;AAAA;AAAA;AAAA;AAAA,EAIzC;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA;AAAA;AAAA;AAAA,EAKA;AAAA,EAET,YAAY,MAAc,MAAwB,MAAiC;AACjF,UAAM,8BAA8B,MAAM,MAAM,IAAI;AAEpD,UAAM,oBAAoB;AAAA,MACxBC,QAAO,IAAI;AAAA,MACX,MAAM,CAAAC,UAAQC,WAAUD,MAAK,aAAaA,MAAK,YAAY,CAAC;AAAA,MAC5D,MAAM,CAAAA,UAAQE,WAAU,wBAAwB,GAAGF,KAAI,CAAC;AAAA,IAC1D;AAEA,SAAK,eAAe,KAAK;AACzB,SAAK,cAAc,kBAAkB;AAErC,SAAK,YAAYD,QAAO,EAAE,mBAAmB,KAAK,CAAC,EAAE,MAAM,CAAC,EAAE,mBAAAI,oBAAmB,MAAAH,MAAK,MAAM;AAC1F,aAAO,IAAII,MAAK,GAAG;AAAA,QACjB;AAAA,QACA;AAAA,UACE,UAAU,YAAYJ,OAAM,IAAI;AAAA,UAChC,MAAM,iBAAiB,KAAK,cAAcG,kBAAiB;AAAA,QAC7D;AAAA,QACA,EAAE,GAAG,MAAM,QAAQ,KAAK;AAAA,MAC1B;AAAA,IACF,CAAC;AAED,SAAK,UAAU,kBAAkB,QAAQ,MAAM,aAAW;AACxD,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,UACE,MAAM,KAAK,UAAU,SAAS;AAAA,UAE9B,WAAW;AAAA,YACT,MAAM,KAAK,UAAU,SAAS;AAAA,YAC9B,aAAa;AAAA;AAAA,UACf;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,SAAK,eAAe,kBAAkB,aAAa,MAAM,kBAAgB;AACvE,aAAO;AAAA,QACL,GAAG;AAAA,QACH;AAAA,UACE,QAAQ,KAAK;AAAA,UACb,WAAW;AAAA,QACb;AAAA,MACF;AAAA,IACF,CAAC;AAED,SAAK,gBAAgB;AAAA,MACnB,WAAW,KAAK;AAAA,MAChB,SAAS,KAAK;AAAA,MACd,cAAc,KAAK;AAAA,MACnB,aAAa,KAAK;AAAA,IACpB,CAAC;AAAA,EACH;AACF;AAEA,SAAS,iBACP,cACA,aACwB;AACxB,QAAM,aAAqC,CAAC;AAC5C,QAAM,UAAoB,CAAC;AAE3B,QAAM,0BAA0B,YAAY,YAAY;AAExD,MAAI,wBAAwB,mBAAmB,SAAS,GAAG;AACzD,eAAW,yBAAyB,IAAI;AAAA,MACtC;AAAA,MACA,wBAAwB;AAAA,IAC1B;AAEA,YAAQ,KAAK;AAAA;AAAA;AAAA;AAAA,KAIZ;AAAA,EACH;AAEA,MAAI,OAAO,KAAK,wBAAwB,iBAAiB,EAAE,SAAS,GAAG;AACrE,eAAW,OAAO,wBAAwB,mBAAmB;AAC3D,iBAAW,eAAe,GAAG,EAAE,IAAI,wBAAwB,kBAAkB,GAAG;AAEhF,cAAQ,KAAK;AAAA,8CAC2B,GAAG;AAAA,+BAClB,GAAG;AAAA,sCACI,GAAG;AAAA,OAClC;AAAA,IACH;AAAA,EACF;AAEA,MAAI,wBAAwB,SAAS,SAAS,GAAG;AAC/C,eAAW,qBAAqB,IAAI;AAAA,MAClC;AAAA,MACA,wBAAwB;AAAA,IAC1B;AAEA,YAAQ,KAAK;AAAA;AAAA;AAAA;AAAA,KAIZ;AAAA,EACH;AAEA,MAAI,OAAO,KAAK,YAAY,YAAY,EAAE,SAAS,GAAG;AACpD,eAAW,OAAO,YAAY,cAAc;AAC1C,iBAAW,SAAS,GAAG,EAAE,IAAI,YAAY,aAAa,GAAG;AAEzD,cAAQ,KAAK;AAAA,wCACqB,GAAG;AAAA,yBAClB,GAAG;AAAA,gCACI,GAAG;AAAA,OAC5B;AAAA,IACH;AAAA,EACF;AAEA,MAAI,OAAO,KAAK,YAAY,cAAc,EAAE,SAAS,GAAG;AACtD,UAAM,iBAA2B,CAAC;AAElC,eAAW,OAAO,YAAY,gBAAgB;AAC5C,iBAAW,WAAW,GAAG,EAAE,IAAI,YAAY,eAAe,GAAG;AAE7D,qBAAe,KAAK;AAAA,0CACgB,GAAG;AAAA,2BAClB,GAAG;AAAA,kCACI,GAAG;AAAA,OAC9B;AAAA,IACH;AAEA,YAAQ,KAAK;AAAA;AAAA,QAET,eAAe,IAAI,OAAK,EAAE,KAAK,CAAC,EAAE,KAAK,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,KAKjD;AAAA,EACH;AAEA,aAAW,OAAO,YAAY,SAAS;AACrC,eAAW,GAAG,IAAI,YAAY,QAAQ,GAAG;AAAA,EAC3C;AAEA,aAAW,eAAe,IAAIE,iBAAgB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAS5C,QAAQ,IAAI,OAAK,EAAE,KAAK,CAAC,EAAE,KAAK,MAAM,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,GAKxC;AAED,SAAO;AACT;AAEA,SAAS,yBAAyB,cAAkC,UAA4B;AAC9F,MAAI,iBAAiB,UAAU;AAC7B,WAAO;AAAA;AAAA;AAAA;AAAA,2BAIgB,SAAS,KAAK,GAAG,CAAC;AAAA;AAAA,EAE3C,OAAO;AACL,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA,2BAKgB,SAAS,KAAK,GAAG,CAAC;AAAA;AAAA,EAE3C;AACF;;;AEjPA,SAAiB,UAAAC,eAA0B;AAC3C,SAAS,SAAAC,cAAa;AAsBf,SAAS,sBAAsB,SAA6C;AACjF,SAAOD,QAAO,OAAO,EAAE,MAAM,CAAAE,aAAW;AACtC,UAAM,QACJA,SAAQ,OAAO,iBAAiB,WAC5B,mFACA;AAEN,WAAO;AAAA,MACL;AAAA,MACA,SAAS,CAAC,0BAA0B,YAAYA,SAAQ,IAAI,EAAE;AAAA,MAE9D,GAAGA;AAAA,MAEH,cAAcD,OAAMC,SAAQ,OAAO,cAAcA,SAAQ,YAAY;AAAA,MACrE,SAASD,OAAMC,SAAQ,OAAO,SAASA,SAAQ,OAAO;AAAA,MACtD,aAAaD,OAAMC,SAAQ,OAAO,aAAaA,SAAQ,WAAW;AAAA,IACpE;AAAA,EACF,CAAC;AACH;;;AC3CA,SAAS,aAAyB;AAClC;AAAA,EACE,qBAAAC;AAAA,EACA,aAAAC;AAAA,EAEA,UAAAC;AAAA,OAIK;AACP,SAAS,aAAAC,YAAW,QAAAC,aAAY;AAchC,IAAM,eAAe,CAAC,GAAG,iBAAiB,aAAa,YAAY;AAE5D,IAAM,MAAN,cAAkBC,mBAAkB;AAAA;AAAA;AAAA;AAAA,EAIzB;AAAA,EAEhB,YAAY,MAAc,MAAe,MAAiC;AACxE,UAAM,qBAAqB,MAAM,MAAM,IAAI;AAE3C,SAAK,MAAMC,SAAO,IAAI,EAAE,MAAM,CAAAC,UAAQ;AACpC,YAAM,aAAaC,WAAUD,MAAK,WAAWA,MAAK,UAAU;AAE5D,aAAO,IAAI,MAAM,GAAG;AAAA,QAClB;AAAA,QACA;AAAA,UACE,UAAU,YAAYA,OAAM,IAAI;AAAA,UAChC,MAAME;AAAA,YACJ;AAAA,cACE,UAAU;AAAA,gBACR,MAAM;AAAA,kBACJ,YAAY,WAAW,IAAI,eAAa,kBAAkB,WAAW,IAAI,CAAC;AAAA,kBAE1E,SAAS,WACN,QAAQ,eAAaD,WAAU,UAAU,QAAQ,UAAU,OAAO,CAAC,EACnE,IAAI,iBAAiB;AAAA,kBAExB,eAAe;AAAA,gBACjB;AAAA,cACF;AAAA,YACF;AAAA,YACAE,MAAKH,OAAM,YAAY;AAAA,UACzB;AAAA,QACF;AAAA,QACA,EAAE,QAAQ,MAAM,GAAG,KAAK;AAAA,MAC1B;AAAA,IACF,CAAC;AAED,SAAK,gBAAgB,EAAE,KAAK,KAAK,IAAI,CAAC;AAAA,EACxC;AACF;;;AChEA,SAAS,SAAAI,cAAyB;AAClC;AAAA,EACE,qBAAAC;AAAA,EACA,aAAAC;AAAA,EAEA,UAAAC;AAAA,OAIK;AACP,SAAS,aAAAC,YAAW,QAAAC,aAAY;AAmBhC,IAAM,mBAAmB,CAAC,GAAG,iBAAiB,aAAa,YAAY;AAEhE,IAAM,UAAN,cAAsBC,mBAAkB;AAAA;AAAA;AAAA;AAAA,EAI7B;AAAA,EAEhB,YAAY,MAAc,MAAmB,MAAiC;AAC5E,UAAM,yBAAyB,MAAM,MAAM,IAAI;AAE/C,SAAK,UAAUC,SAAO,IAAI,EAAE,MAAM,CAAAC,UAAQ;AACxC,YAAM,aAAaC,WAAUD,MAAK,WAAWA,MAAK,UAAU;AAE5D,aAAO,IAAIE,OAAM,GAAG;AAAA,QAClB;AAAA,QACA;AAAA,UACE,UAAU,YAAYF,OAAM,IAAI;AAAA,UAEhC,MAAMG;AAAA,YACJ;AAAA,cACE,aAAa;AAAA,gBACX,MAAM;AAAA,kBACJ,UAAU;AAAA,oBACR,MAAM;AAAA,sBACJ,YAAY,WAAW,IAAI,eAAa,kBAAkB,WAAW,IAAI,CAAC;AAAA,sBAE1E,SAAS,WACN,QAAQ,eAAaF,WAAU,UAAU,QAAQ,UAAU,OAAO,CAAC,EACnE,IAAI,iBAAiB;AAAA,oBAC1B;AAAA,kBACF;AAAA,gBACF;AAAA,cACF;AAAA,cAEA,UAAUD,MAAK;AAAA,YACjB;AAAA,YACAI,MAAKJ,OAAM,gBAAgB;AAAA,UAC7B;AAAA,QACF;AAAA,QACA,EAAE,QAAQ,MAAM,GAAG,KAAK;AAAA,MAC1B;AAAA,IACF,CAAC;AAED,SAAK,gBAAgB,EAAE,SAAS,KAAK,QAAQ,CAAC;AAAA,EAChD;AACF;","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
|
-
|
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
|
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
|
-
|
37
|
-
|
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)\
|
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,
|
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.
|
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.
|
29
|
-
"@highstate/common": "^0.
|
30
|
-
"@highstate/contract": "^0.
|
31
|
-
"@highstate/gateway-api": "^0.
|
32
|
-
"@highstate/pulumi": "^0.
|
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.
|
49
|
+
"@highstate/cli": "^0.9.0"
|
49
50
|
},
|
50
|
-
"gitHead": "
|
51
|
+
"gitHead": "b64df0df33afcadf019936eaa2a2ca7ffc82940b"
|
51
52
|
}
|
package/src/access-point.ts
CHANGED
@@ -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).
|
49
|
-
return DnsRecord.
|
50
|
-
|
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
|
-
|
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
|
-
|
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.
|
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
package/src/network-policy.ts
CHANGED
@@ -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
|
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
|
-
|
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:
|
460
|
+
args: NetworkPolicyArgs,
|
464
461
|
opts: ResourceOptions,
|
465
462
|
): Output<NetworkPolicy> {
|
466
463
|
return output(args).apply(async args => {
|
467
|
-
|
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(
|
472
|
-
const implModule = (await import(`@highstate/${
|
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 ${
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
634
|
-
|
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
|
@@ -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
|
-
|
24
|
-
|
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
|
+
})
|