1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as vmwareengine from "@distilled.cloud/gcp/vmwareengine_v1";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import { MinimumLogLevel } from "effect/References";
7import * as Schedule from "effect/Schedule";
8import { GcpEnvironment } from "@/GCP/Environment";
9
10const { test } = Test.make({ providers: GCP.providers() });
11
12const logLevel = Effect.provideService(
13 MinimumLogLevel,
14 process.env.DEBUG ? "Debug" : "Info",
15);
16
17// Private clouds need VMware Engine node quota and bill thousands of dollars
18// a month; set GCP_TEST_VMWAREENGINE=1 on an entitled project to opt in.
19const runLifecycle = !!process.env.GCP_TEST_VMWAREENGINE && !process.env.FAST;
20
21const waitUntilGone = (name: string) =>
22 vmwareengine.getProjectsLocationsPrivateCloudsLoggingServers({ name }).pipe(
23 Effect.as("found" as const),
24 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
25 Effect.repeat({
26 schedule: Schedule.spaced("2 seconds"),
27 until: (status) => status === "gone",
28 times: 10,
29 }),
30 );
31
32test.provider(
33 "getProjectsLocationsPrivateCloudsLoggingServers on a missing logging server fails with a typed tag",
34 (stack) =>
35 Effect.gen(function* () {
36 const { project } = yield* GcpEnvironment.current;
37
38 yield* stack.destroy();
39
40 const error = yield* Effect.flip(
41 vmwareengine.getProjectsLocationsPrivateCloudsLoggingServers({
42 name: `projects/${project}/locations/us-central1-a/privateClouds/alchemy-missing/loggingServers/missing`,
43 }),
44 );
45 expect(error._tag).toEqual("NotFound");
46
47 yield* stack.destroy();
48 }).pipe(logLevel),
49 {
50 tags: ["provider:gcp", "provider:gcp:vmwareengine", "live"],
51 timeout: 90_000,
52 },
53);
54
55test.provider.skipIf(!runLifecycle)(
56 "create, update, and delete a logging server",
57 (stack) =>
58 Effect.gen(function* () {
59 yield* stack.destroy();
60
61 const created = yield* stack.deploy(
62 Effect.gen(function* () {
63 const ven = yield* GCP.VMwareEngine.VmwareEngineNetwork("Ven", {
64 type: "STANDARD",
65 description: "syslog grandparent",
66 });
67 const cloud = yield* GCP.VMwareEngine.PrivateCloud("Sddc", {
68 location: "us-central1-a",
69 networkConfig: {
70 managementCidr: "192.168.1.0/24",
71 vmwareEngineNetwork: ven.name,
72 },
73 managementCluster: {
74 clusterId: "mgmt",
75 nodeTypeConfigs: { "standard-72": { nodeCount: 3 } },
76 },
77 description: "syslog parent",
78 });
79 const syslog = yield* GCP.VMwareEngine.PrivateCloudsLoggingServer(
80 "Esxi",
81 {
82 privateCloud: cloud.name,
83 hostname: "logs.example.com",
84 port: 514,
85 protocol: "UDP",
86 sourceType: "ESXI",
87 },
88 );
89 return { ven, cloud, syslog };
90 }),
91 );
92
93 expect(created.syslog.name).toContain("/loggingServers/");
94 expect(created.syslog.hostname).toEqual("logs.example.com");
95 expect(created.syslog.port).toEqual(514);
96 expect(created.syslog.protocol).toEqual("UDP");
97 expect(created.syslog.sourceType).toEqual("ESXI");
98
99 const fetched =
100 yield* vmwareengine.getProjectsLocationsPrivateCloudsLoggingServers({
101 name: created.syslog.name,
102 });
103 expect(fetched.name).toEqual(created.syslog.name);
104 expect(fetched.hostname).toEqual("logs.example.com");
105
106 const updated = yield* stack.deploy(
107 Effect.gen(function* () {
108 const ven = yield* GCP.VMwareEngine.VmwareEngineNetwork("Ven", {
109 vmwareEngineNetworkId: created.ven.vmwareEngineNetworkId,
110 type: "STANDARD",
111 description: "syslog grandparent",
112 });
113 const cloud = yield* GCP.VMwareEngine.PrivateCloud("Sddc", {
114 privateCloudId: created.cloud.privateCloudId,
115 location: "us-central1-a",
116 networkConfig: {
117 managementCidr: "192.168.1.0/24",
118 vmwareEngineNetwork: ven.name,
119 },
120 managementCluster: {
121 clusterId: "mgmt",
122 nodeTypeConfigs: { "standard-72": { nodeCount: 3 } },
123 },
124 description: "syslog parent",
125 });
126 const syslog = yield* GCP.VMwareEngine.PrivateCloudsLoggingServer(
127 "Esxi",
128 {
129 privateCloud: cloud.name,
130 loggingServerId: created.syslog.loggingServerId,
131 hostname: "logs.example.com",
132 port: 6514,
133 protocol: "TCP",
134 sourceType: "VCSA",
135 },
136 );
137 return { ven, cloud, syslog };
138 }),
139 );
140
141 expect(updated.syslog.name).toEqual(created.syslog.name);
142 expect(updated.syslog.port).toEqual(6514);
143 expect(updated.syslog.protocol).toEqual("TCP");
144 expect(updated.syslog.sourceType).toEqual("VCSA");
145
146 yield* stack.destroy();
147
148 const gone = yield* waitUntilGone(created.syslog.name);
149 expect(gone).toEqual("gone");
150 }).pipe(logLevel),
151 {
152 tags: ["provider:gcp", "provider:gcp:vmwareengine", "live"],
153 timeout: 120_000,
154 },
155);