1/**
2 * Internal helpers for binding Kubernetes objects onto a
3 * `GCP.Container.Cluster` through its `KubernetesObjectBinding` contract.
4 * The cluster's reconciler server-side-applies every bound object after
5 * the control plane is RUNNING. Not exported from the Container index —
6 * the public path for raw manifests is `Kubernetes.Manifest`.
7 */
8import * as Effect from "effect/Effect";
9import type { Cluster } from "../Cluster.ts";
10import {
11 kubernetesObjectKey,
12 toKubernetesObjectRef,
13 type KubernetesObjectDefinition,
14 type KubernetesObjectMetadata,
15} from "../../../Kubernetes/internal/objects.ts";
16
17export interface ClusterObjectProps {
18 /** Target GKE cluster that will own this Kubernetes object. */
19 cluster: Cluster;
20 /** Kubernetes API version. */
21 apiVersion: string;
22 /** Kubernetes kind. */
23 kind: string;
24 /** Object metadata. `name` defaults to the logical id. */
25 metadata?: Omit<KubernetesObjectMetadata, "name"> & {
26 name?: string;
27 };
28 /** Extra top-level fields merged into the final Kubernetes object. */
29 body?: Record<string, unknown>;
30}
31
32export interface ClusterObjectRef {
33 cluster: Cluster;
34 apiVersion: string;
35 kind: string;
36 name: string;
37 namespace: string | undefined;
38 key: string;
39 object: KubernetesObjectDefinition;
40}
41
42export const kubernetesBindingSid = (object: KubernetesObjectDefinition) =>
43 `Kubernetes.Object(${kubernetesObjectKey(toKubernetesObjectRef(object))})`;
44
45export const ClusterObject = Effect.fn(function* (
46 id: string,
47 props: ClusterObjectProps,
48) {
49 const object = {
50 apiVersion: props.apiVersion,
51 kind: props.kind,
52 metadata: {
53 name: props.metadata?.name ?? id,
54 namespace: props.metadata?.namespace,
55 labels: props.metadata?.labels,
56 annotations: props.metadata?.annotations,
57 },
58 ...props.body,
59 } satisfies KubernetesObjectDefinition;
60
61 yield* props.cluster.bind(kubernetesBindingSid(object), {
62 type: "kubernetes-object",
63 object,
64 });
65
66 const ref = toKubernetesObjectRef(object);
67
68 return {
69 cluster: props.cluster,
70 apiVersion: ref.apiVersion,
71 kind: ref.kind,
72 name: ref.name,
73 namespace: ref.namespace,
74 key: kubernetesObjectKey(ref),
75 object,
76 } satisfies ClusterObjectRef;
77});