@highstate/k8s 0.7.2 → 0.7.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/dist/{helm-wPTgVV1N.js → chunk-K4WKJ4L5.js} +89 -47
  2. package/dist/chunk-K4WKJ4L5.js.map +1 -0
  3. package/dist/{shared-Clzbl5K-.js → chunk-T5Z2M4JE.js} +21 -7
  4. package/dist/chunk-T5Z2M4JE.js.map +1 -0
  5. package/dist/highstate.manifest.json +9 -0
  6. package/dist/index.js +304 -154
  7. package/dist/index.js.map +1 -0
  8. package/dist/units/access-point/index.js +9 -7
  9. package/dist/units/access-point/index.js.map +1 -0
  10. package/dist/units/cert-manager/index.js +29 -29
  11. package/dist/units/cert-manager/index.js.map +1 -0
  12. package/dist/units/dns01-issuer/index.js +22 -14
  13. package/dist/units/dns01-issuer/index.js.map +1 -0
  14. package/dist/units/existing-cluster/index.js +49 -21
  15. package/dist/units/existing-cluster/index.js.map +1 -0
  16. package/package.json +15 -16
  17. package/src/access-point.ts +185 -0
  18. package/src/container.ts +271 -0
  19. package/src/cron-job.ts +77 -0
  20. package/src/deployment.ts +210 -0
  21. package/src/gateway/backend.ts +61 -0
  22. package/src/gateway/http-route.ts +139 -0
  23. package/src/gateway/index.ts +2 -0
  24. package/src/helm.ts +298 -0
  25. package/src/index.ts +61 -0
  26. package/src/job.ts +66 -0
  27. package/src/network-policy.ts +732 -0
  28. package/src/pod.ts +5 -0
  29. package/src/pvc.ts +178 -0
  30. package/src/scripting/bundle.ts +244 -0
  31. package/src/scripting/container.ts +44 -0
  32. package/src/scripting/environment.ts +79 -0
  33. package/src/scripting/index.ts +3 -0
  34. package/src/service.ts +279 -0
  35. package/src/shared.ts +150 -0
  36. package/src/stateful-set.ts +159 -0
  37. package/src/units/access-point/index.ts +12 -0
  38. package/src/units/cert-manager/index.ts +37 -0
  39. package/src/units/dns01-issuer/index.ts +41 -0
  40. package/src/units/dns01-issuer/solver.ts +23 -0
  41. package/src/units/existing-cluster/index.ts +107 -0
  42. package/src/workload.ts +150 -0
  43. package/assets/charts.json +0 -8
  44. package/dist/index.d.ts +0 -1036
