@highstate/k8s 0.18.0 → 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.
- package/dist/{chunk-FE4SHRAJ.js → chunk-23X5SXQG.js} +22 -7
- package/dist/chunk-23X5SXQG.js.map +1 -0
- package/dist/{chunk-LGHFSXNT.js → chunk-ADHZK6V2.js} +14 -10
- package/dist/chunk-ADHZK6V2.js.map +1 -0
- package/dist/{chunk-VCXWCZ43.js → chunk-BTAEFJ5N.js} +27 -15
- package/dist/chunk-BTAEFJ5N.js.map +1 -0
- package/dist/{chunk-BR2CLUUD.js → chunk-IXE3OKB4.js} +27 -8
- package/dist/chunk-IXE3OKB4.js.map +1 -0
- package/dist/{chunk-TWBMG6TD.js → chunk-OG2OPX7B.js} +30 -12
- package/dist/chunk-OG2OPX7B.js.map +1 -0
- package/dist/{chunk-DCUMJSO6.js → chunk-P26SQ2ZB.js} +17 -51
- package/dist/chunk-P26SQ2ZB.js.map +1 -0
- package/dist/{chunk-MIC2BHGS.js → chunk-PG27ZY2H.js} +25 -7
- package/dist/chunk-PG27ZY2H.js.map +1 -0
- package/dist/chunk-PZYGZSN5.js +54 -0
- package/dist/{chunk-PZ5AY32C.js.map → chunk-PZYGZSN5.js.map} +1 -1
- package/dist/{chunk-YIJUVPU2.js → chunk-S77TE7UC.js} +27 -15
- package/dist/chunk-S77TE7UC.js.map +1 -0
- package/dist/{chunk-P2VOUU7E.js → chunk-SZKOAHNX.js} +383 -205
- package/dist/chunk-SZKOAHNX.js.map +1 -0
- package/dist/chunk-TOLFVF4S.js +889 -0
- package/dist/chunk-TOLFVF4S.js.map +1 -0
- package/dist/{chunk-RVB4WWZZ.js → chunk-TVKT3ZYX.js} +174 -18
- package/dist/chunk-TVKT3ZYX.js.map +1 -0
- package/dist/cron-job-RKB2HYTO.js +7 -0
- package/dist/{cron-job-NX4HD4FI.js.map → cron-job-RKB2HYTO.js.map} +1 -1
- package/dist/deployment-T35TUOL2.js +7 -0
- package/dist/{deployment-O2LJ5WR5.js.map → deployment-T35TUOL2.js.map} +1 -1
- package/dist/highstate.manifest.json +3 -2
- package/dist/impl/dynamic-endpoint-resolver.js +90 -0
- package/dist/impl/dynamic-endpoint-resolver.js.map +1 -0
- package/dist/impl/gateway-route.js +159 -62
- package/dist/impl/gateway-route.js.map +1 -1
- package/dist/impl/tls-certificate.js +6 -5
- package/dist/impl/tls-certificate.js.map +1 -1
- package/dist/index.js +106 -23
- package/dist/index.js.map +1 -1
- package/dist/job-PE4AKOHB.js +7 -0
- package/dist/job-PE4AKOHB.js.map +1 -0
- package/dist/stateful-set-LUIRHQJY.js +7 -0
- package/dist/{stateful-set-VJYKTQ72.js.map → stateful-set-LUIRHQJY.js.map} +1 -1
- package/dist/units/cert-manager/index.js +7 -8
- package/dist/units/cert-manager/index.js.map +1 -1
- package/dist/units/cluster-patch/index.js +6 -6
- package/dist/units/cluster-patch/index.js.map +1 -1
- package/dist/units/dns01-issuer/index.js +52 -15
- package/dist/units/dns01-issuer/index.js.map +1 -1
- package/dist/units/existing-cluster/index.js +39 -18
- package/dist/units/existing-cluster/index.js.map +1 -1
- package/dist/units/gateway-api/index.js +2 -2
- package/dist/units/reduced-access-cluster/index.js +8 -8
- package/dist/units/reduced-access-cluster/index.js.map +1 -1
- package/package.json +9 -7
- package/src/cluster.ts +12 -8
- package/src/config-map.ts +15 -5
- package/src/container.ts +4 -2
- package/src/cron-job.ts +25 -4
- package/src/deployment.ts +32 -17
- package/src/gateway/backend.ts +3 -3
- package/src/gateway/gateway.ts +12 -56
- package/src/helm.ts +354 -22
- package/src/impl/dynamic-endpoint-resolver.ts +109 -0
- package/src/impl/gateway-route.ts +231 -57
- package/src/impl/tls-certificate.ts +8 -3
- package/src/index.ts +1 -0
- package/src/job.ts +23 -5
- package/src/kubectl.ts +166 -0
- package/src/namespace.ts +47 -3
- package/src/network-policy.ts +1 -1
- package/src/pvc.ts +12 -2
- package/src/rbac.ts +28 -5
- package/src/scripting/environment.ts +3 -2
- package/src/secret.ts +15 -5
- package/src/service.ts +28 -6
- package/src/shared.ts +30 -2
- package/src/stateful-set.ts +32 -17
- package/src/tls.ts +31 -5
- package/src/units/cluster-patch/index.ts +5 -5
- package/src/units/dns01-issuer/index.ts +56 -12
- package/src/units/existing-cluster/index.ts +36 -15
- package/src/units/reduced-access-cluster/index.ts +6 -3
- package/src/worker.ts +4 -2
- package/src/workload.ts +453 -213
- package/dist/chunk-4G6LLC2X.js +0 -240
- package/dist/chunk-4G6LLC2X.js.map +0 -1
- package/dist/chunk-BR2CLUUD.js.map +0 -1
- package/dist/chunk-DCUMJSO6.js.map +0 -1
- package/dist/chunk-FE4SHRAJ.js.map +0 -1
- package/dist/chunk-KMLRI5UZ.js +0 -155
- package/dist/chunk-KMLRI5UZ.js.map +0 -1
- package/dist/chunk-LGHFSXNT.js.map +0 -1
- package/dist/chunk-MIC2BHGS.js.map +0 -1
- package/dist/chunk-OBDQONMV.js +0 -401
- package/dist/chunk-OBDQONMV.js.map +0 -1
- package/dist/chunk-P2VOUU7E.js.map +0 -1
- package/dist/chunk-PZ5AY32C.js +0 -9
- package/dist/chunk-RVB4WWZZ.js.map +0 -1
- package/dist/chunk-TWBMG6TD.js.map +0 -1
- package/dist/chunk-VCXWCZ43.js.map +0 -1
- package/dist/chunk-YIJUVPU2.js.map +0 -1
- package/dist/cron-job-NX4HD4FI.js +0 -8
- package/dist/deployment-O2LJ5WR5.js +0 -8
- package/dist/job-SYME6Y43.js +0 -8
- package/dist/job-SYME6Y43.js.map +0 -1
- package/dist/stateful-set-VJYKTQ72.js +0 -8
package/src/namespace.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type { k8s } from "@highstate/library"
|
|
2
1
|
import { getOrCreate } from "@highstate/contract"
|
|
3
|
-
import {
|
|
2
|
+
import { k8s } from "@highstate/library"
|
|
3
|
+
import { makeEntityOutput, toPromise } from "@highstate/pulumi"
|
|
4
4
|
import { core, type types } from "@pulumi/kubernetes"
|
|
5
5
|
import {
|
|
6
6
|
type ComponentResourceOptions,
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
output,
|
|
11
11
|
type Unwrap,
|
|
12
12
|
} from "@pulumi/pulumi"
|
|
13
|
+
import { ClusterAccessScope } from "./rbac"
|
|
13
14
|
import {
|
|
14
15
|
getProvider,
|
|
15
16
|
mapMetadata,
|
|
@@ -48,6 +49,13 @@ export abstract class Namespace extends Resource {
|
|
|
48
49
|
static readonly apiVersion = "v1"
|
|
49
50
|
static readonly kind = "Namespace"
|
|
50
51
|
|
|
52
|
+
/**
|
|
53
|
+
* The cluster entity authorized to port-forward into the namespace.
|
|
54
|
+
*
|
|
55
|
+
* Only created for namespaces created with `create` or `createOrGet` methods, not for wrapped or external namespaces.
|
|
56
|
+
*/
|
|
57
|
+
portForwardCluster?: Output<k8s.Cluster>
|
|
58
|
+
|
|
51
59
|
constructor(
|
|
52
60
|
type: string,
|
|
53
61
|
name: string,
|
|
@@ -74,7 +82,16 @@ export abstract class Namespace extends Resource {
|
|
|
74
82
|
* The Highstate namespace entity.
|
|
75
83
|
*/
|
|
76
84
|
get entity(): Output<k8s.Namespace> {
|
|
77
|
-
return
|
|
85
|
+
return makeEntityOutput({
|
|
86
|
+
entity: k8s.namespaceEntity,
|
|
87
|
+
identity: this.metadata.uid,
|
|
88
|
+
meta: {
|
|
89
|
+
title: this.metadata.name,
|
|
90
|
+
},
|
|
91
|
+
value: {
|
|
92
|
+
...this.entityBase,
|
|
93
|
+
},
|
|
94
|
+
})
|
|
78
95
|
}
|
|
79
96
|
|
|
80
97
|
/**
|
|
@@ -298,6 +315,33 @@ class CreatedNamespace extends Namespace {
|
|
|
298
315
|
namespace.spec,
|
|
299
316
|
namespace.status,
|
|
300
317
|
)
|
|
318
|
+
|
|
319
|
+
const scope = new ClusterAccessScope(
|
|
320
|
+
`${name}-port-forward`,
|
|
321
|
+
{
|
|
322
|
+
namespace: this,
|
|
323
|
+
rules: [
|
|
324
|
+
{
|
|
325
|
+
apiGroups: [""],
|
|
326
|
+
resources: ["services"],
|
|
327
|
+
verbs: ["get"],
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
apiGroups: [""],
|
|
331
|
+
resources: ["pods"],
|
|
332
|
+
verbs: ["get", "list"],
|
|
333
|
+
},
|
|
334
|
+
{
|
|
335
|
+
apiGroups: [""],
|
|
336
|
+
resources: ["pods/portforward"],
|
|
337
|
+
verbs: ["create"],
|
|
338
|
+
},
|
|
339
|
+
],
|
|
340
|
+
},
|
|
341
|
+
{ parent: this },
|
|
342
|
+
)
|
|
343
|
+
|
|
344
|
+
this.portForwardCluster = scope.cluster
|
|
301
345
|
}
|
|
302
346
|
}
|
|
303
347
|
|
package/src/network-policy.ts
CHANGED
|
@@ -360,7 +360,7 @@ export type NetworkPolicyArgs = ScopedResourceArgs & {
|
|
|
360
360
|
* The pod selector for this network policy.
|
|
361
361
|
* If not provided, it will select all pods in the namespace.
|
|
362
362
|
*/
|
|
363
|
-
selector?: SelectorLike
|
|
363
|
+
selector?: Input<SelectorLike>
|
|
364
364
|
|
|
365
365
|
/**
|
|
366
366
|
* The rule for incoming traffic.
|
package/src/pvc.ts
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import type { k8s } from "@highstate/library"
|
|
2
1
|
import { getOrCreate } from "@highstate/contract"
|
|
2
|
+
import { k8s } from "@highstate/library"
|
|
3
3
|
import {
|
|
4
4
|
type ComponentResourceOptions,
|
|
5
5
|
type Input,
|
|
6
6
|
type Inputs,
|
|
7
7
|
interpolate,
|
|
8
|
+
makeEntityOutput,
|
|
8
9
|
type Output,
|
|
9
10
|
output,
|
|
10
11
|
toPromise,
|
|
@@ -73,7 +74,16 @@ export abstract class PersistentVolumeClaim extends NamespacedResource {
|
|
|
73
74
|
* The Highstate PVC entity.
|
|
74
75
|
*/
|
|
75
76
|
get entity(): Output<k8s.PersistentVolumeClaim> {
|
|
76
|
-
return
|
|
77
|
+
return makeEntityOutput({
|
|
78
|
+
entity: k8s.persistentVolumeClaimEntity,
|
|
79
|
+
identity: this.metadata.uid,
|
|
80
|
+
meta: {
|
|
81
|
+
title: this.metadata.name,
|
|
82
|
+
},
|
|
83
|
+
value: {
|
|
84
|
+
...this.entityBase,
|
|
85
|
+
},
|
|
86
|
+
})
|
|
77
87
|
}
|
|
78
88
|
|
|
79
89
|
/**
|
package/src/rbac.ts
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import type { k8s } from "@highstate/library"
|
|
2
1
|
import type { Namespace } from "./namespace"
|
|
2
|
+
import { common, type k8s } from "@highstate/library"
|
|
3
3
|
import {
|
|
4
4
|
ComponentResource,
|
|
5
5
|
type ComponentResourceOptions,
|
|
6
6
|
type Input,
|
|
7
7
|
type InputArray,
|
|
8
8
|
interpolate,
|
|
9
|
+
makeEntity,
|
|
9
10
|
normalizeInputs,
|
|
10
11
|
type Output,
|
|
11
12
|
output,
|
|
@@ -15,7 +16,6 @@ import {
|
|
|
15
16
|
import { KubeConfig } from "@kubernetes/client-node"
|
|
16
17
|
import { core, rbac, type types } from "@pulumi/kubernetes"
|
|
17
18
|
import { map, unique } from "remeda"
|
|
18
|
-
import { stringify } from "yaml"
|
|
19
19
|
import { Secret } from "./secret"
|
|
20
20
|
import {
|
|
21
21
|
getNamespaceName,
|
|
@@ -185,9 +185,14 @@ export class ClusterAccessScope extends ComponentResource {
|
|
|
185
185
|
kubeconfig,
|
|
186
186
|
newToken: accessTokenSecret.getValue("token"),
|
|
187
187
|
serviceAccount: serviceAccount.metadata.name,
|
|
188
|
-
|
|
188
|
+
serviceAccountId: serviceAccount.metadata.uid,
|
|
189
|
+
}).apply(({ cluster, kubeconfig, newToken, serviceAccount, serviceAccountId }) => {
|
|
190
|
+
if (kubeconfig.content.type !== "embedded-secret") {
|
|
191
|
+
throw new Error("Only embedded secrets are supported for cluster kubeconfig for now")
|
|
192
|
+
}
|
|
193
|
+
|
|
189
194
|
const config = new KubeConfig()
|
|
190
|
-
config.loadFromString(kubeconfig)
|
|
195
|
+
config.loadFromString(kubeconfig.content.value.value)
|
|
191
196
|
|
|
192
197
|
// clear all existing contexts and users
|
|
193
198
|
config.users = []
|
|
@@ -205,7 +210,25 @@ export class ClusterAccessScope extends ComponentResource {
|
|
|
205
210
|
|
|
206
211
|
return {
|
|
207
212
|
...cluster,
|
|
208
|
-
|
|
213
|
+
connectionId: serviceAccountId,
|
|
214
|
+
kubeconfig: makeEntity({
|
|
215
|
+
entity: common.fileEntity,
|
|
216
|
+
identity: `${serviceAccountId}:kubeconfig`,
|
|
217
|
+
meta: {
|
|
218
|
+
title: `kubeconfig for SA ${serviceAccount}`,
|
|
219
|
+
},
|
|
220
|
+
value: {
|
|
221
|
+
content: {
|
|
222
|
+
type: "embedded-secret",
|
|
223
|
+
value: config.exportConfig(),
|
|
224
|
+
},
|
|
225
|
+
meta: {
|
|
226
|
+
name: "kubeconfig",
|
|
227
|
+
contentType: "text/yaml",
|
|
228
|
+
mode: 0o600,
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
}),
|
|
209
232
|
}
|
|
210
233
|
})
|
|
211
234
|
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { InputEndpoint } from "@highstate/common"
|
|
2
2
|
import type { Input, InputArray, InputRecord } from "@highstate/pulumi"
|
|
3
3
|
import type { ContainerEnvironment, ContainerVolumeMount, WorkloadVolume } from "../container"
|
|
4
|
+
import { images } from ".."
|
|
4
5
|
|
|
5
6
|
export type ScriptDistribution = "alpine" | "ubuntu"
|
|
6
7
|
|
|
@@ -94,7 +95,7 @@ const emptyDistributionEnvironment = {
|
|
|
94
95
|
export const emptyScriptEnvironment: ResolvedScriptEnvironment = {
|
|
95
96
|
alpine: {
|
|
96
97
|
...emptyDistributionEnvironment,
|
|
97
|
-
image:
|
|
98
|
+
image: images.alpine.image,
|
|
98
99
|
allowedEndpoints: [
|
|
99
100
|
//
|
|
100
101
|
"tcp://dl-cdn.alpinelinux.org:443",
|
|
@@ -104,7 +105,7 @@ export const emptyScriptEnvironment: ResolvedScriptEnvironment = {
|
|
|
104
105
|
|
|
105
106
|
ubuntu: {
|
|
106
107
|
...emptyDistributionEnvironment,
|
|
107
|
-
image:
|
|
108
|
+
image: images.ubuntu.image,
|
|
108
109
|
allowedEndpoints: [
|
|
109
110
|
//
|
|
110
111
|
"tcp://archive.ubuntu.com:80",
|
package/src/secret.ts
CHANGED
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import type { k8s } from "@highstate/library"
|
|
2
1
|
import { getOrCreate } from "@highstate/contract"
|
|
3
|
-
import {
|
|
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
|
-
|
|
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
|
|
|
@@ -56,7 +57,16 @@ export abstract class Secret extends NamespacedResource {
|
|
|
56
57
|
* The Highstate secret entity.
|
|
57
58
|
*/
|
|
58
59
|
get entity(): Output<k8s.Secret> {
|
|
59
|
-
return
|
|
60
|
+
return makeEntityOutput({
|
|
61
|
+
entity: k8s.secretEntity,
|
|
62
|
+
identity: this.metadata.uid,
|
|
63
|
+
meta: {
|
|
64
|
+
title: this.metadata.name,
|
|
65
|
+
},
|
|
66
|
+
value: {
|
|
67
|
+
...this.entityBase,
|
|
68
|
+
},
|
|
69
|
+
})
|
|
60
70
|
}
|
|
61
71
|
|
|
62
72
|
/**
|
package/src/service.ts
CHANGED
|
@@ -6,12 +6,13 @@ import {
|
|
|
6
6
|
parseL4Protocol,
|
|
7
7
|
} from "@highstate/common"
|
|
8
8
|
import { check, getOrCreate } from "@highstate/contract"
|
|
9
|
-
import { k8s, type network } from "@highstate/library"
|
|
9
|
+
import { type ImplementationReference, k8s, type network } from "@highstate/library"
|
|
10
10
|
import {
|
|
11
11
|
type ComponentResourceOptions,
|
|
12
12
|
type Input,
|
|
13
13
|
type Inputs,
|
|
14
14
|
interpolate,
|
|
15
|
+
makeEntityOutput,
|
|
15
16
|
normalize,
|
|
16
17
|
type Output,
|
|
17
18
|
output,
|
|
@@ -101,9 +102,16 @@ export abstract class Service extends NamespacedResource {
|
|
|
101
102
|
* The Highstate service entity.
|
|
102
103
|
*/
|
|
103
104
|
get entity(): Output<k8s.Service> {
|
|
104
|
-
return
|
|
105
|
-
|
|
106
|
-
|
|
105
|
+
return makeEntityOutput({
|
|
106
|
+
entity: k8s.serviceEntity,
|
|
107
|
+
identity: this.metadata.uid,
|
|
108
|
+
meta: {
|
|
109
|
+
title: this.metadata.name,
|
|
110
|
+
},
|
|
111
|
+
value: {
|
|
112
|
+
...this.entityBase,
|
|
113
|
+
endpoints: this.endpoints,
|
|
114
|
+
},
|
|
107
115
|
})
|
|
108
116
|
}
|
|
109
117
|
|
|
@@ -230,6 +238,8 @@ export abstract class Service extends NamespacedResource {
|
|
|
230
238
|
|
|
231
239
|
/**
|
|
232
240
|
* Returns the endpoints of the service including both internal and external endpoints.
|
|
241
|
+
*
|
|
242
|
+
* Also includes an `implRef` for port-forwarding if the namespace was created with port-forwarding enabled.
|
|
233
243
|
*/
|
|
234
244
|
get endpoints(): Output<k8s.ServiceEndpoint[]> {
|
|
235
245
|
return output({
|
|
@@ -237,7 +247,8 @@ export abstract class Service extends NamespacedResource {
|
|
|
237
247
|
metadata: this.metadata,
|
|
238
248
|
spec: this.spec,
|
|
239
249
|
status: this.status,
|
|
240
|
-
|
|
250
|
+
portForwardCluster: this.namespace.portForwardCluster,
|
|
251
|
+
}).apply(({ cluster, metadata, spec, status, portForwardCluster }) => {
|
|
241
252
|
function createMetadata(isInternal: boolean): k8s.EndpointServiceMetadata {
|
|
242
253
|
return {
|
|
243
254
|
"k8s.service": {
|
|
@@ -252,6 +263,15 @@ export abstract class Service extends NamespacedResource {
|
|
|
252
263
|
}
|
|
253
264
|
}
|
|
254
265
|
|
|
266
|
+
const implRef: ImplementationReference | undefined = portForwardCluster
|
|
267
|
+
? {
|
|
268
|
+
package: "@highstate/k8s",
|
|
269
|
+
data: {
|
|
270
|
+
cluster: portForwardCluster,
|
|
271
|
+
},
|
|
272
|
+
}
|
|
273
|
+
: undefined
|
|
274
|
+
|
|
255
275
|
const internalHosts = spec.clusterIPs.length
|
|
256
276
|
? [...spec.clusterIPs, `${metadata.name}.${metadata.namespace}.svc.cluster.local`]
|
|
257
277
|
: []
|
|
@@ -263,6 +283,7 @@ export abstract class Service extends NamespacedResource {
|
|
|
263
283
|
parseEndpoint,
|
|
264
284
|
endpoint => l3EndpointToL4(endpoint, port.port, parseL4Protocol(port.protocol)),
|
|
265
285
|
endpoint => addEndpointMetadata(endpoint, createMetadata(true)),
|
|
286
|
+
endpoint => (implRef ? { ...endpoint, implRef } : endpoint),
|
|
266
287
|
),
|
|
267
288
|
),
|
|
268
289
|
)
|
|
@@ -282,8 +303,9 @@ export abstract class Service extends NamespacedResource {
|
|
|
282
303
|
pipe(
|
|
283
304
|
ip,
|
|
284
305
|
parseEndpoint,
|
|
285
|
-
endpoint => l3EndpointToL4(endpoint, port.
|
|
306
|
+
endpoint => l3EndpointToL4(endpoint, port.nodePort, parseL4Protocol(port.protocol)),
|
|
286
307
|
endpoint => addEndpointMetadata(endpoint, createMetadata(false)),
|
|
308
|
+
endpoint => (implRef ? { ...endpoint, implRef } : endpoint),
|
|
287
309
|
),
|
|
288
310
|
),
|
|
289
311
|
)
|
package/src/shared.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PartialKeys } from "@highstate/contract"
|
|
2
|
-
import type { k8s } from "@highstate/library"
|
|
2
|
+
import type { common, k8s } from "@highstate/library"
|
|
3
3
|
import {
|
|
4
4
|
ComponentResource,
|
|
5
5
|
type ComponentResourceOptions,
|
|
@@ -24,7 +24,13 @@ export function getProvider(cluster: k8s.Cluster): Provider {
|
|
|
24
24
|
return existing
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
if (cluster.kubeconfig.content.type !== "embedded-secret") {
|
|
28
|
+
throw new Error("Only embedded secrets are supported for cluster kubeconfig for now")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const provider = new Provider(name, {
|
|
32
|
+
kubeconfig: secret(cluster.kubeconfig.content.value.value),
|
|
33
|
+
})
|
|
28
34
|
providers.set(name, provider)
|
|
29
35
|
|
|
30
36
|
return provider
|
|
@@ -36,6 +42,28 @@ export async function getProviderAsync(cluster: Input<k8s.Cluster>): Promise<Pro
|
|
|
36
42
|
return getProvider(resolvedCluster)
|
|
37
43
|
}
|
|
38
44
|
|
|
45
|
+
export function getEmbeddedSecretFileContent(file: Input<common.File>): Output<string> {
|
|
46
|
+
return output(file).apply(file => {
|
|
47
|
+
if (file.content.type !== "embedded-secret") {
|
|
48
|
+
throw new Error("Only embedded-secret file contents are supported for kubeconfig for now")
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
return file.content.value.value
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function getClusterKubeconfigContent(cluster: Input<k8s.Cluster>): Output<string> {
|
|
56
|
+
return output(cluster).apply(cluster => {
|
|
57
|
+
if (cluster.kubeconfig.content.type !== "embedded-secret") {
|
|
58
|
+
throw new Error(
|
|
59
|
+
"Only embedded-secret file contents are supported for cluster kubeconfig for now",
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return cluster.kubeconfig.content.value.value
|
|
64
|
+
})
|
|
65
|
+
}
|
|
66
|
+
|
|
39
67
|
export type NamespaceLike = core.v1.Namespace | Namespace | string
|
|
40
68
|
|
|
41
69
|
export type ScopedResourceArgs = {
|
package/src/stateful-set.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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
filterPatchOwnedContainersInTemplate,
|
|
25
|
+
getWorkloadServiceComponents,
|
|
26
|
+
Workload,
|
|
27
|
+
type WorkloadServiceArgs,
|
|
27
28
|
type WorkloadTerminalArgs,
|
|
29
|
+
workloadServiceExtraArgs,
|
|
28
30
|
} from "./workload"
|
|
29
31
|
|
|
30
|
-
export type StatefulSetArgs = Omit<
|
|
32
|
+
export type StatefulSetArgs = Omit<WorkloadServiceArgs, "existing"> &
|
|
31
33
|
Omit<Partial<types.input.apps.v1.StatefulSetSpec>, "template"> & {
|
|
32
34
|
template?: {
|
|
33
35
|
metadata?: types.input.meta.v1.ObjectMeta
|
|
@@ -42,7 +44,7 @@ export type CreateOrGetStatefulSetArgs = StatefulSetArgs & {
|
|
|
42
44
|
existing: Input<k8s.StatefulSet> | undefined
|
|
43
45
|
}
|
|
44
46
|
|
|
45
|
-
export abstract class StatefulSet extends
|
|
47
|
+
export abstract class StatefulSet extends Workload {
|
|
46
48
|
static apiVersion = "apps/v1"
|
|
47
49
|
static kind = "StatefulSet"
|
|
48
50
|
|
|
@@ -95,10 +97,17 @@ export abstract class StatefulSet extends ExposableWorkload {
|
|
|
95
97
|
* The Highstate stateful set entity.
|
|
96
98
|
*/
|
|
97
99
|
get entity(): Output<k8s.StatefulSet> {
|
|
98
|
-
return
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
100
|
+
return makeEntityOutput({
|
|
101
|
+
entity: k8s.statefulSetEntity,
|
|
102
|
+
identity: this.metadata.uid,
|
|
103
|
+
meta: {
|
|
104
|
+
title: this.metadata.name,
|
|
105
|
+
},
|
|
106
|
+
value: {
|
|
107
|
+
...this.entityBase,
|
|
108
|
+
service: this.service.entity,
|
|
109
|
+
spec: this.spec,
|
|
110
|
+
},
|
|
102
111
|
})
|
|
103
112
|
}
|
|
104
113
|
|
|
@@ -250,7 +259,7 @@ export abstract class StatefulSet extends ExposableWorkload {
|
|
|
250
259
|
class CreatedStatefulSet extends StatefulSet {
|
|
251
260
|
constructor(name: string, args: StatefulSetArgs, opts?: ComponentResourceOptions) {
|
|
252
261
|
const { labels, podTemplate, networkPolicy, containers, service, routes } =
|
|
253
|
-
|
|
262
|
+
getWorkloadServiceComponents(
|
|
254
263
|
name,
|
|
255
264
|
{
|
|
256
265
|
...args,
|
|
@@ -275,7 +284,7 @@ class CreatedStatefulSet extends StatefulSet {
|
|
|
275
284
|
template: podTemplate,
|
|
276
285
|
selector: { matchLabels: labels },
|
|
277
286
|
},
|
|
278
|
-
omit(args,
|
|
287
|
+
omit(args, workloadServiceExtraArgs),
|
|
279
288
|
) as types.input.apps.v1.StatefulSetSpec
|
|
280
289
|
},
|
|
281
290
|
),
|
|
@@ -312,7 +321,7 @@ class CreatedStatefulSet extends StatefulSet {
|
|
|
312
321
|
class StatefulSetPatch extends StatefulSet {
|
|
313
322
|
constructor(name: string, args: StatefulSetArgs, opts?: ComponentResourceOptions) {
|
|
314
323
|
const { podTemplate, networkPolicy, containers, service, routes } =
|
|
315
|
-
|
|
324
|
+
getWorkloadServiceComponents(name, args, () => this, opts, true)
|
|
316
325
|
|
|
317
326
|
const statefulSet = output(args.namespace).cluster.apply(cluster => {
|
|
318
327
|
return new apps.v1.StatefulSetPatch(
|
|
@@ -320,10 +329,16 @@ class StatefulSetPatch extends StatefulSet {
|
|
|
320
329
|
{
|
|
321
330
|
metadata: mapMetadata(args, name),
|
|
322
331
|
spec: output({ args, podTemplate }).apply(({ args, podTemplate }) => {
|
|
323
|
-
|
|
332
|
+
const spec = deepmerge(
|
|
324
333
|
{ template: podTemplate },
|
|
325
|
-
omit(args,
|
|
326
|
-
) as types.input.apps.v1.StatefulSetSpec
|
|
334
|
+
omit(args, workloadServiceExtraArgs),
|
|
335
|
+
) as Unwrap<types.input.apps.v1.StatefulSetSpec>
|
|
336
|
+
|
|
337
|
+
if (spec.template) {
|
|
338
|
+
spec.template = filterPatchOwnedContainersInTemplate(spec.template, podTemplate)
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
return spec
|
|
327
342
|
}),
|
|
328
343
|
},
|
|
329
344
|
{
|
package/src/tls.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import type { k8s } from "@highstate/library"
|
|
2
1
|
import type { types } from "@pulumi/kubernetes"
|
|
3
2
|
import { cert_manager, type types as cmTypes } from "@highstate/cert-manager"
|
|
4
3
|
import { getOrCreate } from "@highstate/contract"
|
|
4
|
+
import { k8s } from "@highstate/library"
|
|
5
5
|
import {
|
|
6
6
|
type ComponentResourceOptions,
|
|
7
7
|
type Input,
|
|
8
8
|
type Inputs,
|
|
9
9
|
interpolate,
|
|
10
|
+
makeEntityOutput,
|
|
10
11
|
type Output,
|
|
11
12
|
output,
|
|
12
13
|
toPromise,
|
|
@@ -31,6 +32,22 @@ export type CreateOrGetCertificateArgs = CertificateArgs & {
|
|
|
31
32
|
existing: Input<k8s.Certificate> | undefined
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
const certManagerCertificateWaitFor = "condition=Ready"
|
|
36
|
+
|
|
37
|
+
function mapCertificateMetadata(
|
|
38
|
+
args: CertificateArgs,
|
|
39
|
+
fallbackName: string,
|
|
40
|
+
): Output<types.input.meta.v1.ObjectMeta> {
|
|
41
|
+
return mapMetadata(args, fallbackName).apply(metadata => ({
|
|
42
|
+
...metadata,
|
|
43
|
+
annotations: {
|
|
44
|
+
...metadata.annotations,
|
|
45
|
+
"pulumi.com/waitFor":
|
|
46
|
+
metadata.annotations?.["pulumi.com/waitFor"] ?? certManagerCertificateWaitFor,
|
|
47
|
+
},
|
|
48
|
+
}))
|
|
49
|
+
}
|
|
50
|
+
|
|
34
51
|
/**
|
|
35
52
|
* Represents a cert-manager Certificate resource with metadata and secret.
|
|
36
53
|
*/
|
|
@@ -65,8 +82,17 @@ export abstract class Certificate extends NamespacedResource {
|
|
|
65
82
|
/**
|
|
66
83
|
* The Highstate certificate entity.
|
|
67
84
|
*/
|
|
68
|
-
get entity(): Output<k8s.
|
|
69
|
-
return
|
|
85
|
+
get entity(): Output<k8s.Certificate> {
|
|
86
|
+
return makeEntityOutput({
|
|
87
|
+
entity: k8s.certificateEntity,
|
|
88
|
+
identity: this.metadata.uid,
|
|
89
|
+
meta: {
|
|
90
|
+
title: this.metadata.name,
|
|
91
|
+
},
|
|
92
|
+
value: {
|
|
93
|
+
...this.entityBase,
|
|
94
|
+
},
|
|
95
|
+
})
|
|
70
96
|
}
|
|
71
97
|
|
|
72
98
|
/**
|
|
@@ -228,7 +254,7 @@ class CreatedCertificate extends Certificate {
|
|
|
228
254
|
return new cert_manager.v1.Certificate(
|
|
229
255
|
name,
|
|
230
256
|
{
|
|
231
|
-
metadata:
|
|
257
|
+
metadata: mapCertificateMetadata(args, name),
|
|
232
258
|
spec: omit(args, commonExtraArgs),
|
|
233
259
|
},
|
|
234
260
|
{ ...opts, parent: this, provider: getProvider(cluster) },
|
|
@@ -255,7 +281,7 @@ class CertificatePatch extends Certificate {
|
|
|
255
281
|
return new cert_manager.v1.CertificatePatch(
|
|
256
282
|
name,
|
|
257
283
|
{
|
|
258
|
-
metadata:
|
|
284
|
+
metadata: mapCertificateMetadata(args, name),
|
|
259
285
|
spec: omit(args, commonExtraArgs),
|
|
260
286
|
},
|
|
261
287
|
{ ...opts, parent: this, provider: getProvider(cluster) },
|
|
@@ -5,18 +5,18 @@ import { forUnit, toPromise } from "@highstate/pulumi"
|
|
|
5
5
|
const { args, inputs, outputs } = forUnit(k8s.clusterPatch)
|
|
6
6
|
|
|
7
7
|
const cluster = await toPromise(inputs.k8sCluster)
|
|
8
|
-
const endpoints =
|
|
9
|
-
const apiEndpoints =
|
|
8
|
+
const endpoints = parseEndpoints([...args.endpoints, ...inputs.endpoints], 3)
|
|
9
|
+
const apiEndpoints = parseEndpoints([...args.apiEndpoints, ...inputs.apiEndpoints], 4)
|
|
10
10
|
|
|
11
11
|
const newEndpoints = endpoints.length > 0 ? endpoints : cluster.endpoints
|
|
12
12
|
const newApiEndpoints = apiEndpoints.length > 0 ? apiEndpoints : cluster.apiEndpoints
|
|
13
13
|
|
|
14
14
|
export default outputs({
|
|
15
|
-
k8sCluster:
|
|
16
|
-
...k8sCluster,
|
|
15
|
+
k8sCluster: {
|
|
16
|
+
...inputs.k8sCluster,
|
|
17
17
|
endpoints: newEndpoints,
|
|
18
18
|
apiEndpoints: newApiEndpoints,
|
|
19
|
-
}
|
|
19
|
+
},
|
|
20
20
|
|
|
21
21
|
$statusFields: {
|
|
22
22
|
endpoints: endpoints.map(l3EndpointToString),
|