1import * as GCP from "@/GCP";
2import * as Test from "@/Test/Alchemy";
3import * as parametermanager from "@distilled.cloud/gcp/parametermanager_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 = (name: string) =>
17 parametermanager.getProjectsLocationsParametersVersions({ name }).pipe(
18 Effect.as("found" as const),
19 Effect.catchTag("NotFound", () => Effect.succeed("gone" as const)),
20 Effect.repeat({
21 schedule: Schedule.spaced("1 second"),
22 until: (status) => status === "gone",
23 times: 10,
24 }),
25 );
26
27const payloadOf = (data: string) =>
28 Effect.sync(() => Buffer.from(data, "utf8").toString("base64"));
29
30test.provider(
31 "create, update, and delete a parameter version",
32 (stack) =>
33 Effect.gen(function* () {
34 yield* stack.destroy();
35
36 const created = yield* stack.deploy(
37 Effect.gen(function* () {
38 const parameter = yield* GCP.ParameterManager.Parameter("AppConfig", {
39 labels: { env: "test" },
40 });
41 const version = yield* GCP.ParameterManager.ParametersVersion("V1", {
42 parameter: parameter.name,
43 data: "host=api.example.com",
44 });
45 return { parameter, version };
46 }),
47 );
48
49 expect(created.version.name).toContain("/versions/");
50 expect(created.version.parameter).toEqual(created.parameter.name);
51 expect(created.version.disabled).toEqual(false);
52 const expectedPayload = yield* payloadOf("host=api.example.com");
53 expect(created.version.payloadData).toEqual(expectedPayload);
54
55 const fetched =
56 yield* parametermanager.getProjectsLocationsParametersVersions({
57 name: created.version.name,
58 view: "FULL",
59 });
60 expect(fetched.name).toEqual(created.version.name);
61 expect(fetched.disabled).toBeFalsy();
62 expect(fetched.payload?.data).toEqual(created.version.payloadData);
63
64 const updated = yield* stack.deploy(
65 Effect.gen(function* () {
66 const parameter = yield* GCP.ParameterManager.Parameter("AppConfig", {
67 parameterId: created.parameter.parameterId,
68 location: created.parameter.location,
69 labels: { env: "test" },
70 });
71 const version = yield* GCP.ParameterManager.ParametersVersion("V1", {
72 parameter: parameter.name,
73 parameterVersionId: created.version.parameterVersionId,
74 data: "host=api.example.com",
75 disabled: true,
76 });
77 return { parameter, version };
78 }),
79 );
80
81 expect(updated.version.name).toEqual(created.version.name);
82 expect(updated.version.disabled).toEqual(true);
83
84 const fetchedUpdate =
85 yield* parametermanager.getProjectsLocationsParametersVersions({
86 name: created.version.name,
87 view: "BASIC",
88 });
89 expect(fetchedUpdate.disabled).toEqual(true);
90
91 yield* stack.destroy();
92
93 const gone = yield* waitUntilGone(created.version.name);
94 expect(gone).toEqual("gone");
95 }).pipe(logLevel),
96 {
97 tags: ["provider:gcp", "provider:gcp:parametermanager", "live"],
98 timeout: 90_000,
99 },
100);
101
102test.provider(
103 "replace a parameter version when payload changes",
104 (stack) =>
105 Effect.gen(function* () {
106 yield* stack.destroy();
107
108 const created = yield* stack.deploy(
109 Effect.gen(function* () {
110 const parameter = yield* GCP.ParameterManager.Parameter(
111 "AppConfig",
112 {},
113 );
114 const version = yield* GCP.ParameterManager.ParametersVersion("V1", {
115 parameter: parameter.name,
116 data: "first",
117 });
118 return { parameter, version };
119 }),
120 );
121
122 const firstPayload = yield* payloadOf("first");
123 expect(created.version.payloadData).toEqual(firstPayload);
124
125 const replaced = yield* stack.deploy(
126 Effect.gen(function* () {
127 const parameter = yield* GCP.ParameterManager.Parameter("AppConfig", {
128 parameterId: created.parameter.parameterId,
129 location: created.parameter.location,
130 });
131 const version = yield* GCP.ParameterManager.ParametersVersion("V1", {
132 parameter: parameter.name,
133 parameterVersionId: created.version.parameterVersionId,
134 data: "second",
135 });
136 return { parameter, version };
137 }),
138 );
139
140 expect(replaced.version.name).toEqual(created.version.name);
141 const secondPayload = yield* payloadOf("second");
142 expect(replaced.version.payloadData).toEqual(secondPayload);
143
144 const fetched =
145 yield* parametermanager.getProjectsLocationsParametersVersions({
146 name: replaced.version.name,
147 view: "FULL",
148 });
149 expect(fetched.payload?.data).toEqual(replaced.version.payloadData);
150
151 yield* stack.destroy();
152
153 const gone = yield* waitUntilGone(replaced.version.name);
154 expect(gone).toEqual("gone");
155 }).pipe(logLevel),
156 {
157 tags: ["provider:gcp", "provider:gcp:parametermanager", "live"],
158 timeout: 90_000,
159 },
160);