@highstate/k8s 0.7.0 → 0.7.1
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/{helm-BV9UE-B8.js → helm-wPTgVV1N.js} +179 -48
- package/dist/index.d.ts +339 -74
- package/dist/index.js +531 -198
- package/dist/shared-Clzbl5K-.js +89 -0
- package/dist/units/cert-manager/index.js +6 -5
- package/dist/units/dns01-issuer/index.js +3 -3
- package/dist/units/existing-cluster/index.js +21 -5
- package/package.json +8 -7
- package/dist/shared-r5jBysdR.js +0 -51
package/dist/index.js
CHANGED
@@ -1,14 +1,16 @@
|
|
1
|
-
import { m as mapMetadata, c as commonExtraArgs, a as mapSelectorLikeToSelector, b as mapNamespaceNameToSelector, d as mapNamespaceLikeToNamespaceName } from './shared-
|
2
|
-
export {
|
3
|
-
import {
|
1
|
+
import { m as mapMetadata, c as commonExtraArgs, v as verifyProvider, r as resourceIdToString, a as mapSelectorLikeToSelector, b as mapNamespaceNameToSelector, d as mapNamespaceLikeToNamespaceName, g as getAppDisplayName, e as getAppName } from './shared-Clzbl5K-.js';
|
2
|
+
export { h as createNamespace, f as createProvider, i as getNamespace } from './shared-Clzbl5K-.js';
|
3
|
+
import { ComponentResource, output, normalize, toPromise, apply } from '@highstate/pulumi';
|
4
4
|
import { core, apps, networking, batch } from '@pulumi/kubernetes';
|
5
|
-
import { concat, map,
|
6
|
-
import {
|
7
|
-
|
5
|
+
import { omit, concat, map, uniqueBy, capitalize, mergeDeep, flat, merge, pipe } from 'remeda';
|
6
|
+
import { deepmerge } from 'deepmerge-ts';
|
7
|
+
import { output as output$1, ComponentResource as ComponentResource$1 } from '@pulumi/pulumi';
|
8
|
+
import { S as Service, m as mapContainerPortToServicePort, H as HttpRoute, a as mapServiceToLabelSelector } from './helm-wPTgVV1N.js';
|
9
|
+
export { C as Chart, R as RenderedChart, b as getChartService, g as getChartServiceOutput, r as resolveHelmChart } from './helm-wPTgVV1N.js';
|
10
|
+
import { parseDomain, ParseResultType } from 'parse-domain';
|
11
|
+
import '@highstate/library';
|
8
12
|
import { DnsRecord } from '@highstate/common';
|
9
13
|
import { gateway } from '@highstate/gateway-api';
|
10
|
-
import { ComponentResource as ComponentResource$1, output as output$1 } from '@pulumi/pulumi';
|
11
|
-
import { deepmerge } from 'deepmerge-ts';
|
12
14
|
import { trimIndentation, text } from '@highstate/contract';
|
13
15
|
import 'path';
|
14
16
|
import 'node:fs/promises';
|
@@ -17,6 +19,95 @@ import 'crypto-hash';
|
|
17
19
|
import '@pulumi/command';
|
18
20
|
import 'glob';
|
19
21
|
|
22
|
+
const extraPersistentVolumeClaimArgs = [...commonExtraArgs, "size", "cluster"];
|
23
|
+
class PersistentVolumeClaim extends ComponentResource {
|
24
|
+
constructor(type, name, args, opts, clusterInfo, metadata, spec, status) {
|
25
|
+
super(type, name, args, opts);
|
26
|
+
this.clusterInfo = clusterInfo;
|
27
|
+
this.metadata = metadata;
|
28
|
+
this.spec = spec;
|
29
|
+
this.status = status;
|
30
|
+
}
|
31
|
+
/**
|
32
|
+
* The Highstate service entity.
|
33
|
+
*/
|
34
|
+
get entity() {
|
35
|
+
return output({
|
36
|
+
type: "k8s.persistent-volume-claim",
|
37
|
+
clusterInfo: this.clusterInfo,
|
38
|
+
metadata: this.metadata
|
39
|
+
});
|
40
|
+
}
|
41
|
+
static create(name, args, opts) {
|
42
|
+
return new CreatedPersistentVolumeClaim(name, args, opts);
|
43
|
+
}
|
44
|
+
static of(name, entity, opts) {
|
45
|
+
return new ExternalPersistentVolumeClaim(
|
46
|
+
name,
|
47
|
+
output(entity).metadata,
|
48
|
+
output(entity).clusterInfo,
|
49
|
+
opts
|
50
|
+
);
|
51
|
+
}
|
52
|
+
}
|
53
|
+
class CreatedPersistentVolumeClaim extends PersistentVolumeClaim {
|
54
|
+
constructor(name, args, opts) {
|
55
|
+
const pvc = output(args).apply((args2) => {
|
56
|
+
return new core.v1.PersistentVolumeClaim(
|
57
|
+
name,
|
58
|
+
{
|
59
|
+
metadata: mapMetadata(args2, name),
|
60
|
+
spec: deepmerge(
|
61
|
+
{
|
62
|
+
accessModes: ["ReadWriteOnce"],
|
63
|
+
resources: {
|
64
|
+
requests: {
|
65
|
+
storage: args2.size ?? "100Mi"
|
66
|
+
}
|
67
|
+
}
|
68
|
+
},
|
69
|
+
omit(args2, extraPersistentVolumeClaimArgs)
|
70
|
+
)
|
71
|
+
},
|
72
|
+
opts
|
73
|
+
);
|
74
|
+
});
|
75
|
+
super(
|
76
|
+
"k8s:PersistentVolumeClaim",
|
77
|
+
name,
|
78
|
+
args,
|
79
|
+
opts,
|
80
|
+
output(args.cluster).info,
|
81
|
+
pvc.metadata,
|
82
|
+
pvc.spec,
|
83
|
+
pvc.status
|
84
|
+
);
|
85
|
+
}
|
86
|
+
}
|
87
|
+
class ExternalPersistentVolumeClaim extends PersistentVolumeClaim {
|
88
|
+
constructor(name, id, clusterInfo, opts) {
|
89
|
+
const pvc = output(id).apply(async (id2) => {
|
90
|
+
await verifyProvider(opts.provider, this.clusterInfo);
|
91
|
+
return core.v1.PersistentVolumeClaim.get(
|
92
|
+
//
|
93
|
+
name,
|
94
|
+
resourceIdToString(id2),
|
95
|
+
{ parent: this, provider: opts.provider }
|
96
|
+
);
|
97
|
+
});
|
98
|
+
super(
|
99
|
+
"highstate:k8s:ExternalPersistentVolumeClaim",
|
100
|
+
name,
|
101
|
+
{ id, clusterInfo },
|
102
|
+
opts,
|
103
|
+
output(clusterInfo),
|
104
|
+
pvc.metadata,
|
105
|
+
pvc.spec,
|
106
|
+
pvc.status
|
107
|
+
);
|
108
|
+
}
|
109
|
+
}
|
110
|
+
|
20
111
|
const containerExtraArgs = [
|
21
112
|
"port",
|
22
113
|
"volumeMount",
|
@@ -25,10 +116,11 @@ const containerExtraArgs = [
|
|
25
116
|
"environmentSource",
|
26
117
|
"environmentSources"
|
27
118
|
];
|
28
|
-
function mapContainerToRaw(
|
119
|
+
function mapContainerToRaw(container, fallbackName) {
|
120
|
+
const containerName = container.name ?? fallbackName;
|
29
121
|
return {
|
30
122
|
...omit(container, containerExtraArgs),
|
31
|
-
name:
|
123
|
+
name: containerName,
|
32
124
|
ports: normalize(container.port, container.ports),
|
33
125
|
volumeMounts: map(normalize(container.volumeMount, container.volumeMounts), mapVolumeMount),
|
34
126
|
env: concat(
|
@@ -92,7 +184,10 @@ function mapVolumeMount(volumeMount) {
|
|
92
184
|
["volume"]
|
93
185
|
);
|
94
186
|
}
|
95
|
-
return
|
187
|
+
return {
|
188
|
+
...volumeMount,
|
189
|
+
name: volumeMount.name
|
190
|
+
};
|
96
191
|
}
|
97
192
|
function mapEnvironmentSource(envFrom) {
|
98
193
|
if (envFrom instanceof core.v1.ConfigMap) {
|
@@ -112,6 +207,14 @@ function mapEnvironmentSource(envFrom) {
|
|
112
207
|
return envFrom;
|
113
208
|
}
|
114
209
|
function mapWorkloadVolume(volume) {
|
210
|
+
if (volume instanceof PersistentVolumeClaim) {
|
211
|
+
return {
|
212
|
+
name: volume.metadata.name,
|
213
|
+
persistentVolumeClaim: {
|
214
|
+
claimName: volume.metadata.name
|
215
|
+
}
|
216
|
+
};
|
217
|
+
}
|
115
218
|
if (volume instanceof core.v1.PersistentVolumeClaim) {
|
116
219
|
return {
|
117
220
|
name: volume.metadata.name,
|
@@ -139,177 +242,272 @@ function mapWorkloadVolume(volume) {
|
|
139
242
|
return volume;
|
140
243
|
}
|
141
244
|
|
142
|
-
const
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
245
|
+
const workloadExtraArgs = [...commonExtraArgs, "container", "containers"];
|
246
|
+
const publicWorkloadExtraArgs = [...workloadExtraArgs, "service", "httpRoute"];
|
247
|
+
function getWorkloadComponents(name, args) {
|
248
|
+
const labels = {
|
249
|
+
"app.kubernetes.io/name": name
|
250
|
+
};
|
251
|
+
const containers = output$1(args).apply((args2) => normalize(args2.container, args2.containers));
|
252
|
+
const volumes = containers.apply((containers2) => {
|
253
|
+
const containerVolumes = containers2.flatMap((container) => normalize(container.volume, container.volumes)).map(mapWorkloadVolume);
|
254
|
+
const containerVolumeMounts = containers2.flatMap((container) => {
|
255
|
+
return normalize(container.volumeMount, container.volumeMounts).map((volumeMount) => {
|
256
|
+
return "volume" in volumeMount ? volumeMount.volume : void 0;
|
257
|
+
}).filter(Boolean);
|
258
|
+
}).map(mapWorkloadVolume);
|
259
|
+
return uniqueBy([...containerVolumes, ...containerVolumeMounts], (volume) => volume.name);
|
260
|
+
});
|
261
|
+
return { labels, containers, volumes };
|
262
|
+
}
|
263
|
+
function getPublicWorkloadComponents(name, args, parent, opts) {
|
264
|
+
const { labels, containers, volumes } = getWorkloadComponents(name, args);
|
265
|
+
const service = output$1({ args, containers }).apply(({ args: args2, containers: containers2 }) => {
|
266
|
+
if (!args2.service && !args2.httpRoute) {
|
267
|
+
return void 0;
|
268
|
+
}
|
269
|
+
if (args2.patch?.service) {
|
270
|
+
return Service.of(name, args2.patch.service, { parent: parent(), ...opts });
|
271
|
+
}
|
272
|
+
if (args2.patch) {
|
273
|
+
return void 0;
|
274
|
+
}
|
275
|
+
const ports = containers2.flatMap((container) => normalize(container.port, container.ports));
|
276
|
+
return Service.create(
|
277
|
+
name,
|
278
|
+
{
|
279
|
+
...args2.service,
|
280
|
+
selector: labels,
|
281
|
+
cluster: args2.cluster,
|
282
|
+
namespace: args2.namespace,
|
283
|
+
ports: (
|
284
|
+
// allow to completely override the ports
|
285
|
+
!args2.service?.port && !args2.service?.ports ? ports.map(mapContainerPortToServicePort) : args2.service?.ports
|
286
|
+
)
|
287
|
+
},
|
288
|
+
{ parent: parent(), ...opts }
|
289
|
+
);
|
290
|
+
});
|
291
|
+
const httpRoute = output$1({
|
292
|
+
args,
|
293
|
+
service
|
294
|
+
}).apply(({ args: args2, service: service2 }) => {
|
295
|
+
if (!args2.httpRoute || !service2) {
|
296
|
+
return void 0;
|
297
|
+
}
|
298
|
+
if (args2.patch) {
|
299
|
+
return void 0;
|
300
|
+
}
|
301
|
+
return new HttpRoute(
|
302
|
+
name,
|
303
|
+
{
|
304
|
+
...args2.httpRoute,
|
305
|
+
rule: {
|
306
|
+
backend: service2
|
307
|
+
}
|
308
|
+
},
|
309
|
+
{ parent: parent(), ...opts }
|
310
|
+
);
|
311
|
+
});
|
312
|
+
return { labels, containers, volumes, service, httpRoute };
|
313
|
+
}
|
314
|
+
|
149
315
|
class Deployment extends ComponentResource {
|
316
|
+
constructor(type, name, args, opts, clusterInfo, metadata, spec, status, _service, _httpRoute, resources) {
|
317
|
+
super(type, name, args, opts);
|
318
|
+
this.clusterInfo = clusterInfo;
|
319
|
+
this.metadata = metadata;
|
320
|
+
this.spec = spec;
|
321
|
+
this.status = status;
|
322
|
+
this._service = _service;
|
323
|
+
this._httpRoute = _httpRoute;
|
324
|
+
this.resources = resources;
|
325
|
+
}
|
150
326
|
/**
|
151
|
-
* The
|
327
|
+
* The Highstate deployment entity.
|
152
328
|
*/
|
153
|
-
|
329
|
+
get entity() {
|
330
|
+
return output({
|
331
|
+
type: "k8s.deployment",
|
332
|
+
clusterInfo: this.clusterInfo,
|
333
|
+
metadata: this.metadata,
|
334
|
+
spec: this.spec,
|
335
|
+
service: this._service.apply((service) => service?.entity)
|
336
|
+
});
|
337
|
+
}
|
154
338
|
/**
|
155
339
|
* The service associated with the deployment.
|
156
340
|
*/
|
157
|
-
service
|
341
|
+
get service() {
|
342
|
+
return this._service.apply((service) => {
|
343
|
+
if (!service) {
|
344
|
+
throw new Error("The service is not available.");
|
345
|
+
}
|
346
|
+
return service;
|
347
|
+
});
|
348
|
+
}
|
158
349
|
/**
|
159
350
|
* The HTTP route associated with the deployment.
|
160
351
|
*/
|
161
|
-
httpRoute
|
352
|
+
get httpRoute() {
|
353
|
+
return this._httpRoute.apply((httpRoute) => {
|
354
|
+
if (!httpRoute) {
|
355
|
+
throw new Error("The HTTP route is not available.");
|
356
|
+
}
|
357
|
+
return httpRoute;
|
358
|
+
});
|
359
|
+
}
|
360
|
+
static create(name, args, opts) {
|
361
|
+
return new CreatedDeployment(name, args, opts);
|
362
|
+
}
|
363
|
+
}
|
364
|
+
class CreatedDeployment extends Deployment {
|
162
365
|
constructor(name, args, opts) {
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
366
|
+
const { labels, containers, volumes, service, httpRoute } = getPublicWorkloadComponents(
|
367
|
+
name,
|
368
|
+
args,
|
369
|
+
() => this,
|
370
|
+
opts
|
371
|
+
);
|
372
|
+
const deployment = output({ args, containers, volumes }).apply(
|
373
|
+
async ({ args: args2, containers: containers2, volumes: volumes2 }) => {
|
374
|
+
await verifyProvider(opts.provider, args2.cluster.info);
|
375
|
+
return new (args2.patch ? apps.v1.DeploymentPatch : apps.v1.Deployment)(
|
376
|
+
name,
|
377
|
+
{
|
378
|
+
metadata: mapMetadata(args2.patch?.metadata ?? args2, name),
|
379
|
+
spec: deepmerge(
|
380
|
+
{
|
381
|
+
template: {
|
382
|
+
metadata: {
|
383
|
+
labels
|
384
|
+
},
|
385
|
+
spec: {
|
386
|
+
containers: containers2.map((container) => mapContainerToRaw(container, name)),
|
387
|
+
volumes: volumes2
|
388
|
+
}
|
178
389
|
},
|
179
|
-
|
180
|
-
|
181
|
-
volumes: containers.flatMap((container) => normalize(container.volume, container.volumes)).map(mapWorkloadVolume)
|
390
|
+
selector: {
|
391
|
+
matchLabels: labels
|
182
392
|
}
|
183
393
|
},
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
)
|
190
|
-
},
|
191
|
-
{
|
192
|
-
...opts,
|
193
|
-
parent: this
|
194
|
-
}
|
195
|
-
);
|
196
|
-
});
|
197
|
-
this.service = output({
|
198
|
-
args: args.service,
|
199
|
-
httpRouteArgs: args.httpRoute,
|
200
|
-
namespace: this.deployment.metadata.namespace,
|
201
|
-
containers: this.deployment.spec.template.spec.containers
|
202
|
-
}).apply(({ args: args2, httpRouteArgs, namespace, containers }) => {
|
203
|
-
if (!args2 && !httpRouteArgs) {
|
204
|
-
return void 0;
|
205
|
-
}
|
206
|
-
const ports = containers.flatMap((container) => container.ports ?? []);
|
207
|
-
return new Service(
|
208
|
-
args2?.name ?? name,
|
209
|
-
{
|
210
|
-
...args2,
|
211
|
-
namespace,
|
212
|
-
ports: (
|
213
|
-
// allow to completely override the ports
|
214
|
-
!args2?.port && !args2?.ports ? ports.map(mapContainerPortToServicePort) : args2?.ports
|
215
|
-
),
|
216
|
-
selector: labels
|
217
|
-
},
|
218
|
-
{
|
219
|
-
...opts,
|
220
|
-
parent: this
|
221
|
-
}
|
222
|
-
);
|
223
|
-
});
|
224
|
-
this.httpRoute = output({
|
225
|
-
args: args.httpRoute,
|
226
|
-
service: this.service
|
227
|
-
}).apply(({ args: args2, service }) => {
|
228
|
-
if (!args2 || !service) {
|
229
|
-
return void 0;
|
230
|
-
}
|
231
|
-
return new HttpRoute(
|
232
|
-
name,
|
233
|
-
{
|
234
|
-
...args2,
|
235
|
-
rule: {
|
236
|
-
backend: service.service
|
237
|
-
}
|
238
|
-
},
|
239
|
-
{ ...opts, parent: this }
|
240
|
-
);
|
241
|
-
});
|
242
|
-
this.registerOutputs({
|
243
|
-
deployment: this.deployment,
|
244
|
-
service: this.service
|
245
|
-
});
|
246
|
-
}
|
247
|
-
getRequiredService() {
|
248
|
-
return this.service.apply((service) => {
|
249
|
-
if (!service) {
|
250
|
-
throw new Error("The service is not available for this deployment.");
|
394
|
+
omit(args2, publicWorkloadExtraArgs)
|
395
|
+
)
|
396
|
+
},
|
397
|
+
{ parent: this, ...opts }
|
398
|
+
);
|
251
399
|
}
|
252
|
-
|
253
|
-
|
400
|
+
);
|
401
|
+
super(
|
402
|
+
"highstate:k8s:Deployment",
|
403
|
+
name,
|
404
|
+
args,
|
405
|
+
opts,
|
406
|
+
output(args.cluster).info,
|
407
|
+
deployment.metadata,
|
408
|
+
deployment.spec,
|
409
|
+
deployment.status,
|
410
|
+
service,
|
411
|
+
httpRoute,
|
412
|
+
[deployment]
|
413
|
+
);
|
254
414
|
}
|
255
415
|
}
|
256
416
|
|
257
|
-
function mapPersistentVolumeClaimToRaw(args) {
|
258
|
-
return {
|
259
|
-
metadata: mapMetadata(args),
|
260
|
-
spec: args
|
261
|
-
};
|
262
|
-
}
|
263
|
-
|
264
417
|
class StatefulSet extends ComponentResource {
|
418
|
+
constructor(type, name, args, opts, clusterInfo, metadata, spec, status, _service, _httpRoute) {
|
419
|
+
super(type, name, args, opts);
|
420
|
+
this.clusterInfo = clusterInfo;
|
421
|
+
this.metadata = metadata;
|
422
|
+
this.spec = spec;
|
423
|
+
this.status = status;
|
424
|
+
this._service = _service;
|
425
|
+
this._httpRoute = _httpRoute;
|
426
|
+
}
|
265
427
|
/**
|
266
|
-
* The
|
428
|
+
* The Highstate stateful set entity.
|
267
429
|
*/
|
268
|
-
|
430
|
+
get entity() {
|
431
|
+
return output({
|
432
|
+
type: "k8s.stateful-set",
|
433
|
+
clusterInfo: this.clusterInfo,
|
434
|
+
metadata: this.metadata,
|
435
|
+
service: this.service.entity
|
436
|
+
});
|
437
|
+
}
|
269
438
|
/**
|
270
439
|
* The service associated with the stateful set.
|
271
440
|
*/
|
272
|
-
service
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
this.service = output(args.service).apply((service) => {
|
279
|
-
return new Service(
|
280
|
-
service?.name ?? name,
|
281
|
-
{
|
282
|
-
...service,
|
283
|
-
clusterIP: "None"
|
284
|
-
},
|
285
|
-
{ ...opts, parent: this }
|
286
|
-
);
|
287
|
-
});
|
288
|
-
this.statefulSet = output(args).apply((args2) => {
|
289
|
-
return new apps.v1.StatefulSet(name, {
|
290
|
-
metadata: mapMetadata(args2),
|
291
|
-
spec: mergeDeep(args2, {
|
292
|
-
serviceName: this.service.service.metadata.name,
|
293
|
-
template: {
|
294
|
-
metadata: {
|
295
|
-
labels
|
296
|
-
},
|
297
|
-
spec: {
|
298
|
-
containers: normalize(args2.container, args2.containers).map((container) => mapContainerToRaw(name, container))
|
299
|
-
}
|
300
|
-
},
|
301
|
-
selector: {
|
302
|
-
matchLabels: labels
|
303
|
-
},
|
304
|
-
volumeClaimTemplates: normalize(args2.volumeClaim, args2.volumeClaims).map(mapPersistentVolumeClaimToRaw)
|
305
|
-
})
|
306
|
-
});
|
441
|
+
get service() {
|
442
|
+
return this._service.apply((service) => {
|
443
|
+
if (!service) {
|
444
|
+
throw new Error("The service is not available.");
|
445
|
+
}
|
446
|
+
return service;
|
307
447
|
});
|
308
|
-
|
309
|
-
|
310
|
-
|
448
|
+
}
|
449
|
+
/**
|
450
|
+
* The HTTP route associated with the stateful set.
|
451
|
+
*/
|
452
|
+
get httpRoute() {
|
453
|
+
return this._httpRoute.apply((httpRoute) => {
|
454
|
+
if (!httpRoute) {
|
455
|
+
throw new Error("The HTTP route is not available.");
|
456
|
+
}
|
457
|
+
return httpRoute;
|
311
458
|
});
|
312
459
|
}
|
460
|
+
static create(name, args, opts) {
|
461
|
+
return new CreatedStatefulSet(name, args, opts);
|
462
|
+
}
|
463
|
+
}
|
464
|
+
class CreatedStatefulSet extends StatefulSet {
|
465
|
+
constructor(name, args, opts) {
|
466
|
+
const { containers, volumes, labels, service, httpRoute } = getPublicWorkloadComponents(
|
467
|
+
name,
|
468
|
+
args,
|
469
|
+
() => this,
|
470
|
+
opts
|
471
|
+
);
|
472
|
+
const statefulSet = output({ args, containers, volumes, service }).apply(
|
473
|
+
async ({ args: args2, containers: containers2, volumes: volumes2, service: service2 }) => {
|
474
|
+
await verifyProvider(opts.provider, args2.cluster?.info);
|
475
|
+
return new (args2.patch ? apps.v1.StatefulSetPatch : apps.v1.StatefulSet)(
|
476
|
+
name,
|
477
|
+
{
|
478
|
+
metadata: mapMetadata(args2.patch?.metadata ?? args2, name),
|
479
|
+
spec: deepmerge(
|
480
|
+
{
|
481
|
+
serviceName: service2?.metadata.name || name,
|
482
|
+
template: {
|
483
|
+
metadata: !args2.patch ? { labels } : void 0,
|
484
|
+
spec: {
|
485
|
+
containers: containers2.map((container) => mapContainerToRaw(container, name)),
|
486
|
+
volumes: volumes2
|
487
|
+
}
|
488
|
+
},
|
489
|
+
selector: !args2.patch ? { matchLabels: labels } : void 0
|
490
|
+
},
|
491
|
+
omit(args2, publicWorkloadExtraArgs)
|
492
|
+
)
|
493
|
+
},
|
494
|
+
{ parent: this, ...opts }
|
495
|
+
);
|
496
|
+
}
|
497
|
+
);
|
498
|
+
super(
|
499
|
+
"highstate:k8s:StatefulSet",
|
500
|
+
name,
|
501
|
+
args,
|
502
|
+
opts,
|
503
|
+
output(args.cluster).info,
|
504
|
+
statefulSet.metadata,
|
505
|
+
statefulSet.spec,
|
506
|
+
statefulSet.status,
|
507
|
+
service,
|
508
|
+
httpRoute
|
509
|
+
);
|
510
|
+
}
|
313
511
|
}
|
314
512
|
|
315
513
|
class NetworkPolicy extends ComponentResource {
|
@@ -322,11 +520,28 @@ class NetworkPolicy extends ComponentResource {
|
|
322
520
|
const normalizedArgs = output(args).apply((args2) => {
|
323
521
|
const ingressRules = normalize(args2.ingressRule, args2.ingressRules);
|
324
522
|
const egressRules = normalize(args2.egressRule, args2.egressRules);
|
523
|
+
const endpoints = normalize(args2.egressRule?.toEndpoint, args2.egressRule?.toEndpoints);
|
524
|
+
const parsedEndpoints = endpoints.map((endpoint) => parseDomain(endpoint));
|
525
|
+
const cidrsFromEndpoints = parsedEndpoints.filter((result) => result.type === ParseResultType.Ip).map((result) => NetworkPolicy.mapCidrFromEndpoint(result));
|
526
|
+
const fqdnsFromEndpoints = parsedEndpoints.filter((result) => result.type !== ParseResultType.Invalid).map((result) => result.hostname);
|
527
|
+
const extraEgressRules = [];
|
528
|
+
if (args2.allowKubeDns) {
|
529
|
+
extraEgressRules.push({
|
530
|
+
namespaces: ["kube-system"],
|
531
|
+
selectors: [{ matchLabels: { "k8s-app": "kube-dns" } }],
|
532
|
+
ports: [{ port: 53, protocol: "UDP" }],
|
533
|
+
all: false,
|
534
|
+
cidrs: [],
|
535
|
+
fqdns: [],
|
536
|
+
services: []
|
537
|
+
});
|
538
|
+
}
|
325
539
|
return {
|
326
540
|
...args2,
|
327
541
|
podSelector: args2.selector ? mapSelectorLikeToSelector(args2.selector) : {},
|
328
542
|
isolateEgress: args2.isolateEgress ?? false,
|
329
543
|
isolateIngress: args2.isolateIngress ?? false,
|
544
|
+
allowKubeApiServer: args2.allowKubeApiServer ?? false,
|
330
545
|
ingressRules: ingressRules.map((rule) => ({
|
331
546
|
all: rule.fromAll ?? false,
|
332
547
|
cidrs: normalize(rule.fromCidr, rule.fromCidrs),
|
@@ -336,15 +551,17 @@ class NetworkPolicy extends ComponentResource {
|
|
336
551
|
selectors: normalize(rule.fromSelector, rule.fromSelectors),
|
337
552
|
ports: normalize(rule.toPort, rule.toPorts)
|
338
553
|
})),
|
339
|
-
egressRules: egressRules.map((rule) =>
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
554
|
+
egressRules: egressRules.map((rule) => {
|
555
|
+
return {
|
556
|
+
all: rule.toAll ?? false,
|
557
|
+
cidrs: normalize(rule.toCidr, rule.toCidrs).concat(cidrsFromEndpoints),
|
558
|
+
fqdns: normalize(rule.toFqdn, rule.toFqdns).concat(fqdnsFromEndpoints),
|
559
|
+
services: normalize(rule.toService, rule.toServices),
|
560
|
+
namespaces: normalize(rule.toNamespace, rule.toNamespaces),
|
561
|
+
selectors: normalize(rule.toSelector, rule.toSelectors),
|
562
|
+
ports: normalize(rule.toPort, rule.toPorts)
|
563
|
+
};
|
564
|
+
}).concat(extraEgressRules)
|
348
565
|
};
|
349
566
|
});
|
350
567
|
this.networkPolicy = normalizedArgs.apply((args2) => {
|
@@ -354,9 +571,16 @@ class NetworkPolicy extends ComponentResource {
|
|
354
571
|
});
|
355
572
|
this.registerOutputs({ networkPolicy: this.networkPolicy });
|
356
573
|
}
|
574
|
+
static mapCidrFromEndpoint(result) {
|
575
|
+
if (result.ipVersion === 4) {
|
576
|
+
return `${result.hostname}/32`;
|
577
|
+
}
|
578
|
+
return `${result.hostname}/128`;
|
579
|
+
}
|
580
|
+
static supportedCNIs = ["cilium"];
|
357
581
|
static create(name, args, opts) {
|
358
582
|
return output(args).apply(async (args2) => {
|
359
|
-
if (!args2.cni || args2.cni
|
583
|
+
if (!args2.cni || !NetworkPolicy.supportedCNIs.includes(args2.cni)) {
|
360
584
|
return new NativeNetworkPolicy(name, args2, opts);
|
361
585
|
}
|
362
586
|
const implName = `${capitalize(args2.cni)}NetworkPolicy`;
|
@@ -368,6 +592,56 @@ class NetworkPolicy extends ComponentResource {
|
|
368
592
|
return new implClass(name, args2, opts);
|
369
593
|
});
|
370
594
|
}
|
595
|
+
static allowInsideNamespace(namespace, k8sCluster, opts) {
|
596
|
+
return NetworkPolicy.create(
|
597
|
+
"allow-inside-namespace",
|
598
|
+
{
|
599
|
+
namespace,
|
600
|
+
cni: output(k8sCluster).info.cni,
|
601
|
+
description: "Allow all traffic inside the namespace.",
|
602
|
+
selector: {},
|
603
|
+
ingressRule: { fromNamespace: namespace },
|
604
|
+
egressRule: { toNamespace: namespace }
|
605
|
+
},
|
606
|
+
opts
|
607
|
+
);
|
608
|
+
}
|
609
|
+
static allowKubeApiServer(namespace, k8sCluster, opts) {
|
610
|
+
return NetworkPolicy.create(
|
611
|
+
"allow-kube-api-server",
|
612
|
+
{
|
613
|
+
namespace,
|
614
|
+
cni: output(k8sCluster).info.cni,
|
615
|
+
description: "Allow all traffic to the Kubernetes API server from the namespace.",
|
616
|
+
allowKubeApiServer: true
|
617
|
+
},
|
618
|
+
opts
|
619
|
+
);
|
620
|
+
}
|
621
|
+
static allowKubeDns(namespace, k8sCluster, opts) {
|
622
|
+
return NetworkPolicy.create(
|
623
|
+
"allow-kube-dns",
|
624
|
+
{
|
625
|
+
namespace,
|
626
|
+
cni: output(k8sCluster).info.cni,
|
627
|
+
description: "Allow all traffic to the Kubernetes DNS server from the namespace.",
|
628
|
+
allowKubeDns: true
|
629
|
+
},
|
630
|
+
opts
|
631
|
+
);
|
632
|
+
}
|
633
|
+
static allowAllEgress(namespace, k8sCluster, opts) {
|
634
|
+
return NetworkPolicy.create(
|
635
|
+
"allow-all-egress",
|
636
|
+
{
|
637
|
+
namespace,
|
638
|
+
cni: output(k8sCluster).info.cni,
|
639
|
+
description: "Allow all egress traffic from the namespace.",
|
640
|
+
egressRule: { toAll: true }
|
641
|
+
},
|
642
|
+
opts
|
643
|
+
);
|
644
|
+
}
|
371
645
|
}
|
372
646
|
class NativeNetworkPolicy extends NetworkPolicy {
|
373
647
|
create(name, args, opts) {
|
@@ -411,10 +685,16 @@ class NativeNetworkPolicy extends NetworkPolicy {
|
|
411
685
|
if (needFallback) {
|
412
686
|
return [{ to: [{ ipBlock: NativeNetworkPolicy.fallbackIpBlock }] }];
|
413
687
|
}
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
}
|
688
|
+
const extraRules = [];
|
689
|
+
if (args.allowKubeApiServer) {
|
690
|
+
extraRules.push({ to: [{ ipBlock: { cidr: "10.96.0.1" } }] });
|
691
|
+
}
|
692
|
+
return args.egressRules.map((rule) => {
|
693
|
+
return {
|
694
|
+
to: rule.all ? void 0 : NativeNetworkPolicy.createRulePeers(rule),
|
695
|
+
ports: NativeNetworkPolicy.mapPorts(rule.ports)
|
696
|
+
};
|
697
|
+
}).concat(extraRules);
|
418
698
|
}
|
419
699
|
static createRulePeers(args) {
|
420
700
|
return [
|
@@ -475,28 +755,80 @@ class NativeNetworkPolicy extends NetworkPolicy {
|
|
475
755
|
}
|
476
756
|
|
477
757
|
function useAccessPoint(args) {
|
478
|
-
const result = output(args).apply(
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
758
|
+
const result = output({ args, namespaceName: output(args.namespace).metadata.name }).apply(
|
759
|
+
({ args: args2, namespaceName }) => {
|
760
|
+
const gateway2 = createGateway({
|
761
|
+
...args2,
|
762
|
+
annotations: {
|
763
|
+
"cert-manager.io/cluster-issuer": args2.accessPoint.tlsIssuer.clusterIssuerName
|
764
|
+
},
|
765
|
+
gateway: args2.accessPoint.gateway
|
766
|
+
});
|
767
|
+
const dnsRecords = normalize(args2.fqdn, args2.fqdns).map((fqdn) => {
|
768
|
+
return DnsRecord.create(fqdn, {
|
769
|
+
provider: args2.accessPoint.dnsProvider,
|
770
|
+
type: "A",
|
771
|
+
value: args2.accessPoint.gateway.ip
|
772
|
+
});
|
773
|
+
});
|
774
|
+
const networkPolicies = [];
|
775
|
+
if (args2.accessPoint.gateway.service) {
|
776
|
+
const displayName = getAppDisplayName(args2.accessPoint.gateway.service.metadata);
|
777
|
+
networkPolicies.push(
|
778
|
+
NetworkPolicy.create(
|
779
|
+
`allow-ingress-from-${getAppName(args2.accessPoint.gateway.service.metadata)}`,
|
780
|
+
{
|
781
|
+
cni: args2.accessPoint.gateway.service.clusterInfo.cni,
|
782
|
+
namespace: args2.namespace,
|
783
|
+
description: `Allow ingress traffic from the gateway "${displayName}".`,
|
784
|
+
ingressRule: {
|
785
|
+
fromNamespace: args2.accessPoint.gateway.service.metadata.namespace,
|
786
|
+
fromSelector: args2.accessPoint.gateway.service.spec.selector
|
787
|
+
}
|
788
|
+
},
|
789
|
+
{ provider: args2.provider }
|
790
|
+
),
|
791
|
+
NetworkPolicy.create(
|
792
|
+
`allow-egress-to-${namespaceName}`,
|
793
|
+
{
|
794
|
+
cni: args2.accessPoint.gateway.service.clusterInfo.cni,
|
795
|
+
namespace: args2.accessPoint.gateway.service.metadata.namespace,
|
796
|
+
selector: args2.accessPoint.gateway.service.spec.selector,
|
797
|
+
description: `Allow egress traffic to the namespace "${namespaceName}".`,
|
798
|
+
egressRule: {
|
799
|
+
toNamespace: args2.namespace
|
800
|
+
}
|
801
|
+
},
|
802
|
+
{ provider: args2.provider }
|
803
|
+
)
|
804
|
+
);
|
805
|
+
}
|
806
|
+
return output({
|
807
|
+
gateway: gateway2,
|
808
|
+
dnsRecords,
|
809
|
+
networkPolicies
|
810
|
+
});
|
811
|
+
}
|
812
|
+
);
|
496
813
|
return toPromise(result);
|
497
814
|
}
|
815
|
+
function useStandardAcessPoint(appName, namespace, args, inputs, provider) {
|
816
|
+
return useAccessPoint({
|
817
|
+
name: appName,
|
818
|
+
namespace,
|
819
|
+
fqdn: args.fqdn,
|
820
|
+
accessPoint: inputs.accessPoint,
|
821
|
+
clusterInfo: inputs.k8sCluster.info,
|
822
|
+
provider
|
823
|
+
});
|
824
|
+
}
|
498
825
|
function createGateway(args) {
|
499
826
|
return output(args).apply((args2) => {
|
827
|
+
if (args2.clusterInfo.id !== args2.gateway.clusterInfo.id) {
|
828
|
+
throw new Error(
|
829
|
+
"The provided Kubernetes cluster is different from the one where the gateway controller is deployed."
|
830
|
+
);
|
831
|
+
}
|
500
832
|
return new gateway.v1.Gateway(
|
501
833
|
args2.name,
|
502
834
|
{
|
@@ -507,18 +839,19 @@ function createGateway(args) {
|
|
507
839
|
},
|
508
840
|
spec: {
|
509
841
|
gatewayClassName: output(args2.gateway).gatewayClassName,
|
510
|
-
listeners:
|
511
|
-
|
512
|
-
|
842
|
+
listeners: normalize(args2.fqdn, args2.fqdns).map((fqdn) => {
|
843
|
+
const normalizedName = fqdn.replace(/\*/g, "wildcard");
|
844
|
+
return {
|
845
|
+
name: `https-${normalizedName}`,
|
513
846
|
port: output(args2.gateway).httpsListenerPort,
|
514
847
|
protocol: "HTTPS",
|
515
|
-
hostname:
|
848
|
+
hostname: fqdn,
|
516
849
|
tls: {
|
517
850
|
mode: "Terminate",
|
518
|
-
certificateRefs: [{ name:
|
851
|
+
certificateRefs: [{ name: normalizedName }]
|
519
852
|
}
|
520
|
-
}
|
521
|
-
|
853
|
+
};
|
854
|
+
})
|
522
855
|
}
|
523
856
|
},
|
524
857
|
{ provider: args2.provider, deletedWith: args2.namespace }
|
@@ -748,7 +1081,7 @@ class Job extends ComponentResource {
|
|
748
1081
|
{
|
749
1082
|
template: {
|
750
1083
|
spec: {
|
751
|
-
containers: containers.map((container) => mapContainerToRaw(
|
1084
|
+
containers: containers.map((container) => mapContainerToRaw(container, name)),
|
752
1085
|
volumes: containers.flatMap((container) => normalize(container.volume, container.volumes)).map(mapWorkloadVolume),
|
753
1086
|
restartPolicy: "Never"
|
754
1087
|
}
|
@@ -784,7 +1117,7 @@ class CronJob extends ComponentResource {
|
|
784
1117
|
spec: {
|
785
1118
|
template: {
|
786
1119
|
spec: {
|
787
|
-
containers: containers.map((container) => mapContainerToRaw(
|
1120
|
+
containers: containers.map((container) => mapContainerToRaw(container, name)),
|
788
1121
|
volumes: containers.flatMap((container) => normalize(container.volume, container.volumes)).map(mapWorkloadVolume)
|
789
1122
|
}
|
790
1123
|
}
|
@@ -802,4 +1135,4 @@ class CronJob extends ComponentResource {
|
|
802
1135
|
}
|
803
1136
|
}
|
804
1137
|
|
805
|
-
export { CronJob, Deployment, HttpRoute, Job, NetworkPolicy, ScriptBundle, Service, StatefulSet, createScriptContainer, mapContainerPortToServicePort, mapMetadata, mapNamespaceLikeToNamespaceName, mapNamespaceNameToSelector, mapSelectorLikeToSelector, mapServiceToLabelSelector, useAccessPoint };
|
1138
|
+
export { CronJob, Deployment, HttpRoute, Job, NetworkPolicy, PersistentVolumeClaim, ScriptBundle, Service, StatefulSet, createScriptContainer, getAppDisplayName, getAppName, mapContainerPortToServicePort, mapMetadata, mapNamespaceLikeToNamespaceName, mapNamespaceNameToSelector, mapSelectorLikeToSelector, mapServiceToLabelSelector, useAccessPoint, useStandardAcessPoint };
|