1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as dns from "@distilled.cloud/gcp/dns_v1";
4import { expect } from "alchemy-test";
5import * as Effect from "effect/Effect";
6import { MinimumLogLevel } from "effect/References";
7import * as Schedule from "effect/Schedule";
8
9const { test } = Test.make({ providers: GCP.providers() });
10
11const logLevel = Effect.provideService(
12 MinimumLogLevel,
13 process.env.DEBUG ? "Debug" : "Info",
14);
15
16const waitUntilGone = (
17 project: string,
18 managedZone: string,
19 name: string,
20 type: string,
21) =>
22 dns
23 .getResourceRecordSets({
24 project,
25 managedZone,
26 name,
27 type,
28 })
29 .pipe(
30 Effect.as("found" as const),
31 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
32 Effect.repeat({
33 schedule: Schedule.spaced("1 second"),
34 until: (status) => status === "gone",
35 times: 10,
36 }),
37 );
38
39test.provider(
40 "create, update, replace, and delete a resource record set",
41 (stack) =>
42 Effect.gen(function* () {
43 yield* stack.destroy();
44
45 const created = yield* stack.deploy(
46 Effect.gen(function* () {
47 const zone = yield* GCP.DNS.ManagedZone("Public", {
48 description: "alchemy rrset test zone",
49 labels: { env: "test" },
50 forceDestroy: true,
51 });
52 const record = yield* GCP.DNS.ResourceRecordSet("Www", {
53 managedZone: zone.zoneName,
54 name: "www",
55 type: "A",
56 ttl: 300,
57 rrdatas: ["203.0.113.10"],
58 });
59 return { zone, record };
60 }),
61 );
62
63 const recordName = `www.${created.zone.dnsName}`;
64 expect(created.record.managedZone).toEqual(created.zone.zoneName);
65 expect(created.record.name).toEqual(recordName);
66 expect(created.record.type).toEqual("A");
67 expect(created.record.ttl).toEqual(300);
68 expect(created.record.rrdatas).toEqual(["203.0.113.10"]);
69 expect(created.record.project).toEqual(created.zone.project);
70
71 const fetched = yield* dns.getResourceRecordSets({
72 project: created.record.project,
73 managedZone: created.zone.zoneName,
74 name: recordName,
75 type: "A",
76 });
77 expect(fetched.name).toEqual(recordName);
78 expect(fetched.type).toEqual("A");
79 expect(fetched.ttl).toEqual(300);
80 expect(fetched.rrdatas).toEqual(["203.0.113.10"]);
81
82 const updated = yield* stack.deploy(
83 Effect.gen(function* () {
84 const zone = yield* GCP.DNS.ManagedZone("Public", {
85 zoneName: created.zone.zoneName,
86 dnsName: created.zone.dnsName,
87 description: "alchemy rrset test zone",
88 labels: { env: "test" },
89 forceDestroy: true,
90 });
91 const record = yield* GCP.DNS.ResourceRecordSet("Www", {
92 managedZone: zone.zoneName,
93 name: "www",
94 type: "A",
95 ttl: 600,
96 rrdatas: ["203.0.113.20", "203.0.113.21"],
97 });
98 return { zone, record };
99 }),
100 );
101
102 expect(updated.record.name).toEqual(recordName);
103 expect(updated.record.type).toEqual("A");
104 expect(updated.record.ttl).toEqual(600);
105 expect(updated.record.rrdatas).toEqual(["203.0.113.20", "203.0.113.21"]);
106
107 const fetchedUpdated = yield* dns.getResourceRecordSets({
108 project: created.record.project,
109 managedZone: created.zone.zoneName,
110 name: recordName,
111 type: "A",
112 });
113 expect(fetchedUpdated.ttl).toEqual(600);
114 expect(fetchedUpdated.rrdatas).toEqual(["203.0.113.20", "203.0.113.21"]);
115
116 const replacedName = `api.${created.zone.dnsName}`;
117 const replaced = yield* stack.deploy(
118 Effect.gen(function* () {
119 const zone = yield* GCP.DNS.ManagedZone("Public", {
120 zoneName: created.zone.zoneName,
121 dnsName: created.zone.dnsName,
122 description: "alchemy rrset test zone",
123 labels: { env: "test" },
124 forceDestroy: true,
125 });
126 const record = yield* GCP.DNS.ResourceRecordSet("Www", {
127 managedZone: zone.zoneName,
128 name: "api",
129 type: "A",
130 ttl: 120,
131 rrdatas: ["203.0.113.30"],
132 });
133 return { zone, record };
134 }),
135 );
136
137 expect(replaced.record.name).toEqual(replacedName);
138 expect(replaced.record.ttl).toEqual(120);
139 expect(replaced.record.rrdatas).toEqual(["203.0.113.30"]);
140
141 const fetchedReplaced = yield* dns.getResourceRecordSets({
142 project: created.record.project,
143 managedZone: created.zone.zoneName,
144 name: replacedName,
145 type: "A",
146 });
147 expect(fetchedReplaced.rrdatas).toEqual(["203.0.113.30"]);
148
149 const previousGone = yield* waitUntilGone(
150 created.record.project,
151 created.zone.zoneName,
152 recordName,
153 "A",
154 );
155 expect(previousGone).toEqual("gone");
156
157 yield* stack.destroy();
158
159 const gone = yield* waitUntilGone(
160 created.record.project,
161 created.zone.zoneName,
162 replacedName,
163 "A",
164 );
165 expect(gone).toEqual("gone");
166 }).pipe(logLevel),
167 { tags: ["provider:gcp", "provider:gcp:dns", "live"], timeout: 90_000 },
168);