@@ -0,0 +1,107 @@
1
+ import { text } from "@highstate/contract"
2
+ import { k8s } from "@highstate/library"
3
+ import { forUnit, getUnitInstanceName, secret, toPromise } from "@highstate/pulumi"
4
+ import { core, Provider } from "@pulumi/kubernetes"
5
+ import { KubeConfig, AppsV1Api, CoreV1Api } from "@kubernetes/client-node"
6
+
7
+ const { name, args, secrets, outputs } = forUnit(k8s.existingCluster)
8
+
9
+ const kubeconfigContent = await toPromise(secrets.kubeconfig.apply(JSON.stringify))
10
+
11
+ const provider = new Provider(name, { kubeconfig: kubeconfigContent })
12
+
13
+ let cni: string | undefined
14
+
15
+ const kubeConfig = new KubeConfig()
16
+ kubeConfig.loadFromString(kubeconfigContent)
17
+
18
+ const appsApi = kubeConfig.makeApiClient(AppsV1Api)
19
+ const nodeApi = kubeConfig.makeApiClient(CoreV1Api)
20
+
21
+ const isCilium = await appsApi
22
+ .readNamespacedDaemonSet({ name: "cilium", namespace: "kube-system" })
23
+ .then(() => true)
24
+ .catch(() => false)
25
+
26
+ if (isCilium) {
27
+ cni = "cilium"
28
+ }
29
+
30
+ const isPrivateIp = (ip: string) => {
31
+ const privateIpRegex = /^(10|172\.16|192\.168)\./
32
+ return privateIpRegex.test(ip)
33
+ }
34
+
35
+ const nodes = await nodeApi.listNode()
36
+
37
+ const externalIps = nodes.items.flatMap(node => {
38
+ const addresses = node.status?.addresses ?? []
39
+ const externalIp = addresses.find(address => address.type === "ExternalIP")
40
+ const internalIp = addresses.find(address => address.type === "InternalIP")
41
+
42
+ const result: string[] = []
43
+
44
+ if (externalIp?.address) {
45
+ result.push(externalIp.address)
46
+ }
47
+
48
+ if (internalIp?.address && args.internalIpsPolicy === "always") {
49
+ result.push(internalIp.address)
50
+ }
51
+
52
+ if (
53
+ internalIp?.address &&
54
+ args.internalIpsPolicy === "public" &&
55
+ !isPrivateIp(internalIp.address)
56
+ ) {
57
+ result.push(internalIp.address)
58
+ }
59
+
60
+ return result
61
+ })
62
+
63
+ const kubeSystem = core.v1.Namespace.get("kube-system", "kube-system", { provider })
64
+
65
+ export default outputs({
66
+ cluster: {
67
+ info: {
68
+ id: kubeSystem.metadata.uid,
69
+ name,
70
+ cni,
71
+ externalIps,
72
+ },
73
+ kubeconfig: secret(kubeconfigContent),
74
+ },
75
+
76
+ $terminals: {
77
+ management: {
78
+ title: `K8S: ${getUnitInstanceName()}`,
79
+ description: "Manage the cluster using kubectl and helm",
80
+ image: "ghcr.io/exeteres/highstate/terminal-kubectl",
81
+ command: ["bash", "/welcome.sh"],
82
+ files: {
83
+ "/kubeconfig": secret(kubeconfigContent),
84
+
85
+ "/welcome.sh": text`
86
+ if [ "$HIGHSTATE_TERMINAL_FIRST_LAUNCH" = "1" ]; then
87
+ echo "Connecting to the cluster..."
88
+ kubectl cluster-info
89
+
90
+ echo "Use 'kubectl' and 'helm' to manage the cluster."
91
+ echo
92
+ fi
93
+
94
+ exec script -q -c bash /dev/null
95
+ `,
96
+ },
97
+ env: {
98
+ KUBECONFIG: "/kubeconfig",
99
+ },
100
+ },
101
+ },
102
+
103
+ $status: {
104
+ clusterId: kubeSystem.metadata.uid,
105
+ cni: cni ?? "unknown",
106
+ },
107
+ })
@@ -0,0 +1,150 @@
1
+ import type { types } from "@pulumi/kubernetes"
2
+ import type { k8s } from "@highstate/library"
3
+ import { normalize, type ComponentResourceOptions, type InputArray } from "@highstate/pulumi"
4
+ import { ComponentResource, output, type Input, type Output } from "@pulumi/pulumi"
5
+ import { uniqueBy } from "remeda"
6
+ import { commonExtraArgs, type CommonArgs } from "./shared"
7
+ import { mapContainerPortToServicePort, Service, type ServiceArgs } from "./service"
8
+ import { HttpRoute, type HttpRouteArgs } from "./gateway"
9
+ import {
10
+ mapContainerToRaw,
11
+ mapWorkloadVolume,
12
+ type Container,
13
+ type WorkloadVolume,
14
+ } from "./container"
15
+
16
+ export type WorkloadArgs = CommonArgs & {
17
+ container?: Input<Container>
18
+ containers?: InputArray<Container>
19
+
20
+ /**
21
+ * The cluster to create the resource in.
22
+ */
23
+ cluster: Input<k8s.Cluster>
24
+ }
25
+
26
+ export const workloadExtraArgs = [...commonExtraArgs, "container", "containers"] as const
27
+
28
+ export class WorkloadBase<TArgs extends WorkloadArgs> extends ComponentResource {
29
+ protected readonly containers: Output<types.input.core.v1.Container[]>
30
+ protected readonly volumes: Output<types.input.core.v1.Volume[]>
31
+
32
+ constructor(type: string, name: string, args: TArgs, opts: ComponentResourceOptions | undefined) {
33
+ super(type, name, args, opts)
34
+
35
+ const containers = output(args).apply(args => normalize(args.container, args.containers))
36
+
37
+ this.containers = containers.apply(containers =>
38
+ containers.map(container => mapContainerToRaw(container, name)),
39
+ )
40
+
41
+ this.volumes = containers.apply(containers =>
42
+ containers
43
+ .flatMap(container => normalize(container.volume, container.volumes))
44
+ .map(mapWorkloadVolume),
45
+ )
46
+ }
47
+ }
48
+
49
+ export type PublicWorkloadArgs = WorkloadArgs & {
50
+ service?: Input<Omit<ServiceArgs, "cluster" | "namespace">>
51
+ httpRoute?: Input<Omit<HttpRouteArgs, "cluster" | "namespace">>
52
+ patch?: Input<k8s.Deployment | k8s.StatefulSet>
53
+ } & Partial<types.input.apps.v1.StatefulSetSpec>
54
+
55
+ export const publicWorkloadExtraArgs = [...workloadExtraArgs, "service", "httpRoute"] as const
56
+
57
+ export function getWorkloadComponents(name: string, args: WorkloadArgs) {
58
+ const labels = {
59
+ "app.kubernetes.io/name": name,
60
+ }
61
+
62
+ const containers = output(args).apply(args => normalize(args.container, args.containers))
63
+ const volumes = containers.apply(containers => {
64
+ const containerVolumes = containers
65
+ .flatMap(container => normalize(container.volume, container.volumes))
66
+ .map(mapWorkloadVolume)
67
+
68
+ const containerVolumeMounts = containers
69
+ .flatMap(container => {
70
+ return normalize(container.volumeMount, container.volumeMounts)
71
+ .map(volumeMount => {
72
+ return "volume" in volumeMount ? volumeMount.volume : undefined
73
+ })
74
+ .filter(Boolean) as WorkloadVolume[]
75
+ })
76
+ .map(mapWorkloadVolume)
77
+
78
+ return uniqueBy([...containerVolumes, ...containerVolumeMounts], volume => volume.name)
79
+ })
80
+
81
+ return { labels, containers, volumes }
82
+ }
83
+
84
+ export function getPublicWorkloadComponents(
85
+ name: string,
86
+ args: PublicWorkloadArgs,
87
+ parent: () => ComponentResource,
88
+ opts: ComponentResourceOptions,
89
+ ) {
90
+ const { labels, containers, volumes } = getWorkloadComponents(name, args)
91
+
92
+ const service = output({ args, containers }).apply(({ args, containers }) => {
93
+ if (!args.service && !args.httpRoute) {
94
+ return undefined
95
+ }
96
+
97
+ if (args.patch?.service) {
98
+ return Service.of(name, args.patch.service, { parent: parent(), ...opts })
99
+ }
100
+
101
+ if (args.patch) {
102
+ return undefined
103
+ }
104
+
105
+ const ports = containers.flatMap(container => normalize(container.port, container.ports))
106
+
107
+ return Service.create(
108
+ name,
109
+ {
110
+ ...args.service,
111
+ selector: labels,
112
+ cluster: args.cluster,
113
+ namespace: args.namespace,
114
+
115
+ ports:
116
+ // allow to completely override the ports
117
+ !args.service?.port && !args.service?.ports
118
+ ? ports.map(mapContainerPortToServicePort)
119
+ : args.service?.ports,
120
+ },
121
+ { parent: parent(), ...opts },
122
+ )
123
+ })
124
+
125
+ const httpRoute = output({
126
+ args,
127
+ service,
128
+ }).apply(({ args, service }) => {
129
+ if (!args.httpRoute || !service) {
130
+ return undefined
131
+ }
132
+
133
+ if (args.patch) {
134
+ return undefined
135
+ }
136
+
137
+ return new HttpRoute(
138
+ name,
139
+ {
140
+ ...args.httpRoute,
141
+ rule: {
142
+ backend: service,
143
+ },
144
+ },
145
+ { parent: parent(), ...opts },
146
+ )
147
+ })
148
+
149
+ return { labels, containers, volumes, service, httpRoute }
150
+ }
@@ -1,8 +0,0 @@
1
- {
2
- "cert-manager": {
3
- "repo": "https://charts.jetstack.io",
4
- "name": "cert-manager",
5
- "version": "v1.17.1",
6
- "sha256": "48707f6e8937290da96065dc7de8b4f5a95d9707798d4b5a0d560f78c12996f7"
7
- }
8
- }