1import * as GCP from "@/GCP";
2import * as Effect from "effect/Effect";
3import { serveProbes } from "../../bindingHost.ts";
4import { CAPACITY_ZONE_2 } from "../../zones.ts";
5
6/**
7 * GKE cluster create and delete each take 5-10 minutes, so
8 * `GCP_TEST_SLOW=1` opts in. The gate is forwarded to the host's
9 * environment so the deployed runtime binds the same set.
10 */
11export const slow = !!process.env.GCP_TEST_SLOW && !process.env.FAST;
12
13/**
14 * The cluster lives for the whole describe block, so it cannot hold a
15 * `withGkeClusterSlot` permit; it takes its own zone instead so it never
16 * counts against the per-location cluster quota the slotted lifecycle tests
17 * share in `CAPACITY_ZONE`.
18 */
19const ZONE = CAPACITY_ZONE_2;
20
21// Pools stay empty (the probes only read metadata): every GKE node holds an external IP and the project
22// allows only 8 IN_USE_ADDRESSES per region, shared by every capacity test.
23const poolShape = {
24 nodeCount: 0,
25 machineType: "e2-medium",
26 diskSizeGb: 20,
27 spot: true,
28} as const;
29
30/** Zonal cluster GetCluster binds; declared only when {@link slow}. */
31export const App = GCP.Container.Cluster("App", {
32 location: ZONE,
33 machineType: "e2-medium",
34 initialNodeCount: 1,
35 diskSizeGb: 20,
36 spot: true,
37});
38
39/** Node pool (locations API) GetNodePool binds. */
40export const Workers = Effect.gen(function* () {
41 const cluster = yield* App;
42 return yield* GCP.Container.NodePool("Workers", {
43 cluster: cluster.name,
44 ...poolShape,
45 });
46});
47
48/** Node pool (zones API) GetClustersNodePool binds. */
49export const ZonalWorkers = Effect.gen(function* () {
50 const cluster = yield* App;
51 return yield* GCP.Container.ClustersNodePool("ZonalWorkers", {
52 cluster: cluster.clusterId,
53 zone: ZONE,
54 ...poolShape,
55 });
56});
57
58const clusterProbes = Effect.gen(function* () {
59 const getCluster = yield* GCP.Container.GetCluster(App);
60 const getNodePool = yield* GCP.Container.GetNodePool(Workers);
61 const getClustersNodePool =
62 yield* GCP.Container.GetClustersNodePool(ZonalWorkers);
63 return {
64 getCluster: getCluster(),
65 getNodePool: getNodePool(),
66 getClustersNodePool: getClustersNodePool(),
67 };
68});
69
70/**
71 * Effect-native Cloud Run service exercising every GKE binding as its own
72 * runtime service account. Deployed from {@link ../Bindings.test.ts}.
73 */
74export default class ContainerBindingsHost extends GCP.Function<ContainerBindingsHost>()(
75 "ContainerBindingsHost",
76 {
77 main: import.meta.url,
78 invokerIamDisabled: true,
79 env: { GCP_TEST_SLOW: slow ? "1" : "" },
80 },
81 Effect.gen(function* () {
82 const cluster = slow ? yield* clusterProbes : {};
83 return { fetch: serveProbes({ ...cluster }) };
84 }).pipe(
85 Effect.provide(GCP.Container.GetClusterHttp),
86 Effect.provide(GCP.Container.GetNodePoolHttp),
87 Effect.provide(GCP.Container.GetClustersNodePoolHttp),
88 ),
89) {}