@highstate/k8s 0.9.7 → 0.9.9
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-VJA6NM5Q.js → chunk-7R2VAXVL.js} +24 -4
- package/dist/chunk-7R2VAXVL.js.map +1 -0
- package/dist/{chunk-QOKAVPCM.js → chunk-L6G2IHDP.js} +29 -449
- package/dist/chunk-L6G2IHDP.js.map +1 -0
- package/dist/chunk-OP75IMU7.js +766 -0
- package/dist/chunk-OP75IMU7.js.map +1 -0
- package/dist/{chunk-LNNW53JJ.js → chunk-W72HEBHG.js} +2 -2
- package/dist/{chunk-SNSPQJ6A.js → chunk-WUJ7BFVE.js} +2 -2
- package/dist/deployment-A26RVQ73.js +10 -0
- package/dist/highstate.manifest.json +8 -8
- package/dist/index.js +6 -6
- package/dist/stateful-set-S5BHTDJY.js +10 -0
- package/dist/units/cert-manager/index.js +2 -2
- package/package.json +9 -9
- package/src/helm.ts +35 -2
- package/src/service.ts +3 -2
- package/dist/chunk-56QP4XW6.js +0 -347
- package/dist/chunk-56QP4XW6.js.map +0 -1
- package/dist/chunk-QOKAVPCM.js.map +0 -1
- package/dist/chunk-VJA6NM5Q.js.map +0 -1
- package/dist/deployment-NG62MEGK.js +0 -10
- package/dist/stateful-set-JXMHD6FH.js +0 -10
- /package/dist/{chunk-LNNW53JJ.js.map → chunk-W72HEBHG.js.map} +0 -0
- /package/dist/{chunk-SNSPQJ6A.js.map → chunk-WUJ7BFVE.js.map} +0 -0
- /package/dist/{deployment-NG62MEGK.js.map → deployment-A26RVQ73.js.map} +0 -0
- /package/dist/{stateful-set-JXMHD6FH.js.map → stateful-set-S5BHTDJY.js.map} +0 -0
@@ -0,0 +1,766 @@
|
|
1
|
+
import {
|
2
|
+
commonExtraArgs,
|
3
|
+
getProvider,
|
4
|
+
mapMetadata,
|
5
|
+
mapNamespaceLikeToNamespaceName,
|
6
|
+
mapNamespaceNameToSelector,
|
7
|
+
mapSelectorLikeToSelector,
|
8
|
+
resourceIdToString
|
9
|
+
} from "./chunk-HTQP2NB4.js";
|
10
|
+
|
11
|
+
// src/service.ts
|
12
|
+
import { core } from "@pulumi/kubernetes";
|
13
|
+
import {
|
14
|
+
ComponentResource,
|
15
|
+
normalize,
|
16
|
+
output
|
17
|
+
} from "@highstate/pulumi";
|
18
|
+
import { omit, uniqueBy } from "remeda";
|
19
|
+
import { deepmerge } from "deepmerge-ts";
|
20
|
+
import { filterEndpoints, l4EndpointToString, parseL3Endpoint } from "@highstate/common";
|
21
|
+
var serviceExtraArgs = [...commonExtraArgs, "port", "ports", "external"];
|
22
|
+
function hasServiceMetadata(endpoint) {
|
23
|
+
return endpoint.metadata?.k8sService !== void 0;
|
24
|
+
}
|
25
|
+
function getServiceMetadata(endpoint) {
|
26
|
+
return endpoint.metadata?.k8sService;
|
27
|
+
}
|
28
|
+
function withServiceMetadata(endpoint, metadata) {
|
29
|
+
return {
|
30
|
+
...endpoint,
|
31
|
+
metadata: {
|
32
|
+
...endpoint.metadata,
|
33
|
+
k8sService: metadata
|
34
|
+
}
|
35
|
+
};
|
36
|
+
}
|
37
|
+
function isFromCluster(endpoint, cluster) {
|
38
|
+
return getServiceMetadata(endpoint)?.clusterId === cluster.id;
|
39
|
+
}
|
40
|
+
var Service = class extends ComponentResource {
|
41
|
+
constructor(type, name, args, opts, cluster, metadata, spec, status) {
|
42
|
+
super(type, name, args, opts);
|
43
|
+
this.cluster = cluster;
|
44
|
+
this.metadata = metadata;
|
45
|
+
this.spec = spec;
|
46
|
+
this.status = status;
|
47
|
+
}
|
48
|
+
/**
|
49
|
+
* The Highstate service entity.
|
50
|
+
*/
|
51
|
+
get entity() {
|
52
|
+
return output({
|
53
|
+
type: "k8s.service",
|
54
|
+
clusterId: this.cluster.id,
|
55
|
+
metadata: this.metadata,
|
56
|
+
endpoints: this.endpoints
|
57
|
+
});
|
58
|
+
}
|
59
|
+
static create(name, args, opts) {
|
60
|
+
return new CreatedService(name, args, opts);
|
61
|
+
}
|
62
|
+
static wrap(name, service, cluster, opts) {
|
63
|
+
return new WrappedService(name, service, cluster, opts);
|
64
|
+
}
|
65
|
+
static external(name, id, cluster, opts) {
|
66
|
+
return new ExternalService(name, id, cluster, opts);
|
67
|
+
}
|
68
|
+
static of(name, entity, cluster, opts) {
|
69
|
+
return new ExternalService(
|
70
|
+
name,
|
71
|
+
output(entity).metadata,
|
72
|
+
output({ cluster, entity }).apply(({ cluster: cluster2, entity: entity2 }) => {
|
73
|
+
if (cluster2.id !== entity2.clusterId) {
|
74
|
+
throw new Error(
|
75
|
+
`Cluster mismatch when wrapping service "${name}": "${cluster2.id}" != "${entity2.clusterId}"`
|
76
|
+
);
|
77
|
+
}
|
78
|
+
return cluster2;
|
79
|
+
}),
|
80
|
+
opts
|
81
|
+
);
|
82
|
+
}
|
83
|
+
/**
|
84
|
+
* Returns the endpoints of the service applying the given filter.
|
85
|
+
*
|
86
|
+
* If no filter is specified, the default behavior of `filterEndpoints` is used.
|
87
|
+
*
|
88
|
+
* @param filter If specified, the endpoints are filtered based on the given filter.
|
89
|
+
* @returns The endpoints of the service.
|
90
|
+
*/
|
91
|
+
filterEndpoints(filter) {
|
92
|
+
return output({ endpoints: this.endpoints }).apply(({ endpoints }) => {
|
93
|
+
return filterEndpoints(endpoints, filter);
|
94
|
+
});
|
95
|
+
}
|
96
|
+
/**
|
97
|
+
* Returns the endpoints of the service including both internal and external endpoints.
|
98
|
+
*/
|
99
|
+
get endpoints() {
|
100
|
+
return output({
|
101
|
+
cluster: this.cluster,
|
102
|
+
metadata: this.metadata,
|
103
|
+
spec: this.spec,
|
104
|
+
status: this.status
|
105
|
+
}).apply(({ cluster, metadata, spec, status }) => {
|
106
|
+
const endpointMetadata = {
|
107
|
+
k8sService: {
|
108
|
+
clusterId: cluster.id,
|
109
|
+
name: metadata.name,
|
110
|
+
namespace: metadata.namespace,
|
111
|
+
selector: spec.selector,
|
112
|
+
targetPort: spec.ports[0].targetPort ?? spec.ports[0].port
|
113
|
+
}
|
114
|
+
};
|
115
|
+
const clusterIpEndpoints = spec.clusterIPs?.map((ip) => ({
|
116
|
+
...parseL3Endpoint(ip),
|
117
|
+
visibility: "internal",
|
118
|
+
port: spec.ports[0].port,
|
119
|
+
protocol: spec.ports[0].protocol?.toLowerCase(),
|
120
|
+
metadata: endpointMetadata
|
121
|
+
}));
|
122
|
+
if (clusterIpEndpoints.length > 0) {
|
123
|
+
clusterIpEndpoints.unshift({
|
124
|
+
type: "hostname",
|
125
|
+
visibility: "internal",
|
126
|
+
hostname: `${metadata.name}.${metadata.namespace}.svc.cluster.local`,
|
127
|
+
port: spec.ports[0].port,
|
128
|
+
protocol: spec.ports[0].protocol?.toLowerCase(),
|
129
|
+
metadata: endpointMetadata
|
130
|
+
});
|
131
|
+
}
|
132
|
+
const nodePortEndpoints = spec.type === "NodePort" ? cluster.endpoints.map((endpoint) => ({
|
133
|
+
...endpoint,
|
134
|
+
port: spec.ports[0].nodePort,
|
135
|
+
protocol: spec.ports[0].protocol?.toLowerCase(),
|
136
|
+
metadata: endpointMetadata
|
137
|
+
})) : [];
|
138
|
+
const loadBalancerEndpoints = spec.type === "LoadBalancer" ? status.loadBalancer?.ingress?.map((endpoint) => ({
|
139
|
+
...parseL3Endpoint(endpoint.ip ?? endpoint.hostname),
|
140
|
+
port: spec.ports[0].port,
|
141
|
+
protocol: spec.ports[0].protocol?.toLowerCase(),
|
142
|
+
metadata: endpointMetadata
|
143
|
+
})) : [];
|
144
|
+
return uniqueBy(
|
145
|
+
[
|
146
|
+
...clusterIpEndpoints ?? [],
|
147
|
+
...loadBalancerEndpoints ?? [],
|
148
|
+
...nodePortEndpoints ?? []
|
149
|
+
],
|
150
|
+
(endpoint) => l4EndpointToString(endpoint)
|
151
|
+
);
|
152
|
+
});
|
153
|
+
}
|
154
|
+
};
|
155
|
+
var CreatedService = class extends Service {
|
156
|
+
constructor(name, args, opts) {
|
157
|
+
const service = output(args).apply((args2) => {
|
158
|
+
return new core.v1.Service(
|
159
|
+
name,
|
160
|
+
{
|
161
|
+
metadata: mapMetadata(args2, name),
|
162
|
+
spec: deepmerge(
|
163
|
+
{
|
164
|
+
ports: normalize(args2.port, args2.ports),
|
165
|
+
externalIPs: args2.external ? args2.externalIPs ?? args2.cluster.externalIps : args2.cluster.externalIps,
|
166
|
+
type: getServiceType(args2, args2.cluster)
|
167
|
+
},
|
168
|
+
omit(args2, serviceExtraArgs)
|
169
|
+
)
|
170
|
+
},
|
171
|
+
{ parent: this, ...opts }
|
172
|
+
);
|
173
|
+
});
|
174
|
+
super(
|
175
|
+
"highstate:k8s:Service",
|
176
|
+
name,
|
177
|
+
args,
|
178
|
+
opts,
|
179
|
+
output(args.cluster),
|
180
|
+
service.metadata,
|
181
|
+
service.spec,
|
182
|
+
service.status
|
183
|
+
);
|
184
|
+
}
|
185
|
+
};
|
186
|
+
var WrappedService = class extends Service {
|
187
|
+
constructor(name, service, cluster, opts) {
|
188
|
+
super(
|
189
|
+
"highstate:k8s:WrappedService",
|
190
|
+
name,
|
191
|
+
{ service, clusterInfo: cluster },
|
192
|
+
opts,
|
193
|
+
output(cluster),
|
194
|
+
output(service).metadata,
|
195
|
+
output(service).spec,
|
196
|
+
output(service).status
|
197
|
+
);
|
198
|
+
}
|
199
|
+
};
|
200
|
+
var ExternalService = class extends Service {
|
201
|
+
constructor(name, id, cluster, opts) {
|
202
|
+
const service = output(id).apply((id2) => {
|
203
|
+
return core.v1.Service.get(
|
204
|
+
//
|
205
|
+
name,
|
206
|
+
resourceIdToString(id2),
|
207
|
+
{ ...opts, parent: this }
|
208
|
+
);
|
209
|
+
});
|
210
|
+
super(
|
211
|
+
"highstate:k8s:ExternalService",
|
212
|
+
name,
|
213
|
+
{ id, cluster },
|
214
|
+
opts,
|
215
|
+
output(cluster),
|
216
|
+
service.metadata,
|
217
|
+
service.spec,
|
218
|
+
service.status
|
219
|
+
);
|
220
|
+
}
|
221
|
+
};
|
222
|
+
function mapContainerPortToServicePort(port) {
|
223
|
+
return {
|
224
|
+
name: port.name,
|
225
|
+
port: port.containerPort,
|
226
|
+
targetPort: port.containerPort,
|
227
|
+
protocol: port.protocol
|
228
|
+
};
|
229
|
+
}
|
230
|
+
function mapServiceToLabelSelector(service) {
|
231
|
+
return {
|
232
|
+
matchLabels: service.spec.selector
|
233
|
+
};
|
234
|
+
}
|
235
|
+
function getServiceType(service, cluster) {
|
236
|
+
if (service?.type) {
|
237
|
+
return service.type;
|
238
|
+
}
|
239
|
+
if (!service?.external) {
|
240
|
+
return "ClusterIP";
|
241
|
+
}
|
242
|
+
return cluster.quirks?.externalServiceType === "LoadBalancer" ? "LoadBalancer" : "NodePort";
|
243
|
+
}
|
244
|
+
|
245
|
+
// src/gateway/http-route.ts
|
246
|
+
import {
|
247
|
+
ComponentResource as ComponentResource2,
|
248
|
+
normalize as normalize2,
|
249
|
+
output as output3
|
250
|
+
} from "@highstate/pulumi";
|
251
|
+
import { gateway } from "@highstate/gateway-api";
|
252
|
+
import { map, pipe } from "remeda";
|
253
|
+
|
254
|
+
// src/gateway/backend.ts
|
255
|
+
import "@pulumi/kubernetes";
|
256
|
+
import { output as output2 } from "@highstate/pulumi";
|
257
|
+
function resolveBackendRef(ref) {
|
258
|
+
if (Service.isInstance(ref)) {
|
259
|
+
return output2({
|
260
|
+
name: ref.metadata.name,
|
261
|
+
namespace: ref.metadata.namespace,
|
262
|
+
port: ref.spec.ports[0].port
|
263
|
+
});
|
264
|
+
}
|
265
|
+
if ("service" in ref) {
|
266
|
+
const service = output2(ref.service);
|
267
|
+
return output2({
|
268
|
+
name: service.metadata.name,
|
269
|
+
namespace: service.metadata.namespace,
|
270
|
+
port: ref.port
|
271
|
+
});
|
272
|
+
}
|
273
|
+
return output2({
|
274
|
+
name: ref.name,
|
275
|
+
namespace: ref.namespace,
|
276
|
+
port: ref.port
|
277
|
+
});
|
278
|
+
}
|
279
|
+
|
280
|
+
// src/gateway/http-route.ts
|
281
|
+
var HttpRoute = class extends ComponentResource2 {
|
282
|
+
/**
|
283
|
+
* The underlying Kubernetes resource.
|
284
|
+
*/
|
285
|
+
route;
|
286
|
+
constructor(name, args, opts) {
|
287
|
+
super("highstate:k8s:HttpRoute", name, args, opts);
|
288
|
+
this.route = output3({
|
289
|
+
args,
|
290
|
+
gatewayNamespace: output3(args.gateway).metadata.namespace
|
291
|
+
}).apply(async ({ args: args2, gatewayNamespace }) => {
|
292
|
+
return new gateway.v1.HTTPRoute(
|
293
|
+
name,
|
294
|
+
{
|
295
|
+
metadata: mapMetadata(
|
296
|
+
{
|
297
|
+
...args2,
|
298
|
+
namespace: gatewayNamespace
|
299
|
+
},
|
300
|
+
name
|
301
|
+
),
|
302
|
+
spec: {
|
303
|
+
hostnames: normalize2(args2.hostname, args2.hostnames),
|
304
|
+
parentRefs: [
|
305
|
+
{
|
306
|
+
name: args2.gateway.metadata.name
|
307
|
+
}
|
308
|
+
],
|
309
|
+
rules: normalize2(args2.rule, args2.rules).map((rule) => ({
|
310
|
+
timeouts: rule.timeouts,
|
311
|
+
matches: pipe(
|
312
|
+
normalize2(rule.match, rule.matches),
|
313
|
+
map(mapHttpRouteRuleMatch),
|
314
|
+
addDefaultPathMatch
|
315
|
+
),
|
316
|
+
filters: normalize2(rule.filter, rule.filters),
|
317
|
+
backendRefs: rule.backend ? [resolveBackendRef(rule.backend)] : void 0
|
318
|
+
}))
|
319
|
+
}
|
320
|
+
},
|
321
|
+
{
|
322
|
+
...opts,
|
323
|
+
parent: this,
|
324
|
+
provider: await getProvider(args2.cluster)
|
325
|
+
}
|
326
|
+
);
|
327
|
+
});
|
328
|
+
}
|
329
|
+
};
|
330
|
+
function addDefaultPathMatch(matches) {
|
331
|
+
return matches.length ? matches : [{ path: { type: "PathPrefix", value: "/" } }];
|
332
|
+
}
|
333
|
+
function mapHttpRouteRuleMatch(match) {
|
334
|
+
if (typeof match === "string") {
|
335
|
+
return { path: { type: "PathPrefix", value: match } };
|
336
|
+
}
|
337
|
+
return match;
|
338
|
+
}
|
339
|
+
|
340
|
+
// src/network-policy.ts
|
341
|
+
import { networking } from "@pulumi/kubernetes";
|
342
|
+
import {
|
343
|
+
ComponentResource as ComponentResource3,
|
344
|
+
interpolate,
|
345
|
+
normalize as normalize3,
|
346
|
+
output as output4
|
347
|
+
} from "@highstate/pulumi";
|
348
|
+
import { capitalize, flat, groupBy, merge, mergeDeep, uniqueBy as uniqueBy2 } from "remeda";
|
349
|
+
import "@highstate/library";
|
350
|
+
import {
|
351
|
+
l34EndpointToString,
|
352
|
+
l3EndpointToCidr,
|
353
|
+
parseL34Endpoint
|
354
|
+
} from "@highstate/common";
|
355
|
+
var NetworkPolicy = class _NetworkPolicy extends ComponentResource3 {
|
356
|
+
/**
|
357
|
+
* The underlying network policy resource.
|
358
|
+
*/
|
359
|
+
networkPolicy;
|
360
|
+
constructor(name, args, opts) {
|
361
|
+
super("k8s:network-policy", name, args, opts);
|
362
|
+
const normalizedArgs = output4(args).apply((args2) => {
|
363
|
+
const ingressRules = normalize3(args2.ingressRule, args2.ingressRules);
|
364
|
+
const egressRules = normalize3(args2.egressRule, args2.egressRules);
|
365
|
+
const extraEgressRules = [];
|
366
|
+
if (args2.allowKubeDns) {
|
367
|
+
extraEgressRules.push({
|
368
|
+
namespaces: ["kube-system"],
|
369
|
+
selectors: [{ matchLabels: { "k8s-app": "kube-dns" } }],
|
370
|
+
ports: [{ port: 53, protocol: "UDP" }],
|
371
|
+
all: false,
|
372
|
+
cidrs: [],
|
373
|
+
fqdns: [],
|
374
|
+
services: []
|
375
|
+
});
|
376
|
+
}
|
377
|
+
return {
|
378
|
+
...args2,
|
379
|
+
podSelector: args2.selector ? mapSelectorLikeToSelector(args2.selector) : {},
|
380
|
+
isolateEgress: args2.isolateEgress ?? false,
|
381
|
+
isolateIngress: args2.isolateIngress ?? false,
|
382
|
+
allowKubeApiServer: args2.allowKubeApiServer ?? false,
|
383
|
+
ingressRules: ingressRules.flatMap((rule) => {
|
384
|
+
const endpoints = normalize3(
|
385
|
+
args2.ingressRule?.fromEndpoint,
|
386
|
+
args2.ingressRule?.fromEndpoints
|
387
|
+
);
|
388
|
+
const parsedEndpoints = endpoints.map(parseL34Endpoint);
|
389
|
+
const endpointsByPortsAndNamespaces = groupBy(parsedEndpoints, (endpoint) => {
|
390
|
+
const namespace = isFromCluster(endpoint, args2.cluster) ? endpoint.metadata.k8sService.namespace : "";
|
391
|
+
const port = isFromCluster(endpoint, args2.cluster) ? endpoint.metadata.k8sService.targetPort : endpoint.port;
|
392
|
+
return `${port ?? "0"}:${namespace}`;
|
393
|
+
});
|
394
|
+
const l3OnlyRule = endpointsByPortsAndNamespaces["0:"] ? _NetworkPolicy.getRuleFromEndpoint(
|
395
|
+
void 0,
|
396
|
+
endpointsByPortsAndNamespaces["0:"],
|
397
|
+
args2.cluster
|
398
|
+
) : void 0;
|
399
|
+
const otherRules = Object.entries(endpointsByPortsAndNamespaces).filter(([key]) => key !== "0:").map(([key, endpoints2]) => {
|
400
|
+
const [port] = key.split(":");
|
401
|
+
const portNumber = parseInt(port, 10);
|
402
|
+
const portValue = isNaN(portNumber) ? port : portNumber;
|
403
|
+
return _NetworkPolicy.getRuleFromEndpoint(portValue, endpoints2, args2.cluster);
|
404
|
+
});
|
405
|
+
return [
|
406
|
+
{
|
407
|
+
all: rule.fromAll ?? false,
|
408
|
+
cidrs: normalize3(rule.fromCidr, rule.fromCidrs).concat(l3OnlyRule?.cidrs ?? []),
|
409
|
+
fqdns: [],
|
410
|
+
services: normalize3(rule.fromService, rule.fromServices),
|
411
|
+
namespaces: normalize3(rule.fromNamespace, rule.fromNamespaces),
|
412
|
+
selectors: normalize3(rule.fromSelector, rule.fromSelectors),
|
413
|
+
ports: normalize3(rule.toPort, rule.toPorts)
|
414
|
+
},
|
415
|
+
...otherRules
|
416
|
+
].filter((rule2) => !_NetworkPolicy.isEmptyRule(rule2));
|
417
|
+
}),
|
418
|
+
egressRules: egressRules.flatMap((rule) => {
|
419
|
+
const endpoints = normalize3(args2.egressRule?.toEndpoint, args2.egressRule?.toEndpoints);
|
420
|
+
const parsedEndpoints = endpoints.map(parseL34Endpoint);
|
421
|
+
const endpointsByPortsAnsNamespaces = groupBy(parsedEndpoints, (endpoint) => {
|
422
|
+
const namespace = isFromCluster(endpoint, args2.cluster) ? endpoint.metadata.k8sService.namespace : "";
|
423
|
+
const port = isFromCluster(endpoint, args2.cluster) ? endpoint.metadata.k8sService.targetPort : endpoint.port;
|
424
|
+
return `${port ?? "0"}:${namespace}`;
|
425
|
+
});
|
426
|
+
const l3OnlyRule = endpointsByPortsAnsNamespaces["0:"] ? _NetworkPolicy.getRuleFromEndpoint(
|
427
|
+
void 0,
|
428
|
+
endpointsByPortsAnsNamespaces["0:"],
|
429
|
+
args2.cluster
|
430
|
+
) : void 0;
|
431
|
+
const otherRules = Object.entries(endpointsByPortsAnsNamespaces).filter(([key]) => key !== "0:").map(([key, endpoints2]) => {
|
432
|
+
const [port] = key.split(":");
|
433
|
+
const portNumber = parseInt(port, 10);
|
434
|
+
const portValue = isNaN(portNumber) ? port : portNumber;
|
435
|
+
return _NetworkPolicy.getRuleFromEndpoint(portValue, endpoints2, args2.cluster);
|
436
|
+
});
|
437
|
+
return [
|
438
|
+
{
|
439
|
+
all: rule.toAll ?? false,
|
440
|
+
cidrs: normalize3(rule.toCidr, rule.toCidrs).concat(l3OnlyRule?.cidrs ?? []),
|
441
|
+
fqdns: normalize3(rule.toFqdn, rule.toFqdns).concat(l3OnlyRule?.fqdns ?? []),
|
442
|
+
services: normalize3(rule.toService, rule.toServices),
|
443
|
+
namespaces: normalize3(rule.toNamespace, rule.toNamespaces),
|
444
|
+
selectors: normalize3(rule.toSelector, rule.toSelectors),
|
445
|
+
ports: normalize3(rule.toPort, rule.toPorts)
|
446
|
+
},
|
447
|
+
...otherRules
|
448
|
+
].filter((rule2) => !_NetworkPolicy.isEmptyRule(rule2));
|
449
|
+
}).concat(extraEgressRules)
|
450
|
+
};
|
451
|
+
});
|
452
|
+
this.networkPolicy = output4(
|
453
|
+
normalizedArgs.apply(async (args2) => {
|
454
|
+
return output4(
|
455
|
+
this.create(name, args2, {
|
456
|
+
...opts,
|
457
|
+
parent: this,
|
458
|
+
provider: await getProvider(args2.cluster)
|
459
|
+
})
|
460
|
+
);
|
461
|
+
})
|
462
|
+
);
|
463
|
+
}
|
464
|
+
static mapCidrFromEndpoint(result) {
|
465
|
+
if (result.type === "ipv4") {
|
466
|
+
return `${result.address}/32`;
|
467
|
+
}
|
468
|
+
return `${result.address}/128`;
|
469
|
+
}
|
470
|
+
static getRuleFromEndpoint(port, endpoints, cluster) {
|
471
|
+
const ports = port ? [{ port, protocol: endpoints[0].protocol?.toUpperCase() }] : [];
|
472
|
+
const cidrs = endpoints.filter((endpoint) => !isFromCluster(endpoint, cluster)).filter((endpoint) => endpoint.type === "ipv4" || endpoint.type === "ipv6").map(_NetworkPolicy.mapCidrFromEndpoint);
|
473
|
+
const fqdns = endpoints.filter((endpoint) => endpoint.type === "hostname").map((endpoint) => endpoint.hostname);
|
474
|
+
const selectors = endpoints.filter((endpoint) => isFromCluster(endpoint, cluster)).map((endpoint) => endpoint.metadata.k8sService.selector);
|
475
|
+
const namespace = endpoints.filter((endpoint) => isFromCluster(endpoint, cluster)).map((endpoint) => getServiceMetadata(endpoint)?.namespace)[0];
|
476
|
+
return {
|
477
|
+
all: false,
|
478
|
+
cidrs,
|
479
|
+
fqdns,
|
480
|
+
services: [],
|
481
|
+
namespaces: namespace ? [namespace] : [],
|
482
|
+
selectors,
|
483
|
+
ports
|
484
|
+
};
|
485
|
+
}
|
486
|
+
static isEmptyRule(rule) {
|
487
|
+
return !rule.all && rule.cidrs.length === 0 && rule.fqdns.length === 0 && rule.services.length === 0 && rule.namespaces.length === 0 && rule.selectors.length === 0 && rule.ports.length === 0;
|
488
|
+
}
|
489
|
+
static create(name, args, opts) {
|
490
|
+
return output4(args).apply(async (args2) => {
|
491
|
+
const cni = args2.cluster.cni;
|
492
|
+
if (cni === "other") {
|
493
|
+
return new NativeNetworkPolicy(name, args2, opts);
|
494
|
+
}
|
495
|
+
const implName = `${capitalize(cni)}NetworkPolicy`;
|
496
|
+
const implModule = await import(`@highstate/${cni}`);
|
497
|
+
const implClass = implModule[implName];
|
498
|
+
if (!implClass) {
|
499
|
+
throw new Error(`No implementation found for ${cni}`);
|
500
|
+
}
|
501
|
+
return new implClass(name, args2, opts);
|
502
|
+
});
|
503
|
+
}
|
504
|
+
static isolate(namespace, cluster, opts) {
|
505
|
+
return _NetworkPolicy.create(
|
506
|
+
"isolate",
|
507
|
+
{
|
508
|
+
namespace,
|
509
|
+
cluster,
|
510
|
+
description: "By default, deny all traffic to/from the namespace.",
|
511
|
+
isolateEgress: true,
|
512
|
+
isolateIngress: true
|
513
|
+
},
|
514
|
+
opts
|
515
|
+
);
|
516
|
+
}
|
517
|
+
static allowInsideNamespace(namespace, cluster, opts) {
|
518
|
+
return _NetworkPolicy.create(
|
519
|
+
"allow-inside-namespace",
|
520
|
+
{
|
521
|
+
namespace,
|
522
|
+
cluster,
|
523
|
+
description: "Allow all traffic inside the namespace.",
|
524
|
+
selector: {},
|
525
|
+
ingressRule: { fromNamespace: namespace },
|
526
|
+
egressRule: { toNamespace: namespace }
|
527
|
+
},
|
528
|
+
opts
|
529
|
+
);
|
530
|
+
}
|
531
|
+
static allowKubeApiServer(namespace, cluster, opts) {
|
532
|
+
return _NetworkPolicy.create(
|
533
|
+
"allow-kube-api-server",
|
534
|
+
{
|
535
|
+
namespace,
|
536
|
+
cluster,
|
537
|
+
description: "Allow all traffic to the Kubernetes API server from the namespace.",
|
538
|
+
allowKubeApiServer: true
|
539
|
+
},
|
540
|
+
opts
|
541
|
+
);
|
542
|
+
}
|
543
|
+
static allowKubeDns(namespace, cluster, opts) {
|
544
|
+
return _NetworkPolicy.create(
|
545
|
+
"allow-kube-dns",
|
546
|
+
{
|
547
|
+
namespace,
|
548
|
+
cluster,
|
549
|
+
description: "Allow all traffic to the Kubernetes DNS server from the namespace.",
|
550
|
+
allowKubeDns: true
|
551
|
+
},
|
552
|
+
opts
|
553
|
+
);
|
554
|
+
}
|
555
|
+
static allowAllEgress(namespace, cluster, opts) {
|
556
|
+
return _NetworkPolicy.create(
|
557
|
+
"allow-all-egress",
|
558
|
+
{
|
559
|
+
namespace,
|
560
|
+
cluster,
|
561
|
+
description: "Allow all egress traffic from the namespace.",
|
562
|
+
egressRule: { toAll: true }
|
563
|
+
},
|
564
|
+
opts
|
565
|
+
);
|
566
|
+
}
|
567
|
+
static allowAllIngress(namespace, cluster, opts) {
|
568
|
+
return _NetworkPolicy.create(
|
569
|
+
"allow-all-ingress",
|
570
|
+
{
|
571
|
+
namespace,
|
572
|
+
cluster,
|
573
|
+
description: "Allow all ingress traffic to the namespace.",
|
574
|
+
ingressRule: { fromAll: true }
|
575
|
+
},
|
576
|
+
opts
|
577
|
+
);
|
578
|
+
}
|
579
|
+
static allowEgressToEndpoint(endpoint, namespace, cluster, opts) {
|
580
|
+
const parsedEndpoint = parseL34Endpoint(endpoint);
|
581
|
+
return _NetworkPolicy.create(
|
582
|
+
`allow-egress-to-${l34EndpointToString(parsedEndpoint)}`,
|
583
|
+
{
|
584
|
+
namespace,
|
585
|
+
cluster,
|
586
|
+
description: interpolate`Allow egress traffic to "${l34EndpointToString(parsedEndpoint)}" from the namespace.`,
|
587
|
+
egressRule: { toEndpoint: endpoint }
|
588
|
+
},
|
589
|
+
opts
|
590
|
+
);
|
591
|
+
}
|
592
|
+
static allowIngressFromEndpoint(endpoint, namespace, cluster, opts) {
|
593
|
+
const parsedEndpoint = parseL34Endpoint(endpoint);
|
594
|
+
return _NetworkPolicy.create(
|
595
|
+
`allow-ingress-from-${l34EndpointToString(parsedEndpoint)}`,
|
596
|
+
{
|
597
|
+
namespace,
|
598
|
+
cluster,
|
599
|
+
description: interpolate`Allow ingress traffic from "${l34EndpointToString(parsedEndpoint)}" to the namespace.`,
|
600
|
+
ingressRule: { fromEndpoint: endpoint }
|
601
|
+
},
|
602
|
+
opts
|
603
|
+
);
|
604
|
+
}
|
605
|
+
};
|
606
|
+
var NativeNetworkPolicy = class _NativeNetworkPolicy extends NetworkPolicy {
|
607
|
+
create(name, args, opts) {
|
608
|
+
const ingress = _NativeNetworkPolicy.createIngressRules(args);
|
609
|
+
const egress = _NativeNetworkPolicy.createEgressRules(args);
|
610
|
+
const policyTypes = [];
|
611
|
+
if (ingress.length > 0 || args.isolateIngress) {
|
612
|
+
policyTypes.push("Ingress");
|
613
|
+
}
|
614
|
+
if (egress.length > 0 || args.isolateEgress) {
|
615
|
+
policyTypes.push("Egress");
|
616
|
+
}
|
617
|
+
return new networking.v1.NetworkPolicy(
|
618
|
+
name,
|
619
|
+
{
|
620
|
+
metadata: mergeDeep(mapMetadata(args, name), {
|
621
|
+
annotations: args.description ? { "kubernetes.io/description": args.description } : void 0
|
622
|
+
}),
|
623
|
+
spec: {
|
624
|
+
podSelector: args.podSelector,
|
625
|
+
ingress,
|
626
|
+
egress,
|
627
|
+
policyTypes
|
628
|
+
}
|
629
|
+
},
|
630
|
+
opts
|
631
|
+
);
|
632
|
+
}
|
633
|
+
static fallbackIpBlock = {
|
634
|
+
cidr: "0.0.0.0/0",
|
635
|
+
except: ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]
|
636
|
+
};
|
637
|
+
static fallbackDnsRule = {
|
638
|
+
to: [
|
639
|
+
{
|
640
|
+
namespaceSelector: { matchLabels: { "kubernetes.io/metadata.name": "kube-system" } },
|
641
|
+
podSelector: { matchLabels: { "k8s-app": "kube-dns" } }
|
642
|
+
}
|
643
|
+
],
|
644
|
+
ports: [{ port: 53, protocol: "UDP" }]
|
645
|
+
};
|
646
|
+
static createIngressRules(args) {
|
647
|
+
return uniqueBy2(
|
648
|
+
args.ingressRules.map((rule) => ({
|
649
|
+
from: rule.all ? [] : _NativeNetworkPolicy.createRulePeers(rule),
|
650
|
+
ports: _NativeNetworkPolicy.mapPorts(rule.ports)
|
651
|
+
})),
|
652
|
+
(rule) => JSON.stringify(rule)
|
653
|
+
);
|
654
|
+
}
|
655
|
+
static createEgressRules(args) {
|
656
|
+
const extraRules = [];
|
657
|
+
const needKubeDns = args.egressRules.some((rule) => rule.fqdns.length > 0);
|
658
|
+
if (needKubeDns) {
|
659
|
+
extraRules.push(_NativeNetworkPolicy.fallbackDnsRule);
|
660
|
+
}
|
661
|
+
const needFallback = args.egressRules.some(
|
662
|
+
(rule) => rule.fqdns.some((fqdn) => !fqdn.endsWith(".cluster.local"))
|
663
|
+
);
|
664
|
+
if (needFallback) {
|
665
|
+
extraRules.push({ to: [{ ipBlock: _NativeNetworkPolicy.fallbackIpBlock }] });
|
666
|
+
}
|
667
|
+
if (args.allowKubeApiServer) {
|
668
|
+
const { quirks, apiEndpoints } = args.cluster;
|
669
|
+
if (quirks?.fallbackKubeApiAccess) {
|
670
|
+
extraRules.push({
|
671
|
+
to: [{ ipBlock: { cidr: `${quirks?.fallbackKubeApiAccess.serverIp}/32` } }],
|
672
|
+
ports: [{ port: quirks?.fallbackKubeApiAccess.serverPort, protocol: "TCP" }]
|
673
|
+
});
|
674
|
+
} else {
|
675
|
+
const rules = apiEndpoints.filter((endpoint) => endpoint.type !== "hostname").map((endpoint) => ({
|
676
|
+
to: [{ ipBlock: { cidr: l3EndpointToCidr(endpoint) } }],
|
677
|
+
ports: [{ port: endpoint.port, protocol: "TCP" }]
|
678
|
+
}));
|
679
|
+
extraRules.push(...rules);
|
680
|
+
}
|
681
|
+
}
|
682
|
+
return uniqueBy2(
|
683
|
+
args.egressRules.map((rule) => {
|
684
|
+
return {
|
685
|
+
to: rule.all ? [] : _NativeNetworkPolicy.createRulePeers(rule),
|
686
|
+
ports: _NativeNetworkPolicy.mapPorts(rule.ports)
|
687
|
+
};
|
688
|
+
}).filter((rule) => rule.to !== void 0).concat(extraRules),
|
689
|
+
(rule) => JSON.stringify(rule)
|
690
|
+
);
|
691
|
+
}
|
692
|
+
static createRulePeers(args) {
|
693
|
+
const peers = uniqueBy2(
|
694
|
+
[
|
695
|
+
..._NativeNetworkPolicy.createCidrPeers(args),
|
696
|
+
..._NativeNetworkPolicy.createServicePeers(args),
|
697
|
+
..._NativeNetworkPolicy.createSelectorPeers(args)
|
698
|
+
],
|
699
|
+
(peer) => JSON.stringify(peer)
|
700
|
+
);
|
701
|
+
return peers.length > 0 ? peers : void 0;
|
702
|
+
}
|
703
|
+
static createCidrPeers(args) {
|
704
|
+
return args.cidrs.map((cidr) => ({ ipBlock: { cidr } }));
|
705
|
+
}
|
706
|
+
static createServicePeers(args) {
|
707
|
+
return args.services.map((service) => {
|
708
|
+
const selector = mapServiceToLabelSelector(service);
|
709
|
+
return {
|
710
|
+
namespaceSelector: mapNamespaceNameToSelector(service.metadata.namespace),
|
711
|
+
podSelector: selector
|
712
|
+
};
|
713
|
+
});
|
714
|
+
}
|
715
|
+
static createSelectorPeers(args) {
|
716
|
+
const selectorPeers = args.selectors.map((selector) => ({
|
717
|
+
podSelector: mapSelectorLikeToSelector(selector)
|
718
|
+
}));
|
719
|
+
const namespacePeers = args.namespaces.map(_NativeNetworkPolicy.createNamespacePeer);
|
720
|
+
if (namespacePeers.length === 0) {
|
721
|
+
return selectorPeers;
|
722
|
+
}
|
723
|
+
if (selectorPeers.length === 0) {
|
724
|
+
return namespacePeers;
|
725
|
+
}
|
726
|
+
return flat(
|
727
|
+
selectorPeers.map((selectorPeer) => {
|
728
|
+
return namespacePeers.map((namespacePeer) => merge(selectorPeer, namespacePeer));
|
729
|
+
})
|
730
|
+
);
|
731
|
+
}
|
732
|
+
static createNamespacePeer(namespace) {
|
733
|
+
const namespaceName = mapNamespaceLikeToNamespaceName(namespace);
|
734
|
+
const namespaceSelector = mapNamespaceNameToSelector(namespaceName);
|
735
|
+
return { namespaceSelector };
|
736
|
+
}
|
737
|
+
static mapPorts(ports) {
|
738
|
+
return ports.map((port) => {
|
739
|
+
if ("port" in port) {
|
740
|
+
return {
|
741
|
+
port: port.port,
|
742
|
+
protocol: port.protocol ?? "TCP"
|
743
|
+
};
|
744
|
+
}
|
745
|
+
return {
|
746
|
+
port: port.range[0],
|
747
|
+
endPort: port.range[1],
|
748
|
+
protocol: port.protocol ?? "TCP"
|
749
|
+
};
|
750
|
+
});
|
751
|
+
}
|
752
|
+
};
|
753
|
+
|
754
|
+
export {
|
755
|
+
hasServiceMetadata,
|
756
|
+
getServiceMetadata,
|
757
|
+
withServiceMetadata,
|
758
|
+
isFromCluster,
|
759
|
+
Service,
|
760
|
+
mapContainerPortToServicePort,
|
761
|
+
mapServiceToLabelSelector,
|
762
|
+
getServiceType,
|
763
|
+
HttpRoute,
|
764
|
+
NetworkPolicy
|
765
|
+
};
|
766
|
+
//# sourceMappingURL=chunk-OP75IMU7.js.map
|