@highstate/k8s 0.9.3 → 0.9.5
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-DQSCJM5S.js +183 -0
- package/dist/chunk-DQSCJM5S.js.map +1 -0
- package/dist/chunk-FKNHHKOL.js +260 -0
- package/dist/chunk-FKNHHKOL.js.map +1 -0
- package/dist/chunk-HW3NS3MC.js +347 -0
- package/dist/chunk-HW3NS3MC.js.map +1 -0
- package/dist/chunk-OQ7UXASD.js +193 -0
- package/dist/chunk-OQ7UXASD.js.map +1 -0
- package/dist/chunk-QGHMLKTW.js +1123 -0
- package/dist/chunk-QGHMLKTW.js.map +1 -0
- package/dist/chunk-UNVSWG6D.js +214 -0
- package/dist/chunk-UNVSWG6D.js.map +1 -0
- package/dist/deployment-ZP3ASKPT.js +10 -0
- package/dist/deployment-ZP3ASKPT.js.map +1 -0
- package/dist/highstate.manifest.json +8 -6
- package/dist/index.js +291 -954
- package/dist/index.js.map +1 -1
- package/dist/stateful-set-2AH7RAF7.js +10 -0
- package/dist/stateful-set-2AH7RAF7.js.map +1 -0
- package/dist/units/access-point/index.js +6 -1
- package/dist/units/access-point/index.js.map +1 -1
- package/dist/units/cert-manager/index.js +19 -24
- package/dist/units/cert-manager/index.js.map +1 -1
- package/dist/units/cluster-dns/index.js +36 -0
- package/dist/units/cluster-dns/index.js.map +1 -0
- package/dist/units/cluster-patch/index.js +34 -0
- package/dist/units/cluster-patch/index.js.map +1 -0
- package/dist/units/dns01-issuer/index.js +2 -2
- package/dist/units/dns01-issuer/index.js.map +1 -1
- package/dist/units/existing-cluster/index.js +23 -15
- package/dist/units/existing-cluster/index.js.map +1 -1
- package/dist/units/gateway-api/index.js +1 -1
- package/package.json +12 -10
- package/src/access-point.ts +44 -39
- package/src/container.ts +54 -5
- package/src/cron-job.ts +14 -30
- package/src/deployment.ts +170 -127
- package/src/gateway/http-route.ts +7 -5
- package/src/helm.ts +57 -8
- package/src/index.ts +11 -4
- package/src/job.ts +14 -32
- package/src/namespace.ts +241 -0
- package/src/network-policy.ts +371 -87
- package/src/network.ts +41 -0
- package/src/pvc.ts +43 -25
- package/src/scripting/bundle.ts +125 -22
- package/src/scripting/container.ts +16 -11
- package/src/scripting/environment.ts +56 -6
- package/src/secret.ts +195 -0
- package/src/service.ts +209 -89
- package/src/shared.ts +42 -51
- package/src/stateful-set.ts +193 -88
- package/src/units/access-point/index.ts +8 -1
- package/src/units/cert-manager/index.ts +15 -20
- package/src/units/cluster-dns/index.ts +37 -0
- package/src/units/cluster-patch/index.ts +35 -0
- package/src/units/dns01-issuer/index.ts +1 -1
- package/src/units/existing-cluster/index.ts +26 -15
- package/src/workload.ts +342 -44
- package/dist/chunk-K4WKJ4L5.js +0 -455
- package/dist/chunk-K4WKJ4L5.js.map +0 -1
- package/dist/chunk-T5Z2M4JE.js +0 -103
- package/dist/chunk-T5Z2M4JE.js.map +0 -1
@@ -0,0 +1,347 @@
|
|
1
|
+
import {
|
2
|
+
commonExtraArgs,
|
3
|
+
getProvider,
|
4
|
+
mapMetadata,
|
5
|
+
resourceIdToString
|
6
|
+
} from "./chunk-FKNHHKOL.js";
|
7
|
+
|
8
|
+
// src/service.ts
|
9
|
+
import { core } from "@pulumi/kubernetes";
|
10
|
+
import {
|
11
|
+
ComponentResource,
|
12
|
+
normalize,
|
13
|
+
output
|
14
|
+
} from "@highstate/pulumi";
|
15
|
+
import { omit, uniqueBy } from "remeda";
|
16
|
+
import { deepmerge } from "deepmerge-ts";
|
17
|
+
import { filterEndpoints, l4EndpointToString, parseL3Endpoint } from "@highstate/common";
|
18
|
+
var serviceExtraArgs = [...commonExtraArgs, "port", "ports", "external"];
|
19
|
+
function hasServiceMetadata(endpoint) {
|
20
|
+
return endpoint.metadata?.k8sService !== void 0;
|
21
|
+
}
|
22
|
+
function getServiceMetadata(endpoint) {
|
23
|
+
return endpoint.metadata?.k8sService;
|
24
|
+
}
|
25
|
+
function withServiceMetadata(endpoint, metadata) {
|
26
|
+
return {
|
27
|
+
...endpoint,
|
28
|
+
metadata: {
|
29
|
+
...endpoint.metadata,
|
30
|
+
k8sService: metadata
|
31
|
+
}
|
32
|
+
};
|
33
|
+
}
|
34
|
+
function isFromCluster(endpoint, cluster) {
|
35
|
+
return getServiceMetadata(endpoint)?.clusterId === cluster.id;
|
36
|
+
}
|
37
|
+
var Service = class extends ComponentResource {
|
38
|
+
constructor(type, name, args, opts, cluster, metadata, spec, status) {
|
39
|
+
super(type, name, args, opts);
|
40
|
+
this.cluster = cluster;
|
41
|
+
this.metadata = metadata;
|
42
|
+
this.spec = spec;
|
43
|
+
this.status = status;
|
44
|
+
}
|
45
|
+
/**
|
46
|
+
* The Highstate service entity.
|
47
|
+
*/
|
48
|
+
get entity() {
|
49
|
+
return output({
|
50
|
+
type: "k8s.service",
|
51
|
+
clusterId: this.cluster.id,
|
52
|
+
metadata: this.metadata,
|
53
|
+
endpoints: this.endpoints
|
54
|
+
});
|
55
|
+
}
|
56
|
+
static create(name, args, opts) {
|
57
|
+
return new CreatedService(name, args, opts);
|
58
|
+
}
|
59
|
+
static wrap(name, service, cluster, opts) {
|
60
|
+
return new WrappedService(name, service, cluster, opts);
|
61
|
+
}
|
62
|
+
static external(name, id, cluster, opts) {
|
63
|
+
return new ExternalService(name, id, cluster, opts);
|
64
|
+
}
|
65
|
+
static of(name, entity, cluster, opts) {
|
66
|
+
return new ExternalService(
|
67
|
+
name,
|
68
|
+
output(entity).metadata,
|
69
|
+
output({ cluster, entity }).apply(({ cluster: cluster2, entity: entity2 }) => {
|
70
|
+
if (cluster2.id !== entity2.clusterId) {
|
71
|
+
throw new Error(
|
72
|
+
`Cluster mismatch when wrapping service "${name}": "${cluster2.id}" != "${entity2.clusterId}"`
|
73
|
+
);
|
74
|
+
}
|
75
|
+
return cluster2;
|
76
|
+
}),
|
77
|
+
opts
|
78
|
+
);
|
79
|
+
}
|
80
|
+
/**
|
81
|
+
* Returns the endpoints of the service applying the given filter.
|
82
|
+
*
|
83
|
+
* If no filter is specified, the default behavior of `filterEndpoints` is used.
|
84
|
+
*
|
85
|
+
* @param filter If specified, the endpoints are filtered based on the given filter.
|
86
|
+
* @returns The endpoints of the service.
|
87
|
+
*/
|
88
|
+
filterEndpoints(filter) {
|
89
|
+
return output({ endpoints: this.endpoints }).apply(({ endpoints }) => {
|
90
|
+
return filterEndpoints(endpoints, filter);
|
91
|
+
});
|
92
|
+
}
|
93
|
+
/**
|
94
|
+
* Returns the endpoints of the service including both internal and external endpoints.
|
95
|
+
*/
|
96
|
+
get endpoints() {
|
97
|
+
return output({
|
98
|
+
clusterId: this.cluster.id,
|
99
|
+
metadata: this.metadata,
|
100
|
+
spec: this.spec,
|
101
|
+
status: this.status
|
102
|
+
}).apply(({ clusterId, metadata, spec, status }) => {
|
103
|
+
const endpointMetadata = {
|
104
|
+
k8sService: {
|
105
|
+
clusterId,
|
106
|
+
name: metadata.name,
|
107
|
+
namespace: metadata.namespace,
|
108
|
+
selector: spec.selector,
|
109
|
+
targetPort: spec.ports[0].targetPort ?? spec.ports[0].port
|
110
|
+
}
|
111
|
+
};
|
112
|
+
const clusterIpEndpoints = spec.clusterIPs?.map((ip) => ({
|
113
|
+
...parseL3Endpoint(ip),
|
114
|
+
port: spec.ports[0].port,
|
115
|
+
protocol: spec.ports[0].protocol?.toLowerCase(),
|
116
|
+
metadata: endpointMetadata
|
117
|
+
}));
|
118
|
+
if (clusterIpEndpoints.length > 0) {
|
119
|
+
clusterIpEndpoints.unshift({
|
120
|
+
type: "hostname",
|
121
|
+
visibility: "internal",
|
122
|
+
hostname: `${metadata.name}.${metadata.namespace}.svc.cluster.local`,
|
123
|
+
port: spec.ports[0].port,
|
124
|
+
protocol: spec.ports[0].protocol?.toLowerCase(),
|
125
|
+
metadata: endpointMetadata
|
126
|
+
});
|
127
|
+
}
|
128
|
+
const nodePortEndpoints = spec.type === "NodePort" ? spec.externalIPs?.map((ip) => ({
|
129
|
+
...parseL3Endpoint(ip),
|
130
|
+
port: spec.ports[0].nodePort,
|
131
|
+
protocol: spec.ports[0].protocol?.toLowerCase(),
|
132
|
+
metadata: endpointMetadata
|
133
|
+
})) : [];
|
134
|
+
const loadBalancerEndpoints = spec.type === "LoadBalancer" ? status.loadBalancer?.ingress?.map((endpoint) => ({
|
135
|
+
...parseL3Endpoint(endpoint.ip ?? endpoint.hostname),
|
136
|
+
port: spec.ports[0].port,
|
137
|
+
protocol: spec.ports[0].protocol?.toLowerCase(),
|
138
|
+
metadata: endpointMetadata
|
139
|
+
})) : [];
|
140
|
+
return uniqueBy(
|
141
|
+
[
|
142
|
+
...clusterIpEndpoints ?? [],
|
143
|
+
...loadBalancerEndpoints ?? [],
|
144
|
+
...nodePortEndpoints ?? []
|
145
|
+
],
|
146
|
+
(endpoint) => l4EndpointToString(endpoint)
|
147
|
+
);
|
148
|
+
});
|
149
|
+
}
|
150
|
+
};
|
151
|
+
var CreatedService = class extends Service {
|
152
|
+
constructor(name, args, opts) {
|
153
|
+
const service = output(args).apply((args2) => {
|
154
|
+
return new core.v1.Service(
|
155
|
+
name,
|
156
|
+
{
|
157
|
+
metadata: mapMetadata(args2, name),
|
158
|
+
spec: deepmerge(
|
159
|
+
{
|
160
|
+
ports: normalize(args2.port, args2.ports),
|
161
|
+
externalIPs: args2.external ? args2.externalIPs ?? args2.cluster.externalIps : args2.cluster.externalIps,
|
162
|
+
type: getServiceType(args2, args2.cluster)
|
163
|
+
},
|
164
|
+
omit(args2, serviceExtraArgs)
|
165
|
+
)
|
166
|
+
},
|
167
|
+
{ parent: this, ...opts }
|
168
|
+
);
|
169
|
+
});
|
170
|
+
super(
|
171
|
+
"highstate:k8s:Service",
|
172
|
+
name,
|
173
|
+
args,
|
174
|
+
opts,
|
175
|
+
output(args.cluster),
|
176
|
+
service.metadata,
|
177
|
+
service.spec,
|
178
|
+
service.status
|
179
|
+
);
|
180
|
+
}
|
181
|
+
};
|
182
|
+
var WrappedService = class extends Service {
|
183
|
+
constructor(name, service, cluster, opts) {
|
184
|
+
super(
|
185
|
+
"highstate:k8s:WrappedService",
|
186
|
+
name,
|
187
|
+
{ service, clusterInfo: cluster },
|
188
|
+
opts,
|
189
|
+
output(cluster),
|
190
|
+
output(service).metadata,
|
191
|
+
output(service).spec,
|
192
|
+
output(service).status
|
193
|
+
);
|
194
|
+
}
|
195
|
+
};
|
196
|
+
var ExternalService = class extends Service {
|
197
|
+
constructor(name, id, cluster, opts) {
|
198
|
+
const service = output(id).apply((id2) => {
|
199
|
+
return core.v1.Service.get(
|
200
|
+
//
|
201
|
+
name,
|
202
|
+
resourceIdToString(id2),
|
203
|
+
{ ...opts, parent: this }
|
204
|
+
);
|
205
|
+
});
|
206
|
+
super(
|
207
|
+
"highstate:k8s:ExternalService",
|
208
|
+
name,
|
209
|
+
{ id, cluster },
|
210
|
+
opts,
|
211
|
+
output(cluster),
|
212
|
+
service.metadata,
|
213
|
+
service.spec,
|
214
|
+
service.status
|
215
|
+
);
|
216
|
+
}
|
217
|
+
};
|
218
|
+
function mapContainerPortToServicePort(port) {
|
219
|
+
return {
|
220
|
+
name: port.name,
|
221
|
+
port: port.containerPort,
|
222
|
+
targetPort: port.containerPort,
|
223
|
+
protocol: port.protocol
|
224
|
+
};
|
225
|
+
}
|
226
|
+
function mapServiceToLabelSelector(service) {
|
227
|
+
return {
|
228
|
+
matchLabels: service.spec.selector
|
229
|
+
};
|
230
|
+
}
|
231
|
+
function getServiceType(service, cluster) {
|
232
|
+
if (service?.type) {
|
233
|
+
return service.type;
|
234
|
+
}
|
235
|
+
if (!service?.external) {
|
236
|
+
return "ClusterIP";
|
237
|
+
}
|
238
|
+
return cluster.quirks?.externalServiceType === "LoadBalancer" ? "LoadBalancer" : "NodePort";
|
239
|
+
}
|
240
|
+
|
241
|
+
// src/gateway/http-route.ts
|
242
|
+
import {
|
243
|
+
ComponentResource as ComponentResource2,
|
244
|
+
normalize as normalize2,
|
245
|
+
output as output3
|
246
|
+
} from "@highstate/pulumi";
|
247
|
+
import { gateway } from "@highstate/gateway-api";
|
248
|
+
import { map, pipe } from "remeda";
|
249
|
+
|
250
|
+
// src/gateway/backend.ts
|
251
|
+
import "@pulumi/kubernetes";
|
252
|
+
import { output as output2 } from "@highstate/pulumi";
|
253
|
+
function resolveBackendRef(ref) {
|
254
|
+
if (Service.isInstance(ref)) {
|
255
|
+
return output2({
|
256
|
+
name: ref.metadata.name,
|
257
|
+
namespace: ref.metadata.namespace,
|
258
|
+
port: ref.spec.ports[0].port
|
259
|
+
});
|
260
|
+
}
|
261
|
+
if ("service" in ref) {
|
262
|
+
const service = output2(ref.service);
|
263
|
+
return output2({
|
264
|
+
name: service.metadata.name,
|
265
|
+
namespace: service.metadata.namespace,
|
266
|
+
port: ref.port
|
267
|
+
});
|
268
|
+
}
|
269
|
+
return output2({
|
270
|
+
name: ref.name,
|
271
|
+
namespace: ref.namespace,
|
272
|
+
port: ref.port
|
273
|
+
});
|
274
|
+
}
|
275
|
+
|
276
|
+
// src/gateway/http-route.ts
|
277
|
+
var HttpRoute = class extends ComponentResource2 {
|
278
|
+
/**
|
279
|
+
* The underlying Kubernetes resource.
|
280
|
+
*/
|
281
|
+
route;
|
282
|
+
constructor(name, args, opts) {
|
283
|
+
super("highstate:k8s:HttpRoute", name, args, opts);
|
284
|
+
this.route = output3({
|
285
|
+
args,
|
286
|
+
gatewayNamespace: output3(args.gateway).metadata.namespace
|
287
|
+
}).apply(async ({ args: args2, gatewayNamespace }) => {
|
288
|
+
return new gateway.v1.HTTPRoute(
|
289
|
+
name,
|
290
|
+
{
|
291
|
+
metadata: mapMetadata(
|
292
|
+
{
|
293
|
+
...args2,
|
294
|
+
namespace: gatewayNamespace
|
295
|
+
},
|
296
|
+
name
|
297
|
+
),
|
298
|
+
spec: {
|
299
|
+
hostnames: normalize2(args2.hostname, args2.hostnames),
|
300
|
+
parentRefs: [
|
301
|
+
{
|
302
|
+
name: args2.gateway.metadata.name
|
303
|
+
}
|
304
|
+
],
|
305
|
+
rules: normalize2(args2.rule, args2.rules).map((rule) => ({
|
306
|
+
timeouts: rule.timeouts,
|
307
|
+
matches: pipe(
|
308
|
+
normalize2(rule.match, rule.matches),
|
309
|
+
map(mapHttpRouteRuleMatch),
|
310
|
+
addDefaultPathMatch
|
311
|
+
),
|
312
|
+
filters: normalize2(rule.filter, rule.filters),
|
313
|
+
backendRefs: rule.backend ? [resolveBackendRef(rule.backend)] : void 0
|
314
|
+
}))
|
315
|
+
}
|
316
|
+
},
|
317
|
+
{
|
318
|
+
...opts,
|
319
|
+
parent: this,
|
320
|
+
provider: await getProvider(args2.cluster)
|
321
|
+
}
|
322
|
+
);
|
323
|
+
});
|
324
|
+
}
|
325
|
+
};
|
326
|
+
function addDefaultPathMatch(matches) {
|
327
|
+
return matches.length ? matches : [{ path: { type: "PathPrefix", value: "/" } }];
|
328
|
+
}
|
329
|
+
function mapHttpRouteRuleMatch(match) {
|
330
|
+
if (typeof match === "string") {
|
331
|
+
return { path: { type: "PathPrefix", value: match } };
|
332
|
+
}
|
333
|
+
return match;
|
334
|
+
}
|
335
|
+
|
336
|
+
export {
|
337
|
+
hasServiceMetadata,
|
338
|
+
getServiceMetadata,
|
339
|
+
withServiceMetadata,
|
340
|
+
isFromCluster,
|
341
|
+
Service,
|
342
|
+
mapContainerPortToServicePort,
|
343
|
+
mapServiceToLabelSelector,
|
344
|
+
getServiceType,
|
345
|
+
HttpRoute
|
346
|
+
};
|
347
|
+
//# sourceMappingURL=chunk-HW3NS3MC.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../src/service.ts","../src/gateway/http-route.ts","../src/gateway/backend.ts"],"sourcesContent":["import type { k8s, network } from \"@highstate/library\"\nimport { core, types } from \"@pulumi/kubernetes\"\nimport {\n ComponentResource,\n normalize,\n output,\n Output,\n type ComponentResourceOptions,\n type Input,\n type Inputs,\n} from \"@highstate/pulumi\"\nimport { omit, uniqueBy } from \"remeda\"\nimport { deepmerge } from \"deepmerge-ts\"\nimport { filterEndpoints, l4EndpointToString, parseL3Endpoint } from \"@highstate/common\"\nimport {\n commonExtraArgs,\n mapMetadata,\n resourceIdToString,\n type CommonArgs,\n type ResourceId,\n type SelectorLike,\n} from \"./shared\"\n\nexport type ServiceArgs = CommonArgs & {\n /**\n * The port to expose the service on.\n */\n port?: Input<types.input.core.v1.ServicePort>\n\n /**\n * Whether the service should be exposed by `NodePort` or `LoadBalancer`.\n *\n * The type of the service will be determined automatically based on the cluster.\n */\n external?: boolean\n} & types.input.core.v1.ServiceSpec\n\nconst serviceExtraArgs = [...commonExtraArgs, \"port\", \"ports\", \"external\"] as const\n\nexport type ServiceEndpointMetadata = {\n clusterId: string\n name: string\n namespace: string\n selector: SelectorLike\n targetPort: string | number\n}\n\n/**\n * Checks if the endpoint has service metadata.\n *\n * Alters the type of the endpoint to include the service metadata if it exists.\n *\n * @param endpoint The endpoint to check.\n * @returns True if the endpoint has service metadata, false otherwise.\n */\nexport function hasServiceMetadata(\n endpoint: network.L3Endpoint,\n): endpoint is network.L3Endpoint & { metadata: { k8sService: ServiceEndpointMetadata } } {\n return endpoint.metadata?.k8sService !== undefined\n}\n\n/**\n * Returns the service metadata of the endpoint.\n *\n * @param endpoint The endpoint to get the service metadata from.\n * @returns The service metadata of the endpoint, or undefined if it doesn't exist.\n */\nexport function getServiceMetadata(\n endpoint: network.L3Endpoint,\n): ServiceEndpointMetadata | undefined {\n return endpoint.metadata?.k8sService as ServiceEndpointMetadata\n}\n\n/**\n * Adds service metadata to the endpoint.\n *\n * @param endpoint The endpoint to add the metadata to.\n * @param metadata The metadata to add.\n * @returns The endpoint with the added metadata.\n */\nexport function withServiceMetadata<TEdnpoint extends network.L34Endpoint>(\n endpoint: TEdnpoint,\n metadata: ServiceEndpointMetadata,\n): TEdnpoint & { metadata: { k8sService: ServiceEndpointMetadata } } {\n return {\n ...endpoint,\n metadata: {\n ...endpoint.metadata,\n k8sService: metadata,\n },\n }\n}\n\n/**\n * Checks if the endpoint is from the given cluster.\n *\n * @param endpoint The endpoint to check.\n * @param cluster The cluster to check against.\n * @returns True if the endpoint is from the cluster, false otherwise.\n */\nexport function isFromCluster(\n endpoint: network.L3Endpoint,\n cluster: k8s.Cluster,\n): endpoint is network.L3Endpoint & { metadata: { k8sService: ServiceEndpointMetadata } } {\n return getServiceMetadata(endpoint)?.clusterId === cluster.id\n}\n\nexport abstract class Service extends ComponentResource {\n protected constructor(\n type: string,\n name: string,\n args: Inputs,\n opts: ComponentResourceOptions,\n\n /**\n * The cluster info associated with the service.\n */\n readonly cluster: Output<k8s.Cluster>,\n\n /**\n * The metadata of the underlying Kubernetes service.\n */\n readonly metadata: Output<types.output.meta.v1.ObjectMeta>,\n\n /**\n * The spec of the underlying Kubernetes service.\n */\n readonly spec: Output<types.output.core.v1.ServiceSpec>,\n\n /**\n * The status of the underlying Kubernetes service.\n */\n readonly status: Output<types.output.core.v1.ServiceStatus>,\n ) {\n super(type, name, args, opts)\n }\n\n /**\n * The Highstate service entity.\n */\n get entity(): Output<k8s.Service> {\n return output({\n type: \"k8s.service\",\n clusterId: this.cluster.id,\n metadata: this.metadata,\n endpoints: this.endpoints,\n })\n }\n\n static create(name: string, args: ServiceArgs, opts: ComponentResourceOptions): Service {\n return new CreatedService(name, args, opts)\n }\n\n static wrap(\n name: string,\n service: Input<core.v1.Service>,\n cluster: Input<k8s.Cluster>,\n opts: ComponentResourceOptions,\n ): Service {\n return new WrappedService(name, service, cluster, opts)\n }\n\n static external(\n name: string,\n id: ResourceId,\n cluster: Input<k8s.Cluster>,\n opts: ComponentResourceOptions,\n ): Service {\n return new ExternalService(name, id, cluster, opts)\n }\n\n static of(\n name: string,\n entity: Input<k8s.Service>,\n cluster: Input<k8s.Cluster>,\n opts: ComponentResourceOptions,\n ): Service {\n return new ExternalService(\n name,\n output(entity).metadata,\n output({ cluster, entity }).apply(({ cluster, entity }) => {\n if (cluster.id !== entity.clusterId) {\n throw new Error(\n `Cluster mismatch when wrapping service \"${name}\": \"${cluster.id}\" != \"${entity.clusterId}\"`,\n )\n }\n\n return cluster\n }),\n opts,\n )\n }\n\n /**\n * Returns the endpoints of the service applying the given filter.\n *\n * If no filter is specified, the default behavior of `filterEndpoints` is used.\n *\n * @param filter If specified, the endpoints are filtered based on the given filter.\n * @returns The endpoints of the service.\n */\n filterEndpoints(filter?: network.EndpointFilter): Output<network.L4Endpoint[]> {\n return output({ endpoints: this.endpoints }).apply(({ endpoints }) => {\n return filterEndpoints(endpoints, filter)\n })\n }\n\n /**\n * Returns the endpoints of the service including both internal and external endpoints.\n */\n get endpoints(): Output<network.L4Endpoint[]> {\n return output({\n clusterId: this.cluster.id,\n metadata: this.metadata,\n spec: this.spec,\n status: this.status,\n }).apply(({ clusterId, metadata, spec, status }) => {\n const endpointMetadata = {\n k8sService: {\n clusterId,\n name: metadata.name,\n namespace: metadata.namespace,\n selector: spec.selector,\n targetPort: spec.ports[0].targetPort ?? spec.ports[0].port,\n },\n }\n\n const clusterIpEndpoints = spec.clusterIPs?.map(ip => ({\n ...parseL3Endpoint(ip),\n port: spec.ports[0].port,\n protocol: spec.ports[0].protocol?.toLowerCase() as network.L4Protocol,\n metadata: endpointMetadata,\n }))\n\n if (clusterIpEndpoints.length > 0) {\n clusterIpEndpoints.unshift({\n type: \"hostname\",\n visibility: \"internal\",\n hostname: `${metadata.name}.${metadata.namespace}.svc.cluster.local`,\n port: spec.ports[0].port,\n protocol: spec.ports[0].protocol?.toLowerCase() as network.L4Protocol,\n metadata: endpointMetadata,\n })\n }\n\n const nodePortEndpoints =\n spec.type === \"NodePort\"\n ? spec.externalIPs?.map(ip => ({\n ...parseL3Endpoint(ip),\n port: spec.ports[0].nodePort,\n protocol: spec.ports[0].protocol?.toLowerCase() as network.L4Protocol,\n metadata: endpointMetadata,\n }))\n : []\n\n const loadBalancerEndpoints =\n spec.type === \"LoadBalancer\"\n ? status.loadBalancer?.ingress?.map(endpoint => ({\n ...parseL3Endpoint(endpoint.ip ?? endpoint.hostname),\n port: spec.ports[0].port,\n protocol: spec.ports[0].protocol?.toLowerCase() as network.L4Protocol,\n metadata: endpointMetadata,\n }))\n : []\n\n return uniqueBy(\n [\n ...(clusterIpEndpoints ?? []),\n ...(loadBalancerEndpoints ?? []),\n ...(nodePortEndpoints ?? []),\n ],\n endpoint => l4EndpointToString(endpoint),\n )\n })\n }\n}\n\nclass CreatedService extends Service {\n constructor(name: string, args: ServiceArgs, opts: ComponentResourceOptions) {\n const service = output(args).apply(args => {\n return new core.v1.Service(\n name,\n {\n metadata: mapMetadata(args, name),\n spec: deepmerge(\n {\n ports: normalize(args.port, args.ports),\n\n externalIPs: args.external\n ? (args.externalIPs ?? args.cluster.externalIps)\n : args.cluster.externalIps,\n\n type: getServiceType(args, args.cluster),\n },\n omit(args, serviceExtraArgs),\n ),\n },\n { parent: this, ...opts },\n )\n })\n\n super(\n \"highstate:k8s:Service\",\n name,\n args,\n opts,\n\n output(args.cluster),\n service.metadata,\n service.spec,\n service.status,\n )\n }\n}\n\nclass WrappedService extends Service {\n constructor(\n name: string,\n service: Input<core.v1.Service>,\n cluster: Input<k8s.Cluster>,\n opts: ComponentResourceOptions,\n ) {\n super(\n \"highstate:k8s:WrappedService\",\n name,\n { service, clusterInfo: cluster },\n opts,\n\n output(cluster),\n output(service).metadata,\n output(service).spec,\n output(service).status,\n )\n }\n}\n\nclass ExternalService extends Service {\n constructor(\n name: string,\n id: Input<ResourceId>,\n cluster: Input<k8s.Cluster>,\n opts: ComponentResourceOptions,\n ) {\n const service = output(id).apply(id => {\n return core.v1.Service.get(\n //\n name,\n resourceIdToString(id),\n { ...opts, parent: this },\n )\n })\n\n super(\n \"highstate:k8s:ExternalService\",\n name,\n { id, cluster },\n opts,\n\n output(cluster),\n service.metadata,\n service.spec,\n service.status,\n )\n }\n}\n\nexport function mapContainerPortToServicePort(\n port: types.input.core.v1.ContainerPort,\n): types.input.core.v1.ServicePort {\n return {\n name: port.name,\n port: port.containerPort,\n targetPort: port.containerPort,\n protocol: port.protocol,\n }\n}\n\nexport function mapServiceToLabelSelector(\n service: core.v1.Service,\n): types.input.meta.v1.LabelSelector {\n return {\n matchLabels: service.spec.selector,\n }\n}\n\nexport function getServiceType(\n service: Pick<ServiceArgs, \"type\" | \"external\"> | undefined,\n cluster: k8s.Cluster,\n): Input<string> {\n if (service?.type) {\n return service.type\n }\n\n if (!service?.external) {\n return \"ClusterIP\"\n }\n\n return cluster.quirks?.externalServiceType === \"LoadBalancer\" ? \"LoadBalancer\" : \"NodePort\"\n}\n","import {\n ComponentResource,\n normalize,\n output,\n Output,\n type ComponentResourceOptions,\n type Input,\n type InputArray,\n} from \"@highstate/pulumi\"\nimport { gateway, types } from \"@highstate/gateway-api\"\nimport { map, pipe } from \"remeda\"\nimport { getProvider, mapMetadata, type CommonArgs } from \"../shared\"\nimport { resolveBackendRef, type BackendRef } from \"./backend\"\n\nexport type HttpRouteArgs = Omit<CommonArgs, \"namespace\"> & {\n /**\n * The gateway to associate with the route.\n */\n gateway: Input<gateway.v1.Gateway>\n\n /**\n * The alias for `hostnames: [hostname]`.\n */\n hostname?: Input<string>\n\n /**\n * The rule of the route.\n */\n rule?: Input<HttpRouteRuleArgs>\n\n /**\n * The rules of the route.\n */\n rules?: InputArray<HttpRouteRuleArgs>\n} & Omit<Partial<types.input.gateway.v1.HTTPRouteSpec>, \"rules\">\n\nexport type HttpRouteRuleArgs = Omit<\n types.input.gateway.v1.HTTPRouteSpecRules,\n \"matches\" | \"filters\" | \"backendRefs\"\n> & {\n /**\n * The conditions of the rule.\n * Can be specified as string to match on the path.\n */\n matches?: InputArray<HttpRouteRuleMatchOptions>\n\n /**\n * The condition of the rule.\n * Can be specified as string to match on the path.\n */\n match?: Input<HttpRouteRuleMatchOptions>\n\n /**\n * The filters of the rule.\n */\n filters?: InputArray<types.input.gateway.v1.HTTPRouteSpecRulesFilters>\n\n /**\n * The filter of the rule.\n */\n filter?: Input<types.input.gateway.v1.HTTPRouteSpecRulesFilters>\n\n /**\n * The service to route to.\n */\n backend?: Input<BackendRef>\n}\n\nexport type HttpRouteRuleMatchOptions = types.input.gateway.v1.HTTPRouteSpecRulesMatches | string\n\nexport class HttpRoute extends ComponentResource {\n /**\n * The underlying Kubernetes resource.\n */\n public readonly route: Output<gateway.v1.HTTPRoute>\n\n constructor(name: string, args: HttpRouteArgs, opts?: ComponentResourceOptions) {\n super(\"highstate:k8s:HttpRoute\", name, args, opts)\n\n this.route = output({\n args,\n gatewayNamespace: output(args.gateway).metadata.namespace,\n }).apply(async ({ args, gatewayNamespace }) => {\n return new gateway.v1.HTTPRoute(\n name,\n {\n metadata: mapMetadata(\n {\n ...args,\n namespace: gatewayNamespace as string,\n },\n name,\n ),\n spec: {\n hostnames: normalize(args.hostname, args.hostnames),\n\n parentRefs: [\n {\n name: args.gateway.metadata.name as Output<string>,\n },\n ],\n\n rules: normalize(args.rule, args.rules).map(rule => ({\n timeouts: rule.timeouts,\n\n matches: pipe(\n normalize(rule.match, rule.matches),\n map(mapHttpRouteRuleMatch),\n addDefaultPathMatch,\n ),\n\n filters: normalize(rule.filter, rule.filters),\n backendRefs: rule.backend ? [resolveBackendRef(rule.backend)] : undefined,\n })),\n } satisfies types.input.gateway.v1.HTTPRouteSpec,\n },\n {\n ...opts,\n parent: this,\n provider: await getProvider(args.cluster),\n },\n )\n })\n }\n}\n\nfunction addDefaultPathMatch(\n matches: types.input.gateway.v1.HTTPRouteSpecRulesMatches[],\n): types.input.gateway.v1.HTTPRouteSpecRulesMatches[] {\n return matches.length ? matches : [{ path: { type: \"PathPrefix\", value: \"/\" } }]\n}\n\nexport function mapHttpRouteRuleMatch(\n match: HttpRouteRuleMatchOptions,\n): types.input.gateway.v1.HTTPRouteSpecRulesMatches {\n if (typeof match === \"string\") {\n return { path: { type: \"PathPrefix\", value: match } }\n }\n\n return match\n}\n","import { core } from \"@pulumi/kubernetes\"\nimport { type Input, output, Output, type Unwrap } from \"@highstate/pulumi\"\nimport { Service } from \"../service\"\n\nexport interface FullBackendRef {\n /**\n * The name of the resource being referenced.\n */\n name: Input<string>\n\n /**\n * The namespace of the resource being referenced.\n * May be undefined if the resource is not in a namespace.\n */\n namespace?: Input<string | undefined>\n\n /**\n * The port of the resource being referenced.\n */\n port: Input<number>\n}\n\nexport interface ServiceBackendRef {\n /**\n * The name of the service being referenced.\n */\n service: Input<core.v1.Service>\n\n /**\n * The port of the service being referenced.\n */\n port: Input<number>\n}\n\nexport type BackendRef = FullBackendRef | ServiceBackendRef | Service\n\nexport function resolveBackendRef(ref: BackendRef): Output<Unwrap<FullBackendRef>> {\n if (Service.isInstance(ref)) {\n return output({\n name: ref.metadata.name,\n namespace: ref.metadata.namespace,\n port: ref.spec.ports[0].port,\n })\n }\n\n if (\"service\" in ref) {\n const service = output(ref.service)\n\n return output({\n name: service.metadata.name,\n namespace: service.metadata.namespace,\n port: ref.port,\n })\n }\n\n return output({\n name: ref.name,\n namespace: ref.namespace,\n port: ref.port,\n })\n}\n"],"mappings":"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","names":["cluster","entity","args","id","ComponentResource","normalize","output","output","output","ComponentResource","output","args","normalize"]}
|
@@ -0,0 +1,193 @@
|
|
1
|
+
import {
|
2
|
+
ExposableWorkload,
|
3
|
+
exposableWorkloadExtraArgs,
|
4
|
+
getExposableWorkloadComponents
|
5
|
+
} from "./chunk-QGHMLKTW.js";
|
6
|
+
import {
|
7
|
+
getProvider,
|
8
|
+
mapMetadata,
|
9
|
+
resourceIdToString,
|
10
|
+
withPatchName
|
11
|
+
} from "./chunk-FKNHHKOL.js";
|
12
|
+
|
13
|
+
// src/stateful-set.ts
|
14
|
+
import { output } from "@highstate/pulumi";
|
15
|
+
import { apps } from "@pulumi/kubernetes";
|
16
|
+
import { omit } from "remeda";
|
17
|
+
import { deepmerge } from "deepmerge-ts";
|
18
|
+
var StatefulSet = class extends ExposableWorkload {
|
19
|
+
constructor(type, name, args, opts, cluster, metadata, spec, status, networkPolicy, service, httpRoute) {
|
20
|
+
super(
|
21
|
+
type,
|
22
|
+
name,
|
23
|
+
args,
|
24
|
+
opts,
|
25
|
+
"statefulset",
|
26
|
+
cluster,
|
27
|
+
metadata,
|
28
|
+
networkPolicy,
|
29
|
+
service,
|
30
|
+
httpRoute
|
31
|
+
);
|
32
|
+
this.spec = spec;
|
33
|
+
this.status = status;
|
34
|
+
}
|
35
|
+
/**
|
36
|
+
* The Highstate stateful set entity.
|
37
|
+
*/
|
38
|
+
get entity() {
|
39
|
+
return output({
|
40
|
+
type: "k8s.stateful-set",
|
41
|
+
clusterId: this.cluster.id,
|
42
|
+
metadata: this.metadata,
|
43
|
+
service: this.service.entity
|
44
|
+
});
|
45
|
+
}
|
46
|
+
static create(name, args, opts) {
|
47
|
+
return new CreatedStatefulSet(name, args, opts);
|
48
|
+
}
|
49
|
+
static createOrPatch(name, args, opts) {
|
50
|
+
if (!args.existing) {
|
51
|
+
return new CreatedStatefulSet(name, args, opts);
|
52
|
+
}
|
53
|
+
return new StatefulSetPatch(
|
54
|
+
name,
|
55
|
+
{
|
56
|
+
...args,
|
57
|
+
name: withPatchName("stateful set", args.existing, args.cluster),
|
58
|
+
namespace: output(args.existing).metadata.namespace
|
59
|
+
},
|
60
|
+
opts
|
61
|
+
);
|
62
|
+
}
|
63
|
+
static patch(name, args, opts) {
|
64
|
+
return new StatefulSetPatch(name, args, opts);
|
65
|
+
}
|
66
|
+
static createOrGet(name, args, opts) {
|
67
|
+
if (!args.existing) {
|
68
|
+
return new CreatedStatefulSet(name, args, opts);
|
69
|
+
}
|
70
|
+
return new ExternalStatefulSet(name, output(args.existing).metadata, args.cluster, opts);
|
71
|
+
}
|
72
|
+
};
|
73
|
+
var CreatedStatefulSet = class extends StatefulSet {
|
74
|
+
constructor(name, args, opts) {
|
75
|
+
const { labels, podTemplate, networkPolicy, service, httpRoute } = getExposableWorkloadComponents(
|
76
|
+
name,
|
77
|
+
{
|
78
|
+
...args,
|
79
|
+
// force create a service since it is required for stateful sets
|
80
|
+
service: output(args.service).apply((service2) => ({ ...service2 }))
|
81
|
+
},
|
82
|
+
() => this,
|
83
|
+
opts
|
84
|
+
);
|
85
|
+
const statefulSet = output({ args, podTemplate }).apply(async ({ args: args2, podTemplate: podTemplate2 }) => {
|
86
|
+
return new apps.v1.StatefulSet(
|
87
|
+
name,
|
88
|
+
{
|
89
|
+
metadata: mapMetadata(args2, name),
|
90
|
+
spec: deepmerge(
|
91
|
+
{
|
92
|
+
serviceName: service.apply((service2) => service2.metadata.name),
|
93
|
+
template: podTemplate2,
|
94
|
+
selector: { matchLabels: labels }
|
95
|
+
},
|
96
|
+
omit(args2, exposableWorkloadExtraArgs)
|
97
|
+
)
|
98
|
+
},
|
99
|
+
{
|
100
|
+
...opts,
|
101
|
+
parent: this,
|
102
|
+
provider: await getProvider(args2.cluster)
|
103
|
+
}
|
104
|
+
);
|
105
|
+
});
|
106
|
+
super(
|
107
|
+
"highstate:k8s:StatefulSet",
|
108
|
+
name,
|
109
|
+
args,
|
110
|
+
opts,
|
111
|
+
output(args.cluster),
|
112
|
+
statefulSet.metadata,
|
113
|
+
statefulSet.spec,
|
114
|
+
statefulSet.status,
|
115
|
+
networkPolicy,
|
116
|
+
service,
|
117
|
+
httpRoute
|
118
|
+
);
|
119
|
+
}
|
120
|
+
};
|
121
|
+
var StatefulSetPatch = class extends StatefulSet {
|
122
|
+
constructor(name, args, opts) {
|
123
|
+
const { podSpec, networkPolicy, service, httpRoute } = getExposableWorkloadComponents(
|
124
|
+
name,
|
125
|
+
args,
|
126
|
+
() => this,
|
127
|
+
opts
|
128
|
+
);
|
129
|
+
const statefulSet = output({ args, podSpec }).apply(async ({ args: args2, podSpec: podSpec2 }) => {
|
130
|
+
return new apps.v1.StatefulSetPatch(
|
131
|
+
name,
|
132
|
+
{
|
133
|
+
metadata: mapMetadata(args2, name),
|
134
|
+
spec: deepmerge(
|
135
|
+
{
|
136
|
+
template: {
|
137
|
+
spec: podSpec2
|
138
|
+
}
|
139
|
+
},
|
140
|
+
omit(args2, exposableWorkloadExtraArgs)
|
141
|
+
)
|
142
|
+
},
|
143
|
+
{
|
144
|
+
...opts,
|
145
|
+
parent: this,
|
146
|
+
provider: await getProvider(args2.cluster)
|
147
|
+
}
|
148
|
+
);
|
149
|
+
});
|
150
|
+
super(
|
151
|
+
"highstate:k8s:StatefulSetPatch",
|
152
|
+
name,
|
153
|
+
args,
|
154
|
+
opts,
|
155
|
+
output(args.cluster),
|
156
|
+
statefulSet.metadata,
|
157
|
+
statefulSet.spec,
|
158
|
+
statefulSet.status,
|
159
|
+
networkPolicy,
|
160
|
+
service,
|
161
|
+
httpRoute
|
162
|
+
);
|
163
|
+
}
|
164
|
+
};
|
165
|
+
var ExternalStatefulSet = class extends StatefulSet {
|
166
|
+
constructor(name, id, cluster, opts) {
|
167
|
+
const statefulSet = output(id).apply(async (id2) => {
|
168
|
+
return apps.v1.StatefulSet.get(name, resourceIdToString(id2), {
|
169
|
+
...opts,
|
170
|
+
parent: this,
|
171
|
+
provider: await getProvider(cluster)
|
172
|
+
});
|
173
|
+
});
|
174
|
+
super(
|
175
|
+
"highstate:k8s:ExternalStatefulSet",
|
176
|
+
name,
|
177
|
+
{ namespace: output(id).namespace, cluster },
|
178
|
+
opts,
|
179
|
+
output(cluster),
|
180
|
+
statefulSet.metadata,
|
181
|
+
statefulSet.spec,
|
182
|
+
statefulSet.status,
|
183
|
+
output(void 0),
|
184
|
+
output(void 0),
|
185
|
+
output(void 0)
|
186
|
+
);
|
187
|
+
}
|
188
|
+
};
|
189
|
+
|
190
|
+
export {
|
191
|
+
StatefulSet
|
192
|
+
};
|
193
|
+
//# sourceMappingURL=chunk-OQ7UXASD.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"sources":["../src/stateful-set.ts"],"sourcesContent":["import type { k8s } from \"@highstate/library\"\nimport type { HttpRoute } from \"./gateway\"\nimport type { Service } from \"./service\"\nimport type { NetworkPolicy } from \"./network-policy\"\nimport { output, type ComponentResourceOptions, Output, type Input } from \"@highstate/pulumi\"\nimport { apps, types } from \"@pulumi/kubernetes\"\nimport { omit } from \"remeda\"\nimport { deepmerge } from \"deepmerge-ts\"\nimport {\n getProvider,\n mapMetadata,\n resourceIdToString,\n withPatchName,\n type ResourceId,\n} from \"./shared\"\nimport {\n exposableWorkloadExtraArgs,\n ExposableWorkload,\n type ExposableWorkloadArgs,\n getExposableWorkloadComponents,\n} from \"./workload\"\n\nexport type StatefulSetArgs = Omit<ExposableWorkloadArgs, \"existing\"> &\n Omit<Partial<types.input.apps.v1.StatefulSetSpec>, \"template\"> & {\n template?: {\n metadata?: types.input.meta.v1.ObjectMeta\n spec?: Partial<types.input.core.v1.PodSpec>\n }\n }\n\nexport type CreateOrGetStatefulSetArgs = StatefulSetArgs & {\n /**\n * The entity to use to determine the stateful set to patch.\n */\n existing: Input<k8s.StatefulSet> | undefined\n}\n\nexport abstract class StatefulSet extends ExposableWorkload {\n protected constructor(\n type: string,\n name: string,\n args: ExposableWorkloadArgs,\n opts: ComponentResourceOptions | undefined,\n\n cluster: Output<k8s.Cluster>,\n metadata: Output<types.output.meta.v1.ObjectMeta>,\n\n /**\n * The spec of the underlying Kubernetes stateful set.\n */\n readonly spec: Output<types.output.apps.v1.StatefulSetSpec>,\n\n /**\n * The status of the underlying Kubernetes stateful set.\n */\n readonly status: Output<types.output.apps.v1.StatefulSetStatus>,\n\n networkPolicy: Output<NetworkPolicy | undefined>,\n\n service: Output<Service | undefined>,\n httpRoute: Output<HttpRoute | undefined>,\n ) {\n super(\n type,\n name,\n args,\n opts,\n \"statefulset\",\n cluster,\n metadata,\n networkPolicy,\n service,\n httpRoute,\n )\n }\n\n /**\n * The Highstate stateful set entity.\n */\n get entity(): Output<k8s.StatefulSet> {\n return output({\n type: \"k8s.stateful-set\",\n clusterId: this.cluster.id,\n metadata: this.metadata,\n service: this.service.entity,\n })\n }\n\n static create(name: string, args: StatefulSetArgs, opts?: ComponentResourceOptions): StatefulSet {\n return new CreatedStatefulSet(name, args, opts)\n }\n\n static createOrPatch(\n name: string,\n args: CreateOrGetStatefulSetArgs,\n opts?: ComponentResourceOptions,\n ): StatefulSet {\n if (!args.existing) {\n return new CreatedStatefulSet(name, args, opts)\n }\n\n return new StatefulSetPatch(\n name,\n {\n ...args,\n name: withPatchName(\"stateful set\", args.existing, args.cluster),\n namespace: output(args.existing).metadata.namespace,\n },\n opts,\n )\n }\n\n static patch(name: string, args: StatefulSetArgs, opts?: ComponentResourceOptions): StatefulSet {\n return new StatefulSetPatch(name, args, opts)\n }\n\n static createOrGet(\n name: string,\n args: CreateOrGetStatefulSetArgs,\n opts?: ComponentResourceOptions,\n ): StatefulSet {\n if (!args.existing) {\n return new CreatedStatefulSet(name, args, opts)\n }\n\n return new ExternalStatefulSet(name, output(args.existing).metadata, args.cluster, opts)\n }\n}\n\nclass CreatedStatefulSet extends StatefulSet {\n constructor(name: string, args: StatefulSetArgs, opts?: ComponentResourceOptions) {\n const { labels, podTemplate, networkPolicy, service, httpRoute } =\n getExposableWorkloadComponents(\n name,\n {\n ...args,\n\n // force create a service since it is required for stateful sets\n service: output(args.service).apply(service => ({ ...service })),\n },\n () => this,\n opts,\n )\n\n const statefulSet = output({ args, podTemplate }).apply(async ({ args, podTemplate }) => {\n return new apps.v1.StatefulSet(\n name,\n {\n metadata: mapMetadata(args, name),\n spec: deepmerge(\n {\n serviceName: service.apply(service => service!.metadata.name),\n template: podTemplate,\n selector: { matchLabels: labels },\n },\n omit(args, exposableWorkloadExtraArgs),\n ) as types.input.apps.v1.StatefulSetSpec,\n },\n {\n ...opts,\n parent: this,\n provider: await getProvider(args.cluster),\n },\n )\n })\n\n super(\n \"highstate:k8s:StatefulSet\",\n name,\n args,\n opts,\n\n output(args.cluster),\n statefulSet.metadata,\n statefulSet.spec,\n statefulSet.status,\n\n networkPolicy,\n service,\n httpRoute,\n )\n }\n}\n\nclass StatefulSetPatch extends StatefulSet {\n constructor(name: string, args: StatefulSetArgs, opts?: ComponentResourceOptions) {\n const { podSpec, networkPolicy, service, httpRoute } = getExposableWorkloadComponents(\n name,\n args,\n () => this,\n opts,\n )\n\n const statefulSet = output({ args, podSpec }).apply(async ({ args, podSpec }) => {\n return new apps.v1.StatefulSetPatch(\n name,\n {\n metadata: mapMetadata(args, name),\n spec: deepmerge(\n {\n template: {\n spec: podSpec,\n },\n },\n omit(args, exposableWorkloadExtraArgs),\n ) as types.input.apps.v1.StatefulSetSpec,\n },\n {\n ...opts,\n parent: this,\n provider: await getProvider(args.cluster),\n },\n )\n })\n\n super(\n \"highstate:k8s:StatefulSetPatch\",\n name,\n args,\n opts,\n\n output(args.cluster),\n statefulSet.metadata,\n statefulSet.spec,\n statefulSet.status,\n\n networkPolicy,\n service,\n httpRoute,\n )\n }\n}\n\nclass ExternalStatefulSet extends StatefulSet {\n constructor(\n name: string,\n id: Input<ResourceId>,\n cluster: Input<k8s.Cluster>,\n opts?: ComponentResourceOptions,\n ) {\n const statefulSet = output(id).apply(async id => {\n return apps.v1.StatefulSet.get(name, resourceIdToString(id), {\n ...opts,\n parent: this,\n provider: await getProvider(cluster),\n })\n })\n\n super(\n \"highstate:k8s:ExternalStatefulSet\",\n name,\n { namespace: output(id).namespace, cluster },\n opts,\n output(cluster),\n statefulSet.metadata,\n statefulSet.spec,\n statefulSet.status,\n\n output(undefined),\n output(undefined),\n output(undefined),\n )\n }\n}\n"],"mappings":"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","names":["service","args","podTemplate","podSpec","id"]}
|