1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as gkeonprem from "@distilled.cloud/gcp/gkeonprem_v1";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import { MinimumLogLevel } from "effect/References";
7import * as Schedule from "effect/Schedule";
8import {
9 missingMembership,
10 currentProject,
11 vmwareAdminMembership,
12 runVmwareLifecycle,
13 vmwareControlPlane,
14 vmwareLoadBalancer,
15 vmwareNetwork,
16} from "./common.ts";
17
18const { test } = Test.make({ providers: GCP.providers() });
19
20const logLevel = Effect.provideService(
21 MinimumLogLevel,
22 process.env.DEBUG ? "Debug" : "Info",
23);
24
25const waitUntilGone = (name: string) =>
26 gkeonprem.getProjectsLocationsVmwareClusters({ name }).pipe(
27 Effect.as("found" as const),
28 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
29 Effect.repeat({
30 schedule: Schedule.spaced("2 seconds"),
31 until: (status) => status === "gone",
32 times: 10,
33 }),
34 );
35
36test.provider(
37 "getProjectsLocationsVmwareClusters on a missing cluster fails with a typed tag",
38 (stack) =>
39 Effect.gen(function* () {
40 const project = yield* currentProject;
41
42 yield* stack.destroy();
43
44 const error = yield* Effect.flip(
45 gkeonprem.getProjectsLocationsVmwareClusters({
46 name: `projects/${project}/locations/us-central1/vmwareClusters/alchemy-missing-vmc`,
47 }),
48 );
49 expect(error._tag).toEqual("NotFound");
50
51 yield* stack.destroy();
52 }).pipe(logLevel),
53 { tags: ["provider:gcp", "provider:gcp:gkeonprem", "live"], timeout: 90_000 },
54);
55
56test.provider.skipIf(runVmwareLifecycle)(
57 "create without an admin cluster fails with AdminClusterUnreachable",
58 (stack) =>
59 Effect.gen(function* () {
60 const project = yield* currentProject;
61
62 yield* stack.destroy();
63
64 const error = yield* Effect.flip(
65 stack.deploy(
66 Effect.gen(function* () {
67 return yield* GCP.GKEOnPrem.VmwareCluster("Workload", {
68 adminClusterMembership: missingMembership(project),
69 onPremVersion: "1.28.0-gke.1",
70 controlPlaneNode: vmwareControlPlane,
71 networkConfig: vmwareNetwork,
72 loadBalancer: vmwareLoadBalancer,
73 description: "alchemy-test-vmc",
74 labels: { env: "test" },
75 });
76 }),
77 ),
78 );
79 expect(error._tag).toEqual("AdminClusterUnreachable");
80
81 yield* stack.destroy();
82 }).pipe(logLevel),
83 { tags: ["provider:gcp", "provider:gcp:gkeonprem", "live"], timeout: 90_000 },
84);
85
86test.provider.skipIf(!runVmwareLifecycle)(
87 "create, update, and delete a vmware cluster",
88 (stack) =>
89 Effect.gen(function* () {
90 const project = yield* currentProject;
91
92 yield* stack.destroy();
93
94 const created = yield* stack.deploy(
95 Effect.gen(function* () {
96 return yield* GCP.GKEOnPrem.VmwareCluster("Workload", {
97 adminClusterMembership:
98 vmwareAdminMembership ?? missingMembership(project),
99 onPremVersion: "1.28.0-gke.1",
100 controlPlaneNode: vmwareControlPlane,
101 networkConfig: vmwareNetwork,
102 loadBalancer: vmwareLoadBalancer,
103 description: "alchemy-test-vmc",
104 labels: { env: "test" },
105 });
106 }),
107 );
108
109 expect(created.name).toContain("/vmwareClusters/");
110 expect(created.description).toEqual("alchemy-test-vmc");
111 expect(created.labels.env).toEqual("test");
112
113 const fetched = yield* gkeonprem.getProjectsLocationsVmwareClusters({
114 name: created.name,
115 });
116 expect(fetched.name).toEqual(created.name);
117 expect(fetched.description).toContain("alchemy-id=");
118 expect(fetched.description).toContain("alchemy-test-vmc");
119 expect(fetched.annotations?.["alchemy-id"]).toBeDefined();
120
121 const updated = yield* stack.deploy(
122 Effect.gen(function* () {
123 return yield* GCP.GKEOnPrem.VmwareCluster("Workload", {
124 vmwareClusterId: created.vmwareClusterId,
125 location: created.location,
126 adminClusterMembership:
127 created.adminClusterMembership ??
128 vmwareAdminMembership ??
129 missingMembership(project),
130 onPremVersion: created.onPremVersion ?? "1.28.0-gke.1",
131 controlPlaneNode: created.controlPlaneNode ?? vmwareControlPlane,
132 networkConfig: created.networkConfig ?? vmwareNetwork,
133 loadBalancer: created.loadBalancer ?? vmwareLoadBalancer,
134 description: "alchemy-test-vmc-v2",
135 labels: { env: "test", team: "platform" },
136 });
137 }),
138 );
139
140 expect(updated.description).toEqual("alchemy-test-vmc-v2");
141 expect(updated.labels.team).toEqual("platform");
142 expect(updated.vmwareClusterId).toEqual(created.vmwareClusterId);
143
144 yield* stack.destroy();
145 yield* waitUntilGone(created.name);
146 }).pipe(logLevel),
147 {
148 tags: ["provider:gcp", "provider:gcp:gkeonprem", "live"],
149 timeout: 120_000,
150 },
151);