@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
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { Gateway, HttpRoute, TcpRoute, UdpRoute } from '../chunk-
|
|
2
|
-
import { Certificate } from '../chunk-
|
|
3
|
-
import { Service, l4EndpointToServicePort } from '../chunk-
|
|
4
|
-
import '../chunk-
|
|
5
|
-
import
|
|
6
|
-
import '../chunk-PZ5AY32C.js';
|
|
1
|
+
import { Gateway, HttpRoute, TcpRoute, UdpRoute } from '../chunk-P26SQ2ZB.js';
|
|
2
|
+
import { Certificate } from '../chunk-IXE3OKB4.js';
|
|
3
|
+
import { isEndpointFromCluster, Service, l4EndpointToServicePort } from '../chunk-OG2OPX7B.js';
|
|
4
|
+
import { Namespace, mapMetadata, getProvider } from '../chunk-TOLFVF4S.js';
|
|
5
|
+
import '../chunk-PZYGZSN5.js';
|
|
7
6
|
import { gatewayRouteMediator } from '@highstate/common';
|
|
8
7
|
import { k8s } from '@highstate/library';
|
|
9
8
|
import { toPromise } from '@highstate/pulumi';
|
|
@@ -11,15 +10,16 @@ import { core } from '@pulumi/kubernetes';
|
|
|
11
10
|
|
|
12
11
|
var createGatewayRoute = gatewayRouteMediator.implement(
|
|
13
12
|
k8s.gatewayDataSchema,
|
|
14
|
-
async ({ name, spec, opts }, data) => {
|
|
15
|
-
const namespace =
|
|
16
|
-
const certSecret = await getCertificateSecret(name, namespace, spec.
|
|
13
|
+
async ({ name, args: spec, opts }, data) => {
|
|
14
|
+
const namespace = resolveRouteNamespace(spec, data);
|
|
15
|
+
const certSecret = await getCertificateSecret(name, namespace, spec.certificate);
|
|
17
16
|
const certificateRef = certSecret ? {
|
|
18
17
|
kind: "Secret",
|
|
19
18
|
group: "",
|
|
20
19
|
name: certSecret.metadata.name
|
|
21
20
|
} : void 0;
|
|
22
|
-
|
|
21
|
+
const routeProtocol = resolveRouteProtocol(spec);
|
|
22
|
+
if (routeProtocol === "http") {
|
|
23
23
|
return await createHttpGatewayRoute({
|
|
24
24
|
name,
|
|
25
25
|
spec,
|
|
@@ -29,17 +29,23 @@ var createGatewayRoute = gatewayRouteMediator.implement(
|
|
|
29
29
|
certificateRef
|
|
30
30
|
});
|
|
31
31
|
}
|
|
32
|
-
const protocol = spec.type === "tcp" ? "TCP" : "UDP";
|
|
33
32
|
return await createL4GatewayRoute({
|
|
34
33
|
name,
|
|
35
34
|
spec,
|
|
36
35
|
opts,
|
|
37
36
|
data,
|
|
38
37
|
namespace,
|
|
39
|
-
protocol
|
|
38
|
+
protocol: routeProtocol === "tcp" ? "TCP" : "UDP"
|
|
40
39
|
});
|
|
41
40
|
}
|
|
42
41
|
);
|
|
42
|
+
function resolveRouteNamespace(spec, data) {
|
|
43
|
+
const metadataNamespace = spec.metadata["k8s.namespace"];
|
|
44
|
+
if (metadataNamespace instanceof Namespace) {
|
|
45
|
+
return metadataNamespace;
|
|
46
|
+
}
|
|
47
|
+
return Namespace.for(data.namespace, data.cluster);
|
|
48
|
+
}
|
|
43
49
|
async function createHttpGatewayRoute({
|
|
44
50
|
name,
|
|
45
51
|
spec,
|
|
@@ -48,34 +54,69 @@ async function createHttpGatewayRoute({
|
|
|
48
54
|
namespace,
|
|
49
55
|
certificateRef
|
|
50
56
|
}) {
|
|
51
|
-
const
|
|
57
|
+
const listenerPort = spec.port ?? (certificateRef ? data.httpsPort : data.httpPort);
|
|
58
|
+
const listenerProtocol = certificateRef ? "HTTPS" : "HTTP";
|
|
59
|
+
const listenerHostname = spec.fqdns[0];
|
|
52
60
|
const listeners = [
|
|
53
61
|
{
|
|
54
|
-
name:
|
|
55
|
-
port:
|
|
56
|
-
protocol:
|
|
62
|
+
name: `${listenerProtocol.toLowerCase()}-${listenerPort}`,
|
|
63
|
+
port: listenerPort,
|
|
64
|
+
protocol: listenerProtocol,
|
|
65
|
+
hostname: listenerHostname,
|
|
57
66
|
tls: {
|
|
58
67
|
mode: "Terminate",
|
|
59
68
|
certificateRefs: certificateRef ? [certificateRef] : void 0
|
|
60
69
|
}
|
|
61
70
|
}
|
|
62
71
|
];
|
|
63
|
-
const gateway =
|
|
72
|
+
const gateway = Gateway.create(
|
|
73
|
+
name,
|
|
64
74
|
{
|
|
65
|
-
name: data.className,
|
|
66
75
|
namespace,
|
|
67
76
|
gatewayClassName: data.className,
|
|
68
77
|
listeners
|
|
69
78
|
},
|
|
70
79
|
opts
|
|
71
80
|
);
|
|
81
|
+
const ruleSpecs = Object.values(spec.rules);
|
|
82
|
+
const rules = await Promise.all(
|
|
83
|
+
ruleSpecs.map(async (ruleSpec, ruleIndex) => {
|
|
84
|
+
const backendRefs = await Promise.all(
|
|
85
|
+
ruleSpec.backends.map(async (backend, backendIndex) => {
|
|
86
|
+
const backendData = await resolveBackendFromEndpoints({
|
|
87
|
+
routeName: name,
|
|
88
|
+
backendName: `${ruleIndex}-${backendIndex}`,
|
|
89
|
+
endpoints: backend.endpoints,
|
|
90
|
+
namespace,
|
|
91
|
+
cluster: data.cluster,
|
|
92
|
+
opts
|
|
93
|
+
});
|
|
94
|
+
const backendPort = await selectBackendPort({
|
|
95
|
+
ports: backendData.ports,
|
|
96
|
+
protocol: "TCP",
|
|
97
|
+
targetPort: backendData.preferredTargetPort,
|
|
98
|
+
serviceName: backendData.serviceName,
|
|
99
|
+
routeName: name
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
name: backendData.serviceName,
|
|
103
|
+
namespace: backendData.serviceNamespace,
|
|
104
|
+
port: backendPort.port
|
|
105
|
+
};
|
|
106
|
+
})
|
|
107
|
+
);
|
|
108
|
+
return {
|
|
109
|
+
matches: ruleSpec.paths,
|
|
110
|
+
backends: backendRefs
|
|
111
|
+
};
|
|
112
|
+
})
|
|
113
|
+
);
|
|
72
114
|
const httpRoute = new HttpRoute(
|
|
73
115
|
name,
|
|
74
116
|
{
|
|
75
117
|
gateway,
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
118
|
+
hostnames: spec.fqdns,
|
|
119
|
+
rules
|
|
79
120
|
},
|
|
80
121
|
opts
|
|
81
122
|
);
|
|
@@ -92,16 +133,24 @@ async function createL4GatewayRoute({
|
|
|
92
133
|
namespace,
|
|
93
134
|
protocol
|
|
94
135
|
}) {
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
}
|
|
99
|
-
const
|
|
136
|
+
const backends = Object.values(spec.rules).flatMap((rule) => rule.backends);
|
|
137
|
+
if (backends.length === 0) {
|
|
138
|
+
throw new Error(`Gateway route "${name}" has no backends to expose.`);
|
|
139
|
+
}
|
|
140
|
+
const firstBackend = backends[0];
|
|
141
|
+
const backendData = await resolveBackendFromEndpoints({
|
|
142
|
+
routeName: name,
|
|
143
|
+
backendName: "0",
|
|
144
|
+
endpoints: firstBackend.endpoints,
|
|
145
|
+
namespace,
|
|
146
|
+
cluster: data.cluster,
|
|
147
|
+
opts
|
|
148
|
+
});
|
|
100
149
|
const backendPort = await selectBackendPort({
|
|
101
|
-
ports:
|
|
150
|
+
ports: backendData.ports,
|
|
102
151
|
protocol,
|
|
103
|
-
targetPort:
|
|
104
|
-
serviceName,
|
|
152
|
+
targetPort: backendData.preferredTargetPort,
|
|
153
|
+
serviceName: backendData.serviceName,
|
|
105
154
|
routeName: name
|
|
106
155
|
});
|
|
107
156
|
const listenerPort = await resolveListenerPort({
|
|
@@ -111,9 +160,12 @@ async function createL4GatewayRoute({
|
|
|
111
160
|
routeName: name
|
|
112
161
|
});
|
|
113
162
|
const listenerName = `${protocol.toLowerCase()}-${listenerPort}`;
|
|
114
|
-
const
|
|
163
|
+
const gatewayName = name;
|
|
164
|
+
const gatewayResourceName = name;
|
|
165
|
+
const gateway = Gateway.create(
|
|
166
|
+
gatewayResourceName,
|
|
115
167
|
{
|
|
116
|
-
name:
|
|
168
|
+
name: gatewayName,
|
|
117
169
|
namespace,
|
|
118
170
|
gatewayClassName: data.className,
|
|
119
171
|
listeners: [
|
|
@@ -126,18 +178,11 @@ async function createL4GatewayRoute({
|
|
|
126
178
|
},
|
|
127
179
|
opts
|
|
128
180
|
);
|
|
129
|
-
const backendRef =
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
}
|
|
135
|
-
return {
|
|
136
|
-
name: metadata.name,
|
|
137
|
-
namespace: metadata.namespace,
|
|
138
|
-
port: backendPort.port
|
|
139
|
-
};
|
|
140
|
-
});
|
|
181
|
+
const backendRef = {
|
|
182
|
+
name: backendData.serviceName,
|
|
183
|
+
namespace: backendData.serviceNamespace,
|
|
184
|
+
port: backendPort.port
|
|
185
|
+
};
|
|
141
186
|
const routeOpts = { ...opts, parent: gateway };
|
|
142
187
|
const route = protocol === "TCP" ? new TcpRoute(
|
|
143
188
|
name,
|
|
@@ -180,6 +225,77 @@ async function getCertificateSecret(_name, namespace, tlsCertificate) {
|
|
|
180
225
|
"Not implemented: copying certificate secret across namespaces/clusters/different systems"
|
|
181
226
|
);
|
|
182
227
|
}
|
|
228
|
+
function resolveRouteProtocol(spec) {
|
|
229
|
+
const rules = Object.values(spec.rules);
|
|
230
|
+
if (rules.length === 0) {
|
|
231
|
+
throw new Error("Gateway route must contain at least one rule");
|
|
232
|
+
}
|
|
233
|
+
const type = rules[0].type;
|
|
234
|
+
if (rules.some((rule) => rule.type !== type)) {
|
|
235
|
+
throw new Error("Gateway route rules must use the same protocol type");
|
|
236
|
+
}
|
|
237
|
+
return type;
|
|
238
|
+
}
|
|
239
|
+
async function resolveBackendFromEndpoints({
|
|
240
|
+
routeName,
|
|
241
|
+
backendName,
|
|
242
|
+
endpoints,
|
|
243
|
+
namespace,
|
|
244
|
+
cluster,
|
|
245
|
+
opts
|
|
246
|
+
}) {
|
|
247
|
+
const serviceMeta = getServiceMetadataFromEndpoints(endpoints, cluster);
|
|
248
|
+
if (serviceMeta) {
|
|
249
|
+
const metadataPorts = endpoints.map((endpoint) => ({
|
|
250
|
+
name: typeof serviceMeta.targetPort === "string" ? serviceMeta.targetPort : void 0,
|
|
251
|
+
port: endpoint.port,
|
|
252
|
+
protocol: endpoint.protocol.toUpperCase(),
|
|
253
|
+
targetPort: serviceMeta.targetPort
|
|
254
|
+
}));
|
|
255
|
+
return {
|
|
256
|
+
serviceName: serviceMeta.name,
|
|
257
|
+
serviceNamespace: serviceMeta.namespace,
|
|
258
|
+
ports: metadataPorts,
|
|
259
|
+
preferredTargetPort: serviceMeta.targetPort
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
const syntheticService = await createServiceFromEndpoints(
|
|
263
|
+
`${routeName}-${backendName}`,
|
|
264
|
+
namespace,
|
|
265
|
+
endpoints,
|
|
266
|
+
cluster,
|
|
267
|
+
opts
|
|
268
|
+
);
|
|
269
|
+
const syntheticServiceName = await toPromise(syntheticService.service.metadata.name);
|
|
270
|
+
const syntheticServiceNamespace = await toPromise(syntheticService.service.metadata.namespace);
|
|
271
|
+
if (!syntheticServiceNamespace) {
|
|
272
|
+
throw new Error(
|
|
273
|
+
`Synthetic backend service "${syntheticServiceName}" for gateway route "${routeName}" has no namespace.`
|
|
274
|
+
);
|
|
275
|
+
}
|
|
276
|
+
return {
|
|
277
|
+
serviceName: syntheticServiceName,
|
|
278
|
+
serviceNamespace: syntheticServiceNamespace,
|
|
279
|
+
ports: syntheticService.ports
|
|
280
|
+
};
|
|
281
|
+
}
|
|
282
|
+
function getServiceMetadataFromEndpoints(endpoints, cluster) {
|
|
283
|
+
const serviceEndpoints = endpoints.filter((endpoint) => isEndpointFromCluster(endpoint, cluster));
|
|
284
|
+
if (serviceEndpoints.length === 0 || serviceEndpoints.length !== endpoints.length) {
|
|
285
|
+
return void 0;
|
|
286
|
+
}
|
|
287
|
+
const first = serviceEndpoints[0].metadata["k8s.service"];
|
|
288
|
+
if (serviceEndpoints.some(
|
|
289
|
+
(endpoint) => endpoint.metadata["k8s.service"].name !== first.name || endpoint.metadata["k8s.service"].namespace !== first.namespace
|
|
290
|
+
)) {
|
|
291
|
+
return void 0;
|
|
292
|
+
}
|
|
293
|
+
return {
|
|
294
|
+
name: first.name,
|
|
295
|
+
namespace: first.namespace,
|
|
296
|
+
targetPort: first.targetPort
|
|
297
|
+
};
|
|
298
|
+
}
|
|
183
299
|
async function createServiceFromEndpoints(name, namespace, endpointsInput, cluster, opts) {
|
|
184
300
|
const endpoints = await toPromise(endpointsInput);
|
|
185
301
|
if (!endpoints.length) {
|
|
@@ -232,25 +348,6 @@ async function createServiceFromEndpoints(name, namespace, endpointsInput, clust
|
|
|
232
348
|
ports: ipPortInfos
|
|
233
349
|
};
|
|
234
350
|
}
|
|
235
|
-
async function getServicePorts(service) {
|
|
236
|
-
const spec = await toPromise(service.spec);
|
|
237
|
-
const ports = spec.ports ?? [];
|
|
238
|
-
const result = [];
|
|
239
|
-
for (const port of ports) {
|
|
240
|
-
const value = port.port;
|
|
241
|
-
const protocol = (port.protocol ?? "TCP").toUpperCase();
|
|
242
|
-
if (value === void 0 || protocol !== "TCP" && protocol !== "UDP") {
|
|
243
|
-
continue;
|
|
244
|
-
}
|
|
245
|
-
result.push({
|
|
246
|
-
name: port.name ?? void 0,
|
|
247
|
-
port: value,
|
|
248
|
-
protocol,
|
|
249
|
-
targetPort: port.targetPort
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
return result;
|
|
253
|
-
}
|
|
254
351
|
function toServicePortInfoFromEndpoint(endpoint) {
|
|
255
352
|
return {
|
|
256
353
|
name: void 0,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/impl/gateway-route.ts"],"names":["service","match"],"mappings":"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","file":"gateway-route.js","sourcesContent":["import type { Secret } from \"../secret\"\nimport { type GatewayRouteSpec, gatewayRouteMediator, type TlsCertificate } from \"@highstate/common\"\nimport { k8s, type network } from \"@highstate/library\"\nimport { type ComponentResourceOptions, type Input, toPromise } from \"@highstate/pulumi\"\nimport { core } from \"@pulumi/kubernetes\"\nimport { Gateway, HttpRoute, TcpRoute, UdpRoute } from \"../gateway\"\nimport { Namespace } from \"../namespace\"\nimport { l4EndpointToServicePort, Service } from \"../service\"\nimport { getProvider, mapMetadata } from \"../shared\"\nimport { Certificate } from \"../tls\"\n\nexport const createGatewayRoute = gatewayRouteMediator.implement(\n k8s.gatewayDataSchema,\n async ({ name, spec, opts }, data) => {\n const namespace =\n spec.nativeData instanceof Service\n ? await toPromise(spec.nativeData.namespace)\n : Namespace.for(data.namespace, data.cluster)\n\n const certSecret = await getCertificateSecret(name, namespace, spec.tlsCertificate)\n\n const certificateRef = certSecret\n ? {\n kind: \"Secret\" as const,\n group: \"\" as const,\n name: certSecret.metadata.name,\n }\n : undefined\n\n if (spec.type === \"http\") {\n return await createHttpGatewayRoute({\n name,\n spec,\n opts,\n data,\n namespace,\n certificateRef,\n })\n }\n\n const protocol = spec.type === \"tcp\" ? \"TCP\" : \"UDP\"\n\n return await createL4GatewayRoute({\n name,\n spec,\n opts,\n data,\n namespace,\n protocol,\n })\n },\n)\n\ntype HttpGatewayRouteSpec = Extract<GatewayRouteSpec, { type: \"http\" }>\ntype L4GatewayRouteSpec = Extract<GatewayRouteSpec, { type: \"tcp\" | \"udp\" }>\n\ntype CreateHttpGatewayRouteArgs = {\n name: string\n spec: HttpGatewayRouteSpec\n opts: ComponentResourceOptions | undefined\n data: k8s.GatewayData\n namespace: Namespace\n certificateRef:\n | {\n kind: \"Secret\"\n group: \"\"\n name: Input<string>\n }\n | undefined\n}\n\nasync function createHttpGatewayRoute({\n name,\n spec,\n opts,\n data,\n namespace,\n certificateRef,\n}: CreateHttpGatewayRouteArgs) {\n const backendService =\n spec.nativeData instanceof Service\n ? spec.nativeData\n : (await createServiceFromEndpoints(name, namespace, spec.endpoints, data.cluster, opts))\n .service\n\n const listeners = [\n {\n name: \"https\",\n port: data.httpsPort,\n protocol: \"HTTPS\",\n tls: {\n mode: \"Terminate\",\n certificateRefs: certificateRef ? [certificateRef] : undefined,\n },\n },\n ]\n\n const gateway = await Gateway.createOnce(\n {\n name: data.className,\n namespace,\n gatewayClassName: data.className,\n listeners,\n },\n opts,\n )\n\n const httpRoute = new HttpRoute(\n name,\n {\n gateway,\n rule: {\n backend: backendService,\n },\n },\n opts,\n )\n\n return {\n resource: httpRoute,\n endpoints: await toPromise(gateway.endpoints),\n }\n}\n\ntype CreateL4GatewayRouteArgs = {\n name: string\n spec: L4GatewayRouteSpec\n opts: ComponentResourceOptions | undefined\n data: k8s.GatewayData\n namespace: Namespace\n protocol: \"TCP\" | \"UDP\"\n}\n\nasync function createL4GatewayRoute({\n name,\n spec,\n opts,\n data,\n namespace,\n protocol,\n}: CreateL4GatewayRouteArgs) {\n const serviceData =\n spec.nativeData instanceof Service\n ? {\n service: spec.nativeData,\n ports: await getServicePorts(spec.nativeData),\n }\n : await createServiceFromEndpoints(name, namespace, spec.endpoints, data.cluster, opts)\n\n const serviceName = await toPromise(serviceData.service.metadata.name)\n\n const backendPort = await selectBackendPort({\n ports: serviceData.ports,\n protocol,\n targetPort: spec.targetPort,\n serviceName,\n routeName: name,\n })\n\n const listenerPort = await resolveListenerPort({\n requestedPort: spec.port,\n backendPort,\n protocol,\n routeName: name,\n })\n\n const listenerName = `${protocol.toLowerCase()}-${listenerPort}`\n\n const gateway = await Gateway.createOnce(\n {\n name: data.className,\n namespace,\n gatewayClassName: data.className,\n listeners: [\n {\n name: listenerName,\n port: listenerPort,\n protocol,\n },\n ],\n },\n opts,\n )\n\n const backendRef = serviceData.service.metadata.apply(metadata => {\n if (!metadata?.name) {\n throw new Error(\n `Service \"${serviceName}\" referenced by gateway route \"${name}\" does not have a name.`,\n )\n }\n\n return {\n name: metadata.name,\n namespace: metadata.namespace,\n port: backendPort.port,\n }\n })\n\n const routeOpts = { ...opts, parent: gateway }\n\n const route =\n protocol === \"TCP\"\n ? new TcpRoute(\n name,\n {\n gateway,\n listenerName,\n backend: backendRef,\n },\n routeOpts,\n )\n : new UdpRoute(\n name,\n {\n gateway,\n listenerName,\n backend: backendRef,\n },\n routeOpts,\n )\n\n return {\n resource: route,\n endpoints: await toPromise(gateway.endpoints),\n }\n}\n\nasync function getCertificateSecret(\n _name: string,\n namespace: Namespace,\n tlsCertificate: Input<TlsCertificate | undefined> | undefined,\n): Promise<Secret | undefined> {\n const resolvedCertificate = await toPromise(tlsCertificate)\n if (!resolvedCertificate) {\n return undefined\n }\n\n const resource = await toPromise(resolvedCertificate.resource)\n\n if (resource instanceof Certificate) {\n const certNamespace = await toPromise(resource.namespace.metadata.name)\n const certClusterId = await toPromise(resource.namespace.cluster.id)\n\n const targetNamespace = await toPromise(namespace.metadata.name)\n const targetClusterId = await toPromise(namespace.cluster.id)\n\n if (certNamespace === targetNamespace && certClusterId === targetClusterId) {\n return await toPromise(resource.secret)\n }\n }\n\n throw new Error(\n \"Not implemented: copying certificate secret across namespaces/clusters/different systems\",\n )\n}\n\ntype ServicePortInfo = {\n name: string | undefined\n port: number\n protocol: \"TCP\" | \"UDP\"\n targetPort?: number | string\n}\n\nasync function createServiceFromEndpoints(\n name: string,\n namespace: Namespace,\n endpointsInput: Input<network.L4Endpoint[]>,\n cluster: k8s.Cluster,\n opts: ComponentResourceOptions | undefined,\n): Promise<{ service: Service; ports: ServicePortInfo[] }> {\n const endpoints = await toPromise(endpointsInput)\n\n if (!endpoints.length) {\n throw new Error(`Gateway route \"${name}\" has no endpoints to expose.`)\n }\n\n const hostnameEndpoints = endpoints.filter(endpoint => endpoint.type === \"hostname\")\n const ipEndpoints = endpoints.filter(endpoint => endpoint.type !== \"hostname\")\n\n if (hostnameEndpoints.length > 0) {\n const hostnamePortInfos: ServicePortInfo[] = []\n for (const endpoint of hostnameEndpoints) {\n hostnamePortInfos.push(toServicePortInfoFromEndpoint(endpoint))\n }\n\n const service = Service.create(`hs-backend-${name}`, {\n namespace,\n type: \"ExternalName\",\n externalName: hostnameEndpoints[0].hostname,\n ports: hostnameEndpoints.map(l4EndpointToServicePort),\n })\n\n return {\n service,\n ports: hostnamePortInfos,\n }\n }\n\n if (ipEndpoints.length === 0) {\n throw new Error(`Gateway route \"${name}\" requires at least one IP endpoint.`)\n }\n\n const ipPortInfos: ServicePortInfo[] = []\n for (const endpoint of ipEndpoints) {\n ipPortInfos.push(toServicePortInfoFromEndpoint(endpoint))\n }\n\n const service = Service.create(`hs-backend-${name}`, {\n namespace,\n type: \"ClusterIP\",\n ports: ipEndpoints.map(l4EndpointToServicePort),\n })\n\n const endpointsName = `hs-backend-${name}`\n\n new core.v1.Endpoints(\n endpointsName,\n {\n metadata: mapMetadata({ namespace }, endpointsName),\n subsets: ipEndpoints.map(endpoint => ({\n addresses: [{ ip: endpoint.address.value }],\n ports: [l4EndpointToServicePort(endpoint)],\n })),\n },\n { ...opts, provider: getProvider(cluster), parent: service },\n )\n\n return {\n service,\n ports: ipPortInfos,\n }\n}\n\nasync function getServicePorts(service: Service): Promise<ServicePortInfo[]> {\n const spec = await toPromise(service.spec)\n const ports = spec.ports ?? []\n\n const result: ServicePortInfo[] = []\n\n for (const port of ports) {\n const value = port.port\n const protocol = (port.protocol ?? \"TCP\").toUpperCase()\n\n if (value === undefined || (protocol !== \"TCP\" && protocol !== \"UDP\")) {\n continue\n }\n\n result.push({\n name: port.name ?? undefined,\n port: value,\n protocol: protocol as \"TCP\" | \"UDP\",\n targetPort: port.targetPort as number | string | undefined,\n })\n }\n\n return result\n}\n\nfunction toServicePortInfoFromEndpoint(endpoint: network.L4Endpoint): ServicePortInfo {\n return {\n name: undefined,\n port: endpoint.port,\n protocol: endpoint.protocol.toUpperCase() as \"TCP\" | \"UDP\",\n targetPort: endpoint.port,\n }\n}\n\nasync function selectBackendPort({\n ports,\n protocol,\n targetPort,\n serviceName,\n routeName,\n}: {\n ports: ServicePortInfo[]\n protocol: \"TCP\" | \"UDP\"\n targetPort: Input<string | number | undefined> | undefined\n serviceName: string\n routeName: string\n}): Promise<ServicePortInfo> {\n const candidates = ports.filter(port => port.protocol === protocol)\n\n if (candidates.length === 0) {\n throw new Error(\n `Service \"${serviceName}\" does not expose any ${protocol} ports required by gateway route \"${routeName}\".`,\n )\n }\n\n if (!targetPort) {\n return candidates[0]\n }\n\n const resolvedTarget = await toPromise(targetPort)\n\n if (resolvedTarget === undefined || resolvedTarget === null) {\n return candidates[0]\n }\n\n if (typeof resolvedTarget === \"number\") {\n const match = candidates.find(candidate => {\n if (candidate.port === resolvedTarget) {\n return true\n }\n\n if (typeof candidate.targetPort === \"number\") {\n return candidate.targetPort === resolvedTarget\n }\n\n return false\n })\n\n if (match) {\n return match\n }\n\n throw new Error(\n `Gateway route \"${routeName}\" requested target port ${resolvedTarget}, but service \"${serviceName}\" does not expose it for ${protocol} backends.`,\n )\n }\n\n const targetString = String(resolvedTarget)\n\n const match = candidates.find(candidate => {\n if (candidate.name === targetString) {\n return true\n }\n\n if (typeof candidate.targetPort === \"string\") {\n return candidate.targetPort === targetString\n }\n\n return false\n })\n\n if (match) {\n return match\n }\n\n throw new Error(\n `Gateway route \"${routeName}\" requested target port \"${targetString}\", but service \"${serviceName}\" does not expose it for ${protocol} backends.`,\n )\n}\n\nasync function resolveListenerPort({\n requestedPort,\n backendPort,\n protocol,\n routeName,\n}: {\n requestedPort: Input<number | undefined> | undefined\n backendPort: ServicePortInfo\n protocol: \"TCP\" | \"UDP\"\n routeName: string\n}): Promise<number> {\n if (!requestedPort) {\n return backendPort.port\n }\n\n const resolved = await toPromise(requestedPort)\n\n if (resolved === undefined || resolved === null) {\n return backendPort.port\n }\n\n if (!Number.isInteger(resolved)) {\n throw new Error(\n `Gateway route \"${routeName}\" must use integer listener ports for ${protocol.toLowerCase()} traffic.`,\n )\n }\n\n const port = Number(resolved)\n\n if (port < 1 || port > 65535) {\n throw new Error(\n `Gateway route \"${routeName}\" specified listener port ${port}, which is outside the valid range 1-65535.`,\n )\n }\n\n return port\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/impl/gateway-route.ts"],"names":["service","match"],"mappings":"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","file":"gateway-route.js","sourcesContent":["import type { Secret } from \"../secret\"\nimport { gatewayRouteMediator, type TlsCertificate } from \"@highstate/common\"\nimport { type common, k8s, type network } from \"@highstate/library\"\nimport { type ComponentResourceOptions, type Input, toPromise } from \"@highstate/pulumi\"\nimport { core } from \"@pulumi/kubernetes\"\nimport { Gateway, HttpRoute, TcpRoute, UdpRoute } from \"../gateway\"\nimport { Namespace } from \"../namespace\"\nimport { isEndpointFromCluster, l4EndpointToServicePort, Service } from \"../service\"\nimport { getProvider, mapMetadata } from \"../shared\"\nimport { Certificate } from \"../tls\"\n\nexport const createGatewayRoute = gatewayRouteMediator.implement(\n k8s.gatewayDataSchema,\n async ({ name, args: spec, opts }, data) => {\n const namespace = resolveRouteNamespace(spec, data)\n\n const certSecret = await getCertificateSecret(name, namespace, spec.certificate)\n\n const certificateRef = certSecret\n ? {\n kind: \"Secret\" as const,\n group: \"\" as const,\n name: certSecret.metadata.name,\n }\n : undefined\n\n const routeProtocol = resolveRouteProtocol(spec)\n\n if (routeProtocol === \"http\") {\n return await createHttpGatewayRoute({\n name,\n spec,\n opts,\n data,\n namespace,\n certificateRef,\n })\n }\n\n return await createL4GatewayRoute({\n name,\n spec,\n opts,\n data,\n namespace,\n protocol: routeProtocol === \"tcp\" ? \"TCP\" : \"UDP\",\n })\n },\n)\n\ntype GatewayRouteRuleSpec = {\n type: \"http\" | \"tcp\" | \"udp\"\n paths: string[]\n backends: {\n endpoints: network.L4Endpoint[]\n weight?: number\n }[]\n}\n\nfunction resolveRouteNamespace(spec: GatewayRouteSpec, data: k8s.GatewayData): Namespace {\n const metadataNamespace = spec.metadata[\"k8s.namespace\"]\n\n if (metadataNamespace instanceof Namespace) {\n return metadataNamespace\n }\n\n return Namespace.for(data.namespace, data.cluster)\n}\n\ntype GatewayRouteSpec = {\n gateway: common.Gateway\n metadata: Record<string, unknown>\n fqdns: string[]\n certificate?: TlsCertificate\n port?: number\n rules: Record<string, GatewayRouteRuleSpec>\n}\n\ntype CreateHttpGatewayRouteArgs = {\n name: string\n spec: GatewayRouteSpec\n opts: ComponentResourceOptions | undefined\n data: k8s.GatewayData\n namespace: Namespace\n certificateRef:\n | {\n kind: \"Secret\"\n group: \"\"\n name: Input<string>\n }\n | undefined\n}\n\nasync function createHttpGatewayRoute({\n name,\n spec,\n opts,\n data,\n namespace,\n certificateRef,\n}: CreateHttpGatewayRouteArgs) {\n const listenerPort = spec.port ?? (certificateRef ? data.httpsPort : data.httpPort)\n const listenerProtocol = certificateRef ? \"HTTPS\" : \"HTTP\"\n const listenerHostname = spec.fqdns[0]\n\n const listeners = [\n {\n name: `${listenerProtocol.toLowerCase()}-${listenerPort}`,\n port: listenerPort,\n protocol: listenerProtocol,\n hostname: listenerHostname,\n tls: {\n mode: \"Terminate\",\n certificateRefs: certificateRef ? [certificateRef] : undefined,\n },\n },\n ]\n\n const gateway = Gateway.create(\n name,\n {\n namespace,\n gatewayClassName: data.className,\n listeners,\n },\n opts,\n )\n\n const ruleSpecs = Object.values(spec.rules)\n\n const rules = await Promise.all(\n ruleSpecs.map(async (ruleSpec, ruleIndex) => {\n const backendRefs = await Promise.all(\n ruleSpec.backends.map(async (backend, backendIndex) => {\n const backendData = await resolveBackendFromEndpoints({\n routeName: name,\n backendName: `${ruleIndex}-${backendIndex}`,\n endpoints: backend.endpoints,\n namespace,\n cluster: data.cluster,\n opts,\n })\n\n const backendPort = await selectBackendPort({\n ports: backendData.ports,\n protocol: \"TCP\",\n targetPort: backendData.preferredTargetPort,\n serviceName: backendData.serviceName,\n routeName: name,\n })\n\n return {\n name: backendData.serviceName,\n namespace: backendData.serviceNamespace,\n port: backendPort.port,\n }\n }),\n )\n\n return {\n matches: ruleSpec.paths,\n backends: backendRefs,\n }\n }),\n )\n\n const httpRoute = new HttpRoute(\n name,\n {\n gateway,\n hostnames: spec.fqdns,\n rules,\n },\n opts,\n )\n\n return {\n resource: httpRoute,\n endpoints: await toPromise(gateway.endpoints),\n }\n}\n\ntype CreateL4GatewayRouteArgs = {\n name: string\n spec: GatewayRouteSpec\n opts: ComponentResourceOptions | undefined\n data: k8s.GatewayData\n namespace: Namespace\n protocol: \"TCP\" | \"UDP\"\n}\n\nasync function createL4GatewayRoute({\n name,\n spec,\n opts,\n data,\n namespace,\n protocol,\n}: CreateL4GatewayRouteArgs) {\n const backends = Object.values(spec.rules).flatMap(rule => rule.backends)\n\n if (backends.length === 0) {\n throw new Error(`Gateway route \"${name}\" has no backends to expose.`)\n }\n\n const firstBackend = backends[0]\n\n const backendData = await resolveBackendFromEndpoints({\n routeName: name,\n backendName: \"0\",\n endpoints: firstBackend.endpoints,\n namespace,\n cluster: data.cluster,\n opts,\n })\n\n const backendPort = await selectBackendPort({\n ports: backendData.ports,\n protocol,\n targetPort: backendData.preferredTargetPort,\n serviceName: backendData.serviceName,\n routeName: name,\n })\n\n const listenerPort = await resolveListenerPort({\n requestedPort: spec.port,\n backendPort,\n protocol,\n routeName: name,\n })\n\n const listenerName = `${protocol.toLowerCase()}-${listenerPort}`\n\n const gatewayName = name\n const gatewayResourceName = name\n\n const gateway = Gateway.create(\n gatewayResourceName,\n {\n name: gatewayName,\n namespace,\n gatewayClassName: data.className,\n listeners: [\n {\n name: listenerName,\n port: listenerPort,\n protocol,\n },\n ],\n },\n opts,\n )\n\n const backendRef = {\n name: backendData.serviceName,\n namespace: backendData.serviceNamespace,\n port: backendPort.port,\n }\n\n const routeOpts = { ...opts, parent: gateway }\n\n const route =\n protocol === \"TCP\"\n ? new TcpRoute(\n name,\n {\n gateway,\n listenerName,\n backend: backendRef,\n },\n routeOpts,\n )\n : new UdpRoute(\n name,\n {\n gateway,\n listenerName,\n backend: backendRef,\n },\n routeOpts,\n )\n\n return {\n resource: route,\n endpoints: await toPromise(gateway.endpoints),\n }\n}\n\nasync function getCertificateSecret(\n _name: string,\n namespace: Namespace,\n tlsCertificate: Input<TlsCertificate | undefined> | undefined,\n): Promise<Secret | undefined> {\n const resolvedCertificate = await toPromise(tlsCertificate)\n if (!resolvedCertificate) {\n return undefined\n }\n\n const resource = await toPromise(resolvedCertificate.resource)\n\n if (resource instanceof Certificate) {\n const certNamespace = await toPromise(resource.namespace.metadata.name)\n const certClusterId = await toPromise(resource.namespace.cluster.id)\n\n const targetNamespace = await toPromise(namespace.metadata.name)\n const targetClusterId = await toPromise(namespace.cluster.id)\n\n if (certNamespace === targetNamespace && certClusterId === targetClusterId) {\n return await toPromise(resource.secret)\n }\n }\n\n throw new Error(\n \"Not implemented: copying certificate secret across namespaces/clusters/different systems\",\n )\n}\n\nfunction resolveRouteProtocol(spec: GatewayRouteSpec): GatewayRouteRuleSpec[\"type\"] {\n const rules = Object.values(spec.rules)\n\n if (rules.length === 0) {\n throw new Error(\"Gateway route must contain at least one rule\")\n }\n\n const type = rules[0].type\n\n if (rules.some(rule => rule.type !== type)) {\n throw new Error(\"Gateway route rules must use the same protocol type\")\n }\n\n return type\n}\n\nasync function resolveBackendFromEndpoints({\n routeName,\n backendName,\n endpoints,\n namespace,\n cluster,\n opts,\n}: {\n routeName: string\n backendName: string\n endpoints: network.L4Endpoint[]\n namespace: Namespace\n cluster: k8s.Cluster\n opts: ComponentResourceOptions | undefined\n}): Promise<{\n serviceName: string\n serviceNamespace: string\n ports: ServicePortInfo[]\n preferredTargetPort?: number | string\n}> {\n const serviceMeta = getServiceMetadataFromEndpoints(endpoints, cluster)\n\n if (serviceMeta) {\n const metadataPorts: ServicePortInfo[] = endpoints.map(endpoint => ({\n name: typeof serviceMeta.targetPort === \"string\" ? serviceMeta.targetPort : undefined,\n port: endpoint.port,\n protocol: endpoint.protocol.toUpperCase() as \"TCP\" | \"UDP\",\n targetPort: serviceMeta.targetPort,\n }))\n\n return {\n serviceName: serviceMeta.name,\n serviceNamespace: serviceMeta.namespace,\n ports: metadataPorts,\n preferredTargetPort: serviceMeta.targetPort,\n }\n }\n\n const syntheticService = await createServiceFromEndpoints(\n `${routeName}-${backendName}`,\n namespace,\n endpoints,\n cluster,\n opts,\n )\n\n const syntheticServiceName = await toPromise(syntheticService.service.metadata.name)\n const syntheticServiceNamespace = await toPromise(syntheticService.service.metadata.namespace)\n\n if (!syntheticServiceNamespace) {\n throw new Error(\n `Synthetic backend service \"${syntheticServiceName}\" for gateway route \"${routeName}\" has no namespace.`,\n )\n }\n\n return {\n serviceName: syntheticServiceName,\n serviceNamespace: syntheticServiceNamespace,\n ports: syntheticService.ports,\n }\n}\n\nfunction getServiceMetadataFromEndpoints(\n endpoints: network.L4Endpoint[],\n cluster: k8s.Cluster,\n):\n | {\n name: string\n namespace: string\n targetPort?: number | string\n }\n | undefined {\n const serviceEndpoints = endpoints.filter(endpoint => isEndpointFromCluster(endpoint, cluster))\n\n if (serviceEndpoints.length === 0 || serviceEndpoints.length !== endpoints.length) {\n return undefined\n }\n\n const first = serviceEndpoints[0].metadata[\"k8s.service\"]\n\n if (\n serviceEndpoints.some(\n endpoint =>\n endpoint.metadata[\"k8s.service\"].name !== first.name ||\n endpoint.metadata[\"k8s.service\"].namespace !== first.namespace,\n )\n ) {\n return undefined\n }\n\n return {\n name: first.name,\n namespace: first.namespace,\n targetPort: first.targetPort,\n }\n}\n\ntype ServicePortInfo = {\n name: string | undefined\n port: number\n protocol: \"TCP\" | \"UDP\"\n targetPort?: number | string\n}\n\nasync function createServiceFromEndpoints(\n name: string,\n namespace: Namespace,\n endpointsInput: Input<network.L4Endpoint[]>,\n cluster: k8s.Cluster,\n opts: ComponentResourceOptions | undefined,\n): Promise<{ service: Service; ports: ServicePortInfo[] }> {\n const endpoints = await toPromise(endpointsInput)\n\n if (!endpoints.length) {\n throw new Error(`Gateway route \"${name}\" has no endpoints to expose.`)\n }\n\n const hostnameEndpoints = endpoints.filter(endpoint => endpoint.type === \"hostname\")\n const ipEndpoints = endpoints.filter(endpoint => endpoint.type !== \"hostname\")\n\n if (hostnameEndpoints.length > 0) {\n const hostnamePortInfos: ServicePortInfo[] = []\n for (const endpoint of hostnameEndpoints) {\n hostnamePortInfos.push(toServicePortInfoFromEndpoint(endpoint))\n }\n\n const service = Service.create(`hs-backend-${name}`, {\n namespace,\n type: \"ExternalName\",\n externalName: hostnameEndpoints[0].hostname,\n ports: hostnameEndpoints.map(l4EndpointToServicePort),\n })\n\n return {\n service,\n ports: hostnamePortInfos,\n }\n }\n\n if (ipEndpoints.length === 0) {\n throw new Error(`Gateway route \"${name}\" requires at least one IP endpoint.`)\n }\n\n const ipPortInfos: ServicePortInfo[] = []\n for (const endpoint of ipEndpoints) {\n ipPortInfos.push(toServicePortInfoFromEndpoint(endpoint))\n }\n\n const service = Service.create(`hs-backend-${name}`, {\n namespace,\n type: \"ClusterIP\",\n ports: ipEndpoints.map(l4EndpointToServicePort),\n })\n\n const endpointsName = `hs-backend-${name}`\n\n new core.v1.Endpoints(\n endpointsName,\n {\n metadata: mapMetadata({ namespace }, endpointsName),\n subsets: ipEndpoints.map(endpoint => ({\n addresses: [{ ip: endpoint.address.value }],\n ports: [l4EndpointToServicePort(endpoint)],\n })),\n },\n { ...opts, provider: getProvider(cluster), parent: service },\n )\n\n return {\n service,\n ports: ipPortInfos,\n }\n}\n\nasync function _getServicePorts(service: Service): Promise<ServicePortInfo[]> {\n const spec = await toPromise(service.spec)\n const ports = spec.ports ?? []\n\n const result: ServicePortInfo[] = []\n\n for (const port of ports) {\n const value = port.port\n const protocol = (port.protocol ?? \"TCP\").toUpperCase()\n\n if (value === undefined || (protocol !== \"TCP\" && protocol !== \"UDP\")) {\n continue\n }\n\n result.push({\n name: port.name ?? undefined,\n port: value,\n protocol: protocol as \"TCP\" | \"UDP\",\n targetPort: port.targetPort as number | string | undefined,\n })\n }\n\n return result\n}\n\nfunction toServicePortInfoFromEndpoint(endpoint: network.L4Endpoint): ServicePortInfo {\n return {\n name: undefined,\n port: endpoint.port,\n protocol: endpoint.protocol.toUpperCase() as \"TCP\" | \"UDP\",\n targetPort: endpoint.port,\n }\n}\n\nasync function selectBackendPort({\n ports,\n protocol,\n targetPort,\n serviceName,\n routeName,\n}: {\n ports: ServicePortInfo[]\n protocol: \"TCP\" | \"UDP\"\n targetPort: Input<string | number | undefined> | undefined\n serviceName: string\n routeName: string\n}): Promise<ServicePortInfo> {\n const candidates = ports.filter(port => port.protocol === protocol)\n\n if (candidates.length === 0) {\n throw new Error(\n `Service \"${serviceName}\" does not expose any ${protocol} ports required by gateway route \"${routeName}\".`,\n )\n }\n\n if (!targetPort) {\n return candidates[0]\n }\n\n const resolvedTarget = await toPromise(targetPort)\n\n if (resolvedTarget === undefined || resolvedTarget === null) {\n return candidates[0]\n }\n\n if (typeof resolvedTarget === \"number\") {\n const match = candidates.find(candidate => {\n if (candidate.port === resolvedTarget) {\n return true\n }\n\n if (typeof candidate.targetPort === \"number\") {\n return candidate.targetPort === resolvedTarget\n }\n\n return false\n })\n\n if (match) {\n return match\n }\n\n throw new Error(\n `Gateway route \"${routeName}\" requested target port ${resolvedTarget}, but service \"${serviceName}\" does not expose it for ${protocol} backends.`,\n )\n }\n\n const targetString = String(resolvedTarget)\n\n const match = candidates.find(candidate => {\n if (candidate.name === targetString) {\n return true\n }\n\n if (typeof candidate.targetPort === \"string\") {\n return candidate.targetPort === targetString\n }\n\n return false\n })\n\n if (match) {\n return match\n }\n\n throw new Error(\n `Gateway route \"${routeName}\" requested target port \"${targetString}\", but service \"${serviceName}\" does not expose it for ${protocol} backends.`,\n )\n}\n\nasync function resolveListenerPort({\n requestedPort,\n backendPort,\n protocol,\n routeName,\n}: {\n requestedPort: Input<number | undefined> | undefined\n backendPort: ServicePortInfo\n protocol: \"TCP\" | \"UDP\"\n routeName: string\n}): Promise<number> {\n if (!requestedPort) {\n return backendPort.port\n }\n\n const resolved = await toPromise(requestedPort)\n\n if (resolved === undefined || resolved === null) {\n return backendPort.port\n }\n\n if (!Number.isInteger(resolved)) {\n throw new Error(\n `Gateway route \"${routeName}\" must use integer listener ports for ${protocol.toLowerCase()} traffic.`,\n )\n }\n\n const port = Number(resolved)\n\n if (port < 1 || port > 65535) {\n throw new Error(\n `Gateway route \"${routeName}\" specified listener port ${port}, which is outside the valid range 1-65535.`,\n )\n }\n\n return port\n}\n"]}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import { Certificate } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import
|
|
4
|
-
import '../chunk-PZ5AY32C.js';
|
|
1
|
+
import { Certificate } from '../chunk-IXE3OKB4.js';
|
|
2
|
+
import { getProvider, Namespace } from '../chunk-TOLFVF4S.js';
|
|
3
|
+
import '../chunk-PZYGZSN5.js';
|
|
5
4
|
import { tlsCertificateMediator } from '@highstate/common';
|
|
6
5
|
import { k8s } from '@highstate/library';
|
|
7
6
|
|
|
@@ -9,7 +8,9 @@ var createCertificate = tlsCertificateMediator.implement(
|
|
|
9
8
|
k8s.tlsIssuerDataSchema,
|
|
10
9
|
({ name, spec, opts }, data) => {
|
|
11
10
|
const provider = getProvider(data.cluster);
|
|
12
|
-
const
|
|
11
|
+
const metadata = spec.metadata;
|
|
12
|
+
const metadataNamespace = metadata?.["k8s.namespace"];
|
|
13
|
+
const namespace = metadataNamespace instanceof Namespace ? metadataNamespace : metadataNamespace ? Namespace.for(metadataNamespace, data.cluster) : Namespace.get("cert-manager", { name: "cert-manager", cluster: data.cluster });
|
|
13
14
|
return Certificate.create(
|
|
14
15
|
name,
|
|
15
16
|
{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/impl/tls-certificate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"sources":["../../src/impl/tls-certificate.ts"],"names":[],"mappings":";;;;;;AAMO,IAAM,oBAAoB,sBAAA,CAAuB,SAAA;AAAA,EACtD,GAAA,CAAI,mBAAA;AAAA,EACJ,CAAC,EAAE,IAAA,EAAM,IAAA,EAAM,IAAA,IAAQ,IAAA,KAAS;AAC9B,IAAA,MAAM,QAAA,GAAW,WAAA,CAAY,IAAA,CAAK,OAAO,CAAA;AAEzC,IAAA,MAAM,WAAW,IAAA,CAAK,QAAA;AACtB,IAAA,MAAM,iBAAA,GAAoB,WAAW,eAAe,CAAA;AAEpD,IAAA,MAAM,SAAA,GACJ,6BAA6B,SAAA,GACzB,iBAAA,GACA,oBACE,SAAA,CAAU,GAAA,CAAI,mBAAoC,IAAA,CAAK,OAAO,IAC9D,SAAA,CAAU,GAAA,CAAI,gBAAgB,EAAE,IAAA,EAAM,gBAAgB,OAAA,EAAS,IAAA,CAAK,SAAS,CAAA;AAErF,IAAA,OAAO,WAAA,CAAY,MAAA;AAAA,MACjB,IAAA;AAAA,MACA;AAAA,QACE,SAAA;AAAA,QAEA,YAAY,IAAA,CAAK,UAAA;AAAA,QACjB,UAAU,IAAA,CAAK,QAAA;AAAA,QACf,SAAA,EAAW;AAAA,UACT,MAAM,IAAA,CAAK,iBAAA;AAAA,UACX,IAAA,EAAM;AAAA,SACR;AAAA,QACA,UAAA,EAAY,kBAAkB,IAAI,CAAA;AAAA,OACpC;AAAA,MACA,EAAE,GAAG,IAAA,EAAM,QAAA;AAAS,KACtB;AAAA,EACF;AACF","file":"tls-certificate.js","sourcesContent":["import { tlsCertificateMediator } from \"@highstate/common\"\nimport { k8s } from \"@highstate/library\"\nimport { Namespace } from \"../namespace\"\nimport { getProvider } from \"../shared\"\nimport { Certificate } from \"../tls\"\n\nexport const createCertificate = tlsCertificateMediator.implement(\n k8s.tlsIssuerDataSchema,\n ({ name, spec, opts }, data) => {\n const provider = getProvider(data.cluster)\n\n const metadata = spec.metadata as Record<string, unknown> | undefined\n const metadataNamespace = metadata?.[\"k8s.namespace\"]\n\n const namespace =\n metadataNamespace instanceof Namespace\n ? metadataNamespace\n : metadataNamespace\n ? Namespace.for(metadataNamespace as k8s.Namespace, data.cluster)\n : Namespace.get(\"cert-manager\", { name: \"cert-manager\", cluster: data.cluster })\n\n return Certificate.create(\n name,\n {\n namespace,\n\n commonName: spec.commonName,\n dnsNames: spec.dnsNames,\n issuerRef: {\n name: data.clusterIssuerName,\n kind: \"ClusterIssuer\",\n },\n secretName: `hs-certificate-${name}`,\n },\n { ...opts, provider },\n )\n },\n)\n"]}
|
package/dist/index.js
CHANGED
|
@@ -1,30 +1,111 @@
|
|
|
1
|
-
export {
|
|
2
|
-
export {
|
|
3
|
-
export {
|
|
4
|
-
export {
|
|
5
|
-
export {
|
|
6
|
-
|
|
7
|
-
export {
|
|
1
|
+
export { Gateway, HttpRoute, TcpRoute, UdpRoute, mapHttpRouteRuleMatch, resolveBackendRef } from './chunk-P26SQ2ZB.js';
|
|
2
|
+
export { Certificate } from './chunk-IXE3OKB4.js';
|
|
3
|
+
export { Job } from './chunk-23X5SXQG.js';
|
|
4
|
+
export { CronJob } from './chunk-PG27ZY2H.js';
|
|
5
|
+
export { Chart, RenderedChart, getChartService, getChartServiceOutput, resolveHelmChart } from './chunk-TVKT3ZYX.js';
|
|
6
|
+
export { Deployment } from './chunk-BTAEFJ5N.js';
|
|
7
|
+
export { StatefulSet } from './chunk-S77TE7UC.js';
|
|
8
|
+
import { ConfigMap } from './chunk-SZKOAHNX.js';
|
|
9
|
+
export { ConfigMap, NativeNetworkPolicy, NetworkPolicy, PersistentVolumeClaim, Workload, filterPatchOwnedContainersInTemplate, getAutoVolumeName, getBestEndpoint, getFallbackContainerName, getWorkloadComponents, getWorkloadServiceComponents, getWorkloadVolumeResourceUuid, mapContainerEnvironment, mapContainerToRaw, mapEnvironmentSource, mapVolumeMount, mapWorkloadVolume, networkPolicyMediator, podSpecDefaults, requireBestEndpoint, workloadExtraArgs, workloadServiceExtraArgs } from './chunk-SZKOAHNX.js';
|
|
8
10
|
export { dns01SolverMediator } from './chunk-HH2JJELM.js';
|
|
9
|
-
|
|
10
|
-
export {
|
|
11
|
-
|
|
12
|
-
export {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
import { images_exports } from './chunk-OBDQONMV.js';
|
|
17
|
-
export { Namespace, NamespacedResource, Resource, commonExtraArgs, getNamespaceName, getProvider, getProviderAsync, images_exports as images, mapMetadata, mapNamespaceNameToSelector, mapSelectorLikeToSelector, validateCluster } from './chunk-OBDQONMV.js';
|
|
18
|
-
import './chunk-PZ5AY32C.js';
|
|
19
|
-
import { parseEndpoint } from '@highstate/common';
|
|
11
|
+
export { createK8sTerminal, detectExternalIps } from './chunk-ADHZK6V2.js';
|
|
12
|
+
export { Service, createServiceSpec, getServiceType, isEndpointFromCluster, l4EndpointToServicePort, mapContainerPortToServicePort, mapServiceToLabelSelector } from './chunk-OG2OPX7B.js';
|
|
13
|
+
import { images_exports, ClusterAccessScope, getClusterKubeconfigContent } from './chunk-TOLFVF4S.js';
|
|
14
|
+
export { ClusterAccessScope, Namespace, NamespacedResource, Resource, Secret, commonExtraArgs, getClusterKubeconfigContent, getEmbeddedSecretFileContent, getNamespaceName, getProvider, getProviderAsync, images_exports as images, mapMetadata, mapNamespaceNameToSelector, mapSelectorLikeToSelector, validateCluster } from './chunk-TOLFVF4S.js';
|
|
15
|
+
import './chunk-PZYGZSN5.js';
|
|
16
|
+
import { MaterializedFile, Command, parseEndpoint } from '@highstate/common';
|
|
17
|
+
import { ComponentResource, output } from '@pulumi/pulumi';
|
|
20
18
|
import { text, trimIndentation } from '@highstate/contract';
|
|
21
19
|
import { normalize } from '@highstate/pulumi';
|
|
22
|
-
import { ComponentResource, output } from '@pulumi/pulumi';
|
|
23
20
|
import { serializeFunction } from '@pulumi/pulumi/runtime/index.js';
|
|
24
21
|
import { deepmerge } from 'deepmerge-ts';
|
|
25
22
|
import { readPackageJSON } from 'pkg-types';
|
|
26
23
|
import { omitBy, mapValues, merge } from 'remeda';
|
|
27
24
|
|
|
25
|
+
function createCommand(command) {
|
|
26
|
+
if (Array.isArray(command)) {
|
|
27
|
+
return command.join(" ");
|
|
28
|
+
}
|
|
29
|
+
return command;
|
|
30
|
+
}
|
|
31
|
+
function buildKubeCommand(command, namespace) {
|
|
32
|
+
if (namespace) {
|
|
33
|
+
return output([command, namespace]).apply(
|
|
34
|
+
([cmd, ns]) => `kubectl -n ${ns} ${createCommand(cmd)}`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
return output(command).apply((cmd) => `kubectl ${createCommand(cmd)}`);
|
|
38
|
+
}
|
|
39
|
+
function buildWorkloadExecCommand(command, workload) {
|
|
40
|
+
return output({
|
|
41
|
+
command,
|
|
42
|
+
kind: output(workload).kind,
|
|
43
|
+
name: output(workload).metadata.name
|
|
44
|
+
}).apply(({ command: command2, kind, name }) => {
|
|
45
|
+
const type = kind.toLowerCase();
|
|
46
|
+
return `exec -it ${type}/${name} -- ${createCommand(command2)}`;
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
var KubeCommand = class _KubeCommand extends ComponentResource {
|
|
50
|
+
/**
|
|
51
|
+
* The underlying command that will be executed when this unit is invoked.
|
|
52
|
+
*/
|
|
53
|
+
command;
|
|
54
|
+
/**
|
|
55
|
+
* The standard output of the command.
|
|
56
|
+
*/
|
|
57
|
+
stdout;
|
|
58
|
+
/**
|
|
59
|
+
* The standard error of the command.
|
|
60
|
+
*/
|
|
61
|
+
stderr;
|
|
62
|
+
constructor(name, args, opts) {
|
|
63
|
+
super("highstate:k8s:KubeCommand", name, args, opts);
|
|
64
|
+
this.command = output(args.cluster).apply((cluster) => {
|
|
65
|
+
const kubeconfig = MaterializedFile.for(cluster.kubeconfig);
|
|
66
|
+
return new Command(`kubectl-${name}`, {
|
|
67
|
+
host: "local",
|
|
68
|
+
create: buildKubeCommand(args.create, args.namespace),
|
|
69
|
+
update: args.update ? buildKubeCommand(args.update, args.namespace) : void 0,
|
|
70
|
+
delete: args.delete ? buildKubeCommand(args.delete, args.namespace) : void 0,
|
|
71
|
+
files: [kubeconfig],
|
|
72
|
+
image: images_exports["terminal-kubectl"].image,
|
|
73
|
+
containerShell: "bash",
|
|
74
|
+
environment: {
|
|
75
|
+
KUBECONFIG: kubeconfig.path
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
this.stdout = this.command.stdout;
|
|
80
|
+
this.stderr = this.command.stderr;
|
|
81
|
+
}
|
|
82
|
+
static forNamespace(name, args, opts) {
|
|
83
|
+
return new _KubeCommand(
|
|
84
|
+
name,
|
|
85
|
+
{
|
|
86
|
+
cluster: output(args.namespace).cluster,
|
|
87
|
+
create: args.create,
|
|
88
|
+
update: args.update,
|
|
89
|
+
delete: args.delete,
|
|
90
|
+
namespace: output(args.namespace).metadata.name
|
|
91
|
+
},
|
|
92
|
+
opts
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
static execInto(name, args, opts) {
|
|
96
|
+
return _KubeCommand.forNamespace(
|
|
97
|
+
name,
|
|
98
|
+
{
|
|
99
|
+
namespace: output(args.workload).namespace,
|
|
100
|
+
create: buildWorkloadExecCommand(args.create, args.workload),
|
|
101
|
+
update: args.update ? buildWorkloadExecCommand(args.update, args.workload) : void 0,
|
|
102
|
+
delete: args.delete ? buildWorkloadExecCommand(args.delete, args.workload) : void 0
|
|
103
|
+
},
|
|
104
|
+
opts
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
28
109
|
// src/scripting/environment.ts
|
|
29
110
|
var emptyDistributionEnvironment = {
|
|
30
111
|
preInstallPackages: [],
|
|
@@ -34,7 +115,7 @@ var emptyDistributionEnvironment = {
|
|
|
34
115
|
var emptyScriptEnvironment = {
|
|
35
116
|
alpine: {
|
|
36
117
|
...emptyDistributionEnvironment,
|
|
37
|
-
image:
|
|
118
|
+
image: images_exports.alpine.image,
|
|
38
119
|
allowedEndpoints: [
|
|
39
120
|
//
|
|
40
121
|
"tcp://dl-cdn.alpinelinux.org:443",
|
|
@@ -43,7 +124,7 @@ var emptyScriptEnvironment = {
|
|
|
43
124
|
},
|
|
44
125
|
ubuntu: {
|
|
45
126
|
...emptyDistributionEnvironment,
|
|
46
|
-
image:
|
|
127
|
+
image: images_exports.ubuntu.image,
|
|
47
128
|
allowedEndpoints: [
|
|
48
129
|
//
|
|
49
130
|
"tcp://archive.ubuntu.com:80",
|
|
@@ -327,6 +408,8 @@ function createScriptContainer(options) {
|
|
|
327
408
|
async function createMonitorWorker(namespace, resources) {
|
|
328
409
|
const scope = new ClusterAccessScope("monitor", {
|
|
329
410
|
rule: {
|
|
411
|
+
apiGroups: ["", "apps"],
|
|
412
|
+
resources: ["deployments", "statefulsets", "services", "pods"],
|
|
330
413
|
verbs: ["get", "list", "watch"]
|
|
331
414
|
},
|
|
332
415
|
namespace,
|
|
@@ -336,12 +419,12 @@ async function createMonitorWorker(namespace, resources) {
|
|
|
336
419
|
name: "monitor",
|
|
337
420
|
image: images_exports["worker.k8s-monitor"].image,
|
|
338
421
|
params: {
|
|
339
|
-
kubeconfig: scope.cluster
|
|
422
|
+
kubeconfig: getClusterKubeconfigContent(scope.cluster),
|
|
340
423
|
resources: output(resources).apply((resources2) => resources2.map((r) => r.entity))
|
|
341
424
|
}
|
|
342
425
|
});
|
|
343
426
|
}
|
|
344
427
|
|
|
345
|
-
export { ScriptBundle, createMonitorWorker, createScriptContainer, emptyScriptEnvironment, functionScriptImages };
|
|
428
|
+
export { KubeCommand, ScriptBundle, createMonitorWorker, createScriptContainer, emptyScriptEnvironment, functionScriptImages };
|
|
346
429
|
//# sourceMappingURL=index.js.map
|
|
347
430
|
//# sourceMappingURL=index.js.map
|