1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as compute from "@distilled.cloud/gcp/compute_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 region: string,
19 resourcePolicy: string,
20) =>
21 compute.getResourcePolicies({ project, region, resourcePolicy }).pipe(
22 Effect.as("found" as const),
23 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
24 Effect.repeat({
25 schedule: Schedule.spaced("1 second"),
26 until: (status) => status === "gone",
27 times: 10,
28 }),
29 );
30
31test.provider(
32 "create, update, and delete a resource policy",
33 (stack) =>
34 Effect.gen(function* () {
35 yield* stack.destroy();
36
37 const created = yield* stack.deploy(
38 Effect.gen(function* () {
39 return yield* GCP.Compute.ResourcePolicy("Nightly", {
40 region: "us-central1",
41 description: "nightly snapshots",
42 snapshotSchedulePolicy: {
43 schedule: {
44 dailySchedule: { daysInCycle: 1, startTime: "04:00" },
45 },
46 retentionPolicy: { maxRetentionDays: 7 },
47 },
48 });
49 }),
50 );
51
52 expect(created.resourcePolicyName).toEqual(expect.any(String));
53 expect(created.region).toEqual("us-central1");
54 expect(created.status).toEqual("READY");
55 expect(created.description).toEqual("nightly snapshots");
56 expect(
57 created.snapshotSchedulePolicy?.schedule?.dailySchedule?.startTime,
58 ).toEqual("04:00");
59 expect(
60 created.snapshotSchedulePolicy?.retentionPolicy?.maxRetentionDays,
61 ).toEqual(7);
62
63 const fetched = yield* compute.getResourcePolicies({
64 project: created.project,
65 region: created.region,
66 resourcePolicy: created.resourcePolicyName,
67 });
68 expect(fetched.name).toEqual(created.resourcePolicyName);
69 expect(fetched.status).toEqual("READY");
70 expect(fetched.description).toContain("[alchemy ");
71 expect(fetched.description).toContain("nightly snapshots");
72 expect(
73 fetched.snapshotSchedulePolicy?.schedule?.dailySchedule?.daysInCycle,
74 ).toEqual(1);
75 expect(
76 fetched.snapshotSchedulePolicy?.retentionPolicy?.maxRetentionDays,
77 ).toEqual(7);
78
79 const updated = yield* stack.deploy(
80 Effect.gen(function* () {
81 return yield* GCP.Compute.ResourcePolicy("Nightly", {
82 resourcePolicyName: created.resourcePolicyName,
83 region: "us-central1",
84 description: "daily snapshots",
85 snapshotSchedulePolicy: {
86 schedule: {
87 dailySchedule: { daysInCycle: 1, startTime: "08:00" },
88 },
89 retentionPolicy: { maxRetentionDays: 14 },
90 },
91 });
92 }),
93 );
94
95 expect(updated.resourcePolicyName).toEqual(created.resourcePolicyName);
96 expect(updated.description).toEqual("daily snapshots");
97 expect(
98 updated.snapshotSchedulePolicy?.schedule?.dailySchedule?.startTime,
99 ).toEqual("08:00");
100 expect(
101 updated.snapshotSchedulePolicy?.retentionPolicy?.maxRetentionDays,
102 ).toEqual(14);
103
104 const fetchedUpdated = yield* compute.getResourcePolicies({
105 project: updated.project,
106 region: updated.region,
107 resourcePolicy: updated.resourcePolicyName,
108 });
109 expect(fetchedUpdated.description).toContain("daily snapshots");
110 expect(
111 fetchedUpdated.snapshotSchedulePolicy?.schedule?.dailySchedule
112 ?.startTime,
113 ).toEqual("08:00");
114 expect(
115 fetchedUpdated.snapshotSchedulePolicy?.retentionPolicy
116 ?.maxRetentionDays,
117 ).toEqual(14);
118
119 yield* stack.destroy();
120
121 const gone = yield* waitUntilGone(
122 created.project,
123 created.region,
124 created.resourcePolicyName,
125 );
126 expect(gone).toEqual("gone");
127 }).pipe(logLevel),
128 { tags: ["provider:gcp", "provider:gcp:compute", "live"], timeout: 90_000 },
129);