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";
8import { withNetworkSlot } from "../networkQuota.ts";
9
10const { test } = Test.make({ providers: GCP.providers() });
11
12const logLevel = Effect.provideService(
13 MinimumLogLevel,
14 process.env.DEBUG ? "Debug" : "Info",
15);
16
17const waitUntilGone = (project: string, policyName: string) =>
18 dns.getPolicies({ project, policy: policyName }).pipe(
19 Effect.as("found" as const),
20 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
21 Effect.repeat({
22 schedule: Schedule.spaced("1 second"),
23 until: (status) => status === "gone",
24 times: 10,
25 }),
26 );
27
28const lastSegment = (url: string) => url.split("/").pop() ?? url;
29
30test.provider(
31 "create, update, replace, and delete a DNS server policy",
32 (stack) =>
33 Effect.gen(function* () {
34 yield* stack.destroy();
35
36 const created = yield* stack.deploy(
37 Effect.gen(function* () {
38 const vpc = yield* GCP.Compute.Network("Vpc", {
39 autoCreateSubnetworks: false,
40 });
41 const policy = yield* GCP.DNS.Policy("DnsPolicy", {
42 description: "alchemy test dns policy",
43 enableLogging: true,
44 networks: [vpc.networkName],
45 });
46 return { vpc, policy };
47 }),
48 );
49
50 expect(created.policy.policyName).toEqual(expect.any(String));
51 expect(created.policy.description).toEqual("alchemy test dns policy");
52 expect(created.policy.enableLogging).toEqual(true);
53 expect(created.policy.enableInboundForwarding).toEqual(false);
54 expect(created.policy.enableDns64).toEqual(false);
55 expect(created.policy.networks.map(lastSegment)).toContain(
56 created.vpc.networkName,
57 );
58
59 const fetched = yield* dns.getPolicies({
60 project: created.policy.project,
61 policy: created.policy.policyName,
62 });
63 expect(fetched.name).toEqual(created.policy.policyName);
64 expect(fetched.enableLogging).toEqual(true);
65 expect(fetched.description).toContain("alchemy-id=");
66 expect(fetched.description).toContain("alchemy test dns policy");
67 expect(
68 (fetched.networks ?? []).map((network) =>
69 lastSegment(network.networkUrl ?? ""),
70 ),
71 ).toContain(created.vpc.networkName);
72
73 const updated = yield* stack.deploy(
74 Effect.gen(function* () {
75 const vpc = yield* GCP.Compute.Network("Vpc", {
76 networkName: created.vpc.networkName,
77 autoCreateSubnetworks: false,
78 });
79 const policy = yield* GCP.DNS.Policy("DnsPolicy", {
80 policyName: created.policy.policyName,
81 description: "updated alchemy test dns policy",
82 enableLogging: false,
83 networks: [vpc.networkName],
84 });
85 return { vpc, policy };
86 }),
87 );
88
89 expect(updated.policy.policyName).toEqual(created.policy.policyName);
90 expect(updated.policy.description).toEqual(
91 "updated alchemy test dns policy",
92 );
93 expect(updated.policy.enableLogging).toEqual(false);
94
95 const fetchedUpdate = yield* dns.getPolicies({
96 project: created.policy.project,
97 policy: created.policy.policyName,
98 });
99 expect(fetchedUpdate.enableLogging).toEqual(false);
100 expect(fetchedUpdate.description).toContain(
101 "updated alchemy test dns policy",
102 );
103
104 const replacedName = `r${created.policy.policyName}`.slice(0, 63);
105 const replaced = yield* stack.deploy(
106 Effect.gen(function* () {
107 const vpc = yield* GCP.Compute.Network("Vpc", {
108 networkName: created.vpc.networkName,
109 autoCreateSubnetworks: false,
110 });
111 const policy = yield* GCP.DNS.Policy("DnsPolicy", {
112 policyName: replacedName,
113 description: "replaced alchemy test dns policy",
114 enableLogging: true,
115 networks: [vpc.networkName],
116 });
117 return { vpc, policy };
118 }),
119 );
120
121 expect(replaced.policy.policyName).toEqual(replacedName);
122 expect(replaced.policy.enableLogging).toEqual(true);
123 expect(replaced.policy.description).toEqual(
124 "replaced alchemy test dns policy",
125 );
126
127 const previousGone = yield* waitUntilGone(
128 created.policy.project,
129 created.policy.policyName,
130 );
131 expect(previousGone).toEqual("gone");
132
133 const fetchedReplacement = yield* dns.getPolicies({
134 project: created.policy.project,
135 policy: replacedName,
136 });
137 expect(fetchedReplacement.name).toEqual(replacedName);
138 expect(fetchedReplacement.enableLogging).toEqual(true);
139
140 yield* stack.destroy();
141
142 const gone = yield* waitUntilGone(created.policy.project, replacedName);
143 expect(gone).toEqual("gone");
144 }).pipe(logLevel, withNetworkSlot),
145 { tags: ["provider:gcp", "provider:gcp:dns", "live"], timeout: 120_000 },
146);