@highstate/k8s 0.19.1 → 0.20.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.
Files changed (105) hide show
  1. package/dist/{chunk-FE4SHRAJ.js → chunk-23X5SXQG.js} +22 -7
  2. package/dist/chunk-23X5SXQG.js.map +1 -0
  3. package/dist/{chunk-LGHFSXNT.js → chunk-ADHZK6V2.js} +14 -10
  4. package/dist/chunk-ADHZK6V2.js.map +1 -0
  5. package/dist/{chunk-VCXWCZ43.js → chunk-BTAEFJ5N.js} +27 -15
  6. package/dist/chunk-BTAEFJ5N.js.map +1 -0
  7. package/dist/{chunk-BR2CLUUD.js → chunk-IXE3OKB4.js} +27 -8
  8. package/dist/chunk-IXE3OKB4.js.map +1 -0
  9. package/dist/{chunk-TWBMG6TD.js → chunk-OG2OPX7B.js} +30 -12
  10. package/dist/chunk-OG2OPX7B.js.map +1 -0
  11. package/dist/{chunk-DCUMJSO6.js → chunk-P26SQ2ZB.js} +17 -51
  12. package/dist/chunk-P26SQ2ZB.js.map +1 -0
  13. package/dist/{chunk-MIC2BHGS.js → chunk-PG27ZY2H.js} +25 -7
  14. package/dist/chunk-PG27ZY2H.js.map +1 -0
  15. package/dist/chunk-PZYGZSN5.js +54 -0
  16. package/dist/{chunk-PZ5AY32C.js.map → chunk-PZYGZSN5.js.map} +1 -1
  17. package/dist/{chunk-YIJUVPU2.js → chunk-S77TE7UC.js} +27 -15
  18. package/dist/chunk-S77TE7UC.js.map +1 -0
  19. package/dist/{chunk-P2VOUU7E.js → chunk-SZKOAHNX.js} +383 -205
  20. package/dist/chunk-SZKOAHNX.js.map +1 -0
  21. package/dist/chunk-TOLFVF4S.js +889 -0
  22. package/dist/chunk-TOLFVF4S.js.map +1 -0
  23. package/dist/{chunk-RVB4WWZZ.js → chunk-TVKT3ZYX.js} +174 -18
  24. package/dist/chunk-TVKT3ZYX.js.map +1 -0
  25. package/dist/cron-job-RKB2HYTO.js +7 -0
  26. package/dist/{cron-job-NX4HD4FI.js.map → cron-job-RKB2HYTO.js.map} +1 -1
  27. package/dist/deployment-T35TUOL2.js +7 -0
  28. package/dist/{deployment-O2LJ5WR5.js.map → deployment-T35TUOL2.js.map} +1 -1
  29. package/dist/highstate.manifest.json +3 -2
  30. package/dist/impl/dynamic-endpoint-resolver.js +90 -0
  31. package/dist/impl/dynamic-endpoint-resolver.js.map +1 -0
  32. package/dist/impl/gateway-route.js +159 -62
  33. package/dist/impl/gateway-route.js.map +1 -1
  34. package/dist/impl/tls-certificate.js +6 -5
  35. package/dist/impl/tls-certificate.js.map +1 -1
  36. package/dist/index.js +106 -23
  37. package/dist/index.js.map +1 -1
  38. package/dist/job-PE4AKOHB.js +7 -0
  39. package/dist/job-PE4AKOHB.js.map +1 -0
  40. package/dist/stateful-set-LUIRHQJY.js +7 -0
  41. package/dist/{stateful-set-VJYKTQ72.js.map → stateful-set-LUIRHQJY.js.map} +1 -1
  42. package/dist/units/cert-manager/index.js +7 -8
  43. package/dist/units/cert-manager/index.js.map +1 -1
  44. package/dist/units/cluster-patch/index.js +6 -6
  45. package/dist/units/cluster-patch/index.js.map +1 -1
  46. package/dist/units/dns01-issuer/index.js +52 -15
  47. package/dist/units/dns01-issuer/index.js.map +1 -1
  48. package/dist/units/existing-cluster/index.js +39 -18
  49. package/dist/units/existing-cluster/index.js.map +1 -1
  50. package/dist/units/gateway-api/index.js +2 -2
  51. package/dist/units/reduced-access-cluster/index.js +8 -8
  52. package/dist/units/reduced-access-cluster/index.js.map +1 -1
  53. package/package.json +9 -7
  54. package/src/cluster.ts +12 -8
  55. package/src/config-map.ts +15 -5
  56. package/src/container.ts +4 -2
  57. package/src/cron-job.ts +25 -4
  58. package/src/deployment.ts +32 -17
  59. package/src/gateway/backend.ts +3 -3
  60. package/src/gateway/gateway.ts +12 -56
  61. package/src/helm.ts +354 -22
  62. package/src/impl/dynamic-endpoint-resolver.ts +109 -0
  63. package/src/impl/gateway-route.ts +231 -57
  64. package/src/impl/tls-certificate.ts +8 -3
  65. package/src/index.ts +1 -0
  66. package/src/job.ts +23 -5
  67. package/src/kubectl.ts +166 -0
  68. package/src/namespace.ts +47 -3
  69. package/src/network-policy.ts +1 -1
  70. package/src/pvc.ts +12 -2
  71. package/src/rbac.ts +28 -5
  72. package/src/scripting/environment.ts +3 -2
  73. package/src/secret.ts +15 -5
  74. package/src/service.ts +28 -6
  75. package/src/shared.ts +30 -2
  76. package/src/stateful-set.ts +32 -17
  77. package/src/tls.ts +31 -5
  78. package/src/units/cluster-patch/index.ts +5 -5
  79. package/src/units/dns01-issuer/index.ts +56 -12
  80. package/src/units/existing-cluster/index.ts +36 -15
  81. package/src/units/reduced-access-cluster/index.ts +6 -3
  82. package/src/worker.ts +4 -2
  83. package/src/workload.ts +453 -213
  84. package/dist/chunk-4G6LLC2X.js +0 -240
  85. package/dist/chunk-4G6LLC2X.js.map +0 -1
  86. package/dist/chunk-BR2CLUUD.js.map +0 -1
  87. package/dist/chunk-DCUMJSO6.js.map +0 -1
  88. package/dist/chunk-FE4SHRAJ.js.map +0 -1
  89. package/dist/chunk-KMLRI5UZ.js +0 -155
  90. package/dist/chunk-KMLRI5UZ.js.map +0 -1
  91. package/dist/chunk-LGHFSXNT.js.map +0 -1
  92. package/dist/chunk-MIC2BHGS.js.map +0 -1
  93. package/dist/chunk-OBDQONMV.js +0 -401
  94. package/dist/chunk-OBDQONMV.js.map +0 -1
  95. package/dist/chunk-P2VOUU7E.js.map +0 -1
  96. package/dist/chunk-PZ5AY32C.js +0 -9
  97. package/dist/chunk-RVB4WWZZ.js.map +0 -1
  98. package/dist/chunk-TWBMG6TD.js.map +0 -1
  99. package/dist/chunk-VCXWCZ43.js.map +0 -1
  100. package/dist/chunk-YIJUVPU2.js.map +0 -1
  101. package/dist/cron-job-NX4HD4FI.js +0 -8
  102. package/dist/deployment-O2LJ5WR5.js +0 -8
  103. package/dist/job-SYME6Y43.js +0 -8
  104. package/dist/job-SYME6Y43.js.map +0 -1
  105. package/dist/stateful-set-VJYKTQ72.js +0 -8
package/src/cluster.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import type { k8s, network } from "@highstate/library"
2
2
  import { isPrivateAddress, parseAddress } from "@highstate/common"
3
3
  import { text, type UnitTerminal } from "@highstate/contract"
4
- import { fileFromString, type Input, type Output, output } from "@highstate/pulumi"
4
+ import { type Input, makeFileOutput, type Output, output } from "@highstate/pulumi"
5
5
  import { CoreV1Api, type KubeConfig } from "@kubernetes/client-node"
6
6
  import { images } from "./shared"
7
7
 
@@ -54,20 +54,24 @@ export function createK8sTerminal(kubeconfig: Input<string>): Output<UnitTermina
54
54
  command: ["bash", "/welcome.sh"],
55
55
 
56
56
  files: {
57
- "/kubeconfig": fileFromString("kubeconfig", kubeconfig, { isSecret: true }),
58
-
59
- "/welcome.sh": fileFromString(
60
- "welcome.sh",
61
- text`
57
+ "/kubeconfig": makeFileOutput({
58
+ name: "kubeconfig",
59
+ content: kubeconfig,
60
+ isSecret: true,
61
+ }),
62
+
63
+ "/welcome.sh": makeFileOutput({
64
+ name: "welcome.sh",
65
+ content: text`
62
66
  echo "Connecting to the cluster..."
63
67
  kubectl cluster-info
64
68
 
65
- echo "Use 'kubectl' and 'helm' to manage the cluster."
69
+ echo "Use 'kubectl', 'helm' or 'k9s' to manage the cluster."
66
70
  echo
67
71
 
68
72
  exec bash
69
73
  `,
70
- ),
74
+ }),
71
75
  },
72
76
 
73
77
  env: {
package/src/config-map.ts CHANGED
@@ -1,15 +1,16 @@
1
- import type { k8s } from "@highstate/library"
2
1
  import { getOrCreate } from "@highstate/contract"
3
- import { toPromise } from "@highstate/pulumi"
4
- import { core, type types } from "@pulumi/kubernetes"
2
+ import { k8s } from "@highstate/library"
5
3
  import {
6
4
  type ComponentResourceOptions,
7
5
  type Input,
8
6
  type Inputs,
9
7
  interpolate,
8
+ makeEntityOutput,
10
9
  type Output,
11
10
  output,
12
- } from "@pulumi/pulumi"
11
+ toPromise,
12
+ } from "@highstate/pulumi"
13
+ import { core, type types } from "@pulumi/kubernetes"
13
14
  import { Namespace } from "./namespace"
14
15
  import { getProvider, mapMetadata, NamespacedResource, type ScopedResourceArgs } from "./shared"
15
16
 
@@ -51,7 +52,16 @@ export abstract class ConfigMap extends NamespacedResource {
51
52
  * The Highstate config map entity.
52
53
  */
53
54
  get entity(): Output<k8s.ConfigMap> {
54
- return output(this.entityBase)
55
+ return makeEntityOutput({
56
+ entity: k8s.configMapEntity,
57
+ identity: this.metadata.uid,
58
+ meta: {
59
+ title: this.metadata.name,
60
+ },
61
+ value: {
62
+ ...this.entityBase,
63
+ },
64
+ })
55
65
  }
56
66
 
57
67
  /**
package/src/container.ts CHANGED
@@ -120,6 +120,8 @@ export type ContainerEnvironmentSource =
120
120
  | types.input.core.v1.EnvFromSource
121
121
  | core.v1.ConfigMap
122
122
  | core.v1.Secret
123
+ | ConfigMap
124
+ | Secret
123
125
 
124
126
  export type ContainerVolumeMount =
125
127
  | types.input.core.v1.VolumeMount
@@ -268,7 +270,7 @@ export function mapVolumeMount(volumeMount: ContainerVolumeMount): types.input.c
268
270
  export function mapEnvironmentSource(
269
271
  envFrom: ContainerEnvironmentSource,
270
272
  ): types.input.core.v1.EnvFromSource {
271
- if (envFrom instanceof core.v1.ConfigMap) {
273
+ if (envFrom instanceof core.v1.ConfigMap || envFrom instanceof ConfigMap) {
272
274
  return {
273
275
  configMapRef: {
274
276
  name: envFrom.metadata.name,
@@ -276,7 +278,7 @@ export function mapEnvironmentSource(
276
278
  }
277
279
  }
278
280
 
279
- if (envFrom instanceof core.v1.Secret) {
281
+ if (envFrom instanceof core.v1.Secret || envFrom instanceof Secret) {
280
282
  return {
281
283
  secretRef: {
282
284
  name: envFrom.metadata.name,
package/src/cron-job.ts CHANGED
@@ -1,13 +1,14 @@
1
1
  import type { UnitTerminal } from "@highstate/contract"
2
- import type { k8s } from "@highstate/library"
3
2
  import type { Container } from "./container"
4
3
  import type { NetworkPolicy } from "./network-policy"
5
4
  import { getOrCreate } from "@highstate/contract"
5
+ import { k8s } from "@highstate/library"
6
6
  import {
7
7
  type ComponentResourceOptions,
8
8
  type Input,
9
9
  type Inputs,
10
10
  interpolate,
11
+ makeEntityOutput,
11
12
  type Output,
12
13
  output,
13
14
  toPromise,
@@ -19,6 +20,7 @@ import { omit } from "remeda"
19
20
  import { Namespace } from "./namespace"
20
21
  import { commonExtraArgs, getProvider, mapMetadata, type ScopedResourceArgs } from "./shared"
21
22
  import {
23
+ filterPatchOwnedContainersInTemplate,
22
24
  getWorkloadComponents,
23
25
  Workload,
24
26
  type WorkloadArgs,
@@ -96,7 +98,17 @@ export abstract class CronJob extends Workload {
96
98
  * The Highstate cron job entity.
97
99
  */
98
100
  get entity(): Output<k8s.CronJob> {
99
- return output(this.entityBase)
101
+ return makeEntityOutput({
102
+ entity: k8s.cronJobEntity,
103
+ identity: this.metadata.uid,
104
+ meta: {
105
+ title: this.metadata.name,
106
+ },
107
+ value: {
108
+ ...this.entityBase,
109
+ spec: this.spec.jobTemplate.spec,
110
+ },
111
+ })
100
112
  }
101
113
 
102
114
  protected getTerminalMeta(): Output<UnitTerminal["meta"]> {
@@ -313,7 +325,7 @@ class CronJobPatch extends CronJob {
313
325
  {
314
326
  metadata: mapMetadata(args, name),
315
327
  spec: output({ args, podTemplate }).apply(({ args, podTemplate }) => {
316
- return deepmerge(
328
+ const spec = deepmerge(
317
329
  {
318
330
  jobTemplate: {
319
331
  spec: {
@@ -323,7 +335,16 @@ class CronJobPatch extends CronJob {
323
335
  schedule: args.schedule!,
324
336
  } satisfies types.input.batch.v1.CronJobSpec,
325
337
  omit(args, cronJobExtraArgs) as types.input.batch.v1.CronJobSpec,
326
- )
338
+ ) as Unwrap<types.input.batch.v1.CronJobSpec>
339
+
340
+ if (spec.jobTemplate?.spec?.template) {
341
+ spec.jobTemplate.spec.template = filterPatchOwnedContainersInTemplate(
342
+ spec.jobTemplate.spec.template,
343
+ podTemplate,
344
+ )
345
+ }
346
+
347
+ return spec
327
348
  }),
328
349
  },
329
350
  {
package/src/deployment.ts CHANGED
@@ -1,14 +1,15 @@
1
1
  import type { AccessPointRoute } from "@highstate/common"
2
- import type { k8s } from "@highstate/library"
3
2
  import type { Container } from "./container"
4
3
  import type { NetworkPolicy } from "./network-policy"
5
4
  import type { Service } from "./service"
6
5
  import { getOrCreate, type UnitTerminal } from "@highstate/contract"
6
+ import { k8s } from "@highstate/library"
7
7
  import {
8
8
  type ComponentResourceOptions,
9
9
  type Input,
10
10
  type Inputs,
11
11
  interpolate,
12
+ makeEntityOutput,
12
13
  type Output,
13
14
  output,
14
15
  toPromise,
@@ -20,14 +21,15 @@ import { omit } from "remeda"
20
21
  import { Namespace } from "./namespace"
21
22
  import { getProvider, mapMetadata } from "./shared"
22
23
  import {
23
- ExposableWorkload,
24
- type ExposableWorkloadArgs,
25
- exposableWorkloadExtraArgs,
26
- getExposableWorkloadComponents,
24
+ filterPatchOwnedContainersInTemplate,
25
+ getWorkloadServiceComponents,
26
+ Workload,
27
+ type WorkloadServiceArgs,
27
28
  type WorkloadTerminalArgs,
29
+ workloadServiceExtraArgs,
28
30
  } from "./workload"
29
31
 
30
- export type DeploymentArgs = Omit<ExposableWorkloadArgs, "existing"> &
32
+ export type DeploymentArgs = Omit<WorkloadServiceArgs, "existing"> &
31
33
  Omit<Partial<types.input.apps.v1.DeploymentSpec>, "template"> & {
32
34
  template?: {
33
35
  metadata?: types.input.meta.v1.ObjectMeta
@@ -42,7 +44,7 @@ export type CreateOrGetDeploymentArgs = DeploymentArgs & {
42
44
  existing: Input<k8s.Deployment> | undefined
43
45
  }
44
46
 
45
- export abstract class Deployment extends ExposableWorkload {
47
+ export abstract class Deployment extends Workload {
46
48
  static readonly apiVersion = "apps/v1"
47
49
  static readonly kind = "Deployment"
48
50
 
@@ -107,10 +109,17 @@ export abstract class Deployment extends ExposableWorkload {
107
109
  get entity(): Output<k8s.Deployment> {
108
110
  const service = this._service.apply(service => service?.entity)
109
111
 
110
- return output({
111
- ...this.entityBase,
112
- service,
113
- endpoints: service.apply(svc => output(svc?.endpoints ?? [])),
112
+ return makeEntityOutput({
113
+ entity: k8s.deploymentEntity,
114
+ identity: this.metadata.uid,
115
+ meta: {
116
+ title: this.metadata.name,
117
+ },
118
+ value: {
119
+ ...this.entityBase,
120
+ service,
121
+ spec: this.spec,
122
+ },
114
123
  })
115
124
  }
116
125
 
@@ -249,7 +258,7 @@ export abstract class Deployment extends ExposableWorkload {
249
258
  class CreatedDeployment extends Deployment {
250
259
  constructor(name: string, args: DeploymentArgs, opts?: ComponentResourceOptions) {
251
260
  const { labels, podTemplate, networkPolicy, containers, service, routes } =
252
- getExposableWorkloadComponents(name, args, () => this, opts)
261
+ getWorkloadServiceComponents(name, args, () => this, opts)
253
262
 
254
263
  const deployment = output(args.namespace).cluster.apply(cluster => {
255
264
  return new apps.v1.Deployment(
@@ -262,7 +271,7 @@ class CreatedDeployment extends Deployment {
262
271
  template: podTemplate,
263
272
  selector: { matchLabels: labels },
264
273
  },
265
- omit(args, exposableWorkloadExtraArgs),
274
+ omit(args, workloadServiceExtraArgs),
266
275
  ) as types.input.apps.v1.DeploymentSpec
267
276
  }),
268
277
  },
@@ -295,7 +304,7 @@ class CreatedDeployment extends Deployment {
295
304
  class DeploymentPatch extends Deployment {
296
305
  constructor(name: string, args: DeploymentArgs, opts?: ComponentResourceOptions) {
297
306
  const { podTemplate, networkPolicy, containers, service, routes } =
298
- getExposableWorkloadComponents(name, args, () => this, opts, true)
307
+ getWorkloadServiceComponents(name, args, () => this, opts, true)
299
308
 
300
309
  const deployment = output(args.namespace).cluster.apply(cluster => {
301
310
  return new apps.v1.DeploymentPatch(
@@ -303,10 +312,16 @@ class DeploymentPatch extends Deployment {
303
312
  {
304
313
  metadata: mapMetadata(args, name),
305
314
  spec: output({ args, podTemplate }).apply(({ args, podTemplate }) => {
306
- return deepmerge(
315
+ const spec = deepmerge(
307
316
  { template: podTemplate },
308
- omit(args, exposableWorkloadExtraArgs),
309
- ) as types.input.apps.v1.DeploymentSpec
317
+ omit(args, workloadServiceExtraArgs),
318
+ ) as Unwrap<types.input.apps.v1.DeploymentSpec>
319
+
320
+ if (spec.template) {
321
+ spec.template = filterPatchOwnedContainersInTemplate(spec.template, podTemplate)
322
+ }
323
+
324
+ return spec
310
325
  }),
311
326
  },
312
327
  {
@@ -24,12 +24,12 @@ export interface ServiceBackendRef {
24
24
  /**
25
25
  * The name of the service being referenced.
26
26
  */
27
- service: Input<core.v1.Service>
27
+ service: Input<core.v1.Service | Service>
28
28
 
29
29
  /**
30
30
  * The port of the service being referenced.
31
31
  */
32
- port: Input<number>
32
+ port?: Input<number>
33
33
  }
34
34
 
35
35
  export type BackendRef = FullBackendRef | ServiceBackendRef | Service
@@ -49,7 +49,7 @@ export function resolveBackendRef(ref: BackendRef): Output<Unwrap<FullBackendRef
49
49
  return output({
50
50
  name: service.metadata.name,
51
51
  namespace: service.metadata.namespace,
52
- port: ref.port,
52
+ port: ref.port ?? service.spec.ports[0].port,
53
53
  })
54
54
  }
55
55
 
@@ -1,15 +1,15 @@
1
- import type { k8s, network } from "@highstate/library"
2
1
  import type { types } from "@pulumi/kubernetes"
3
- import type { SetRequired } from "type-fest"
4
2
  import { parseEndpoint } from "@highstate/common"
5
3
  import { getOrCreate } from "@highstate/contract"
6
4
  import { gateway, type types as gwTypes } from "@highstate/gateway-api"
5
+ import { k8s, type network } from "@highstate/library"
7
6
  import {
8
7
  type ComponentResourceOptions,
9
8
  type Input,
10
9
  type InputArray,
11
10
  type Inputs,
12
11
  interpolate,
12
+ makeEntityOutput,
13
13
  type Output,
14
14
  output,
15
15
  toPromise,
@@ -81,7 +81,16 @@ export abstract class Gateway extends NamespacedResource {
81
81
  * The Highstate gateway entity.
82
82
  */
83
83
  get entity(): Output<k8s.Gateway> {
84
- return output(this.entityBase)
84
+ return makeEntityOutput({
85
+ entity: k8s.gatewayEntity,
86
+ identity: this.metadata.uid,
87
+ meta: {
88
+ title: this.metadata.name,
89
+ },
90
+ value: {
91
+ ...this.entityBase,
92
+ },
93
+ })
85
94
  }
86
95
 
87
96
  /**
@@ -217,59 +226,6 @@ export abstract class Gateway extends NamespacedResource {
217
226
 
218
227
  return Gateway.for(resolvedEntity, output(cluster))
219
228
  }
220
-
221
- /**
222
- * Creates a gateway with the provided name/namespace/cluster only once.
223
- *
224
- * It automatically names the resource with the following format: `{name}.{namespace}.{clusterName}.{clusterId}`.
225
- *
226
- * On subsequent calls the gateway is patched with the union of existing and requested listeners.
227
- * Only the listeners field is modified to avoid altering other spec fields.
228
- *
229
- * @param name The name of the gateway to create.
230
- * @param args The arguments to create the gateway with.
231
- * @param opts Optional resource options.
232
- */
233
- static async createOnce(
234
- args: SetRequired<GatewayArgs, "name">,
235
- opts?: ComponentResourceOptions,
236
- ): Promise<Gateway> {
237
- const { name, namespace, cluster } = await toPromise({
238
- name: args.name,
239
- namespace: output(args.namespace).metadata.name,
240
- cluster: output(args.namespace).cluster,
241
- })
242
-
243
- const fullName = `${name}.${namespace}.${cluster.name}.${cluster.id}`
244
-
245
- const existing = Gateway.gatewayCache.get(fullName)
246
- if (existing) {
247
- Gateway.patch(
248
- fullName,
249
- {
250
- name,
251
- namespace: args.namespace,
252
- listeners: args.listeners,
253
- },
254
- opts,
255
- )
256
-
257
- return existing
258
- }
259
-
260
- const created = Gateway.create(
261
- fullName,
262
- {
263
- ...args,
264
- name,
265
- namespace: args.namespace,
266
- },
267
- opts,
268
- )
269
-
270
- Gateway.gatewayCache.set(fullName, created)
271
- return created
272
- }
273
229
  }
274
230
 
275
231
  class CreatedGateway extends Gateway {