1import { adopt } from "@/AdoptPolicy.ts";
2import {
3 OrganizationVPCEndpoint,
4 validateOrganizationVPCEndpoint,
5} from "@/Neon/OrganizationVPCEndpoint.ts";
6import { providers } from "@/Neon/Providers.ts";
7import * as Output from "@/Output.ts";
8import * as Test from "@/Test/Alchemy";
9import * as SDK from "@distilled.cloud/neon";
10import { expect } from "alchemy-test";
11import * as Effect from "effect/Effect";
12import * as Result from "effect/Result";
13
14const { test } = Test.make({ providers: providers() });
15const props = {
16 orgId: "org-network-fixture",
17 regionId: "aws-us-east-2",
18 vpcEndpointId: "vpce-0123456789abcdef0",
19 label: "Fixture",
20};
21const context = {
22 id: "Network",
23 fqn: "Network",
24 instanceId: "network-validation",
25 oldBindings: [],
26 newBindings: [],
27};
28
29test(
30 "organization registration validates AWS scope and endpoint identities",
31 Effect.gen(function* () {
32 yield* validateOrganizationVPCEndpoint(props);
33 for (const patch of [
34 { orgId: "" },
35 { regionId: "azure-eastus2" },
36 { vpcEndpointId: "vpc-0123456789abcdef0" },
37 { label: " " },
38 ]) {
39 expect(
40 Result.isFailure(
41 yield* validateOrganizationVPCEndpoint({ ...props, ...patch }).pipe(
42 Effect.result,
43 ),
44 ),
45 ).toBe(true);
46 }
47 }),
48 { tags: ["provider:neon", "provider:neon:organizationvpcendpoint", "live"] },
49);
50
51test.provider(
52 "organization registration scope replacements delete the old scope first",
53 () =>
54 Effect.gen(function* () {
55 const provider = yield* OrganizationVPCEndpoint.Provider;
56 for (const patch of [
57 { orgId: "org-other" },
58 { regionId: "aws-us-west-2" },
59 { vpcEndpointId: "vpce-abcdef01234567890" },
60 { regionId: Output.literal("aws-us-west-2") },
61 ]) {
62 expect(
63 yield* provider.diff!({
64 ...context,
65 olds: props,
66 news: { ...props, ...patch },
67 output: undefined,
68 }),
69 ).toEqual({ action: "replace", deleteFirst: true });
70 }
71 for (const news of [Output.literal(props), Effect.succeed(props)]) {
72 expect(
73 yield* provider.diff!({
74 ...context,
75 olds: props,
76 news,
77 output: undefined,
78 }),
79 ).toEqual({ action: "replace", deleteFirst: true });
80 }
81 expect(
82 yield* provider.diff!({
83 ...context,
84 olds: props,
85 news: { ...props, label: Output.literal("Updated") },
86 output: undefined,
87 }),
88 ).toBeUndefined();
89 }).pipe(
90 Effect.provideService(
91 SDK.Credentials,
92 Effect.die("Unexpected Neon request in a no-I/O guard test"),
93 ),
94 ),
95 { tags: ["provider:neon", "provider:neon:organizationvpcendpoint", "live"] },
96);
97
98test.provider(
99 "organization registration rejects a cached endpoint from another region before I/O",
100 () =>
101 Effect.gen(function* () {
102 const provider = yield* OrganizationVPCEndpoint.Provider;
103 expect(
104 yield* provider
105 .reconcile({
106 ...context,
107 bindings: [],
108 session: {
109 emit: () => Effect.void,
110 done: () => Effect.void,
111 note: () => Effect.void,
112 },
113 olds: undefined,
114 news: { ...props, regionId: "aws-us-west-2" },
115 output: {
116 ...props,
117 initialLabel: props.label,
118 managedLabel: props.label,
119 state: "accepted",
120 },
121 })
122 .pipe(
123 Effect.as(false),
124 Effect.catchTag("InvalidOrganizationVPCEndpoint", () =>
125 Effect.succeed(true),
126 ),
127 ),
128 ).toBe(true);
129 }).pipe(
130 Effect.provideService(
131 SDK.Credentials,
132 Effect.die("Unexpected Neon request in a no-I/O guard test"),
133 ),
134 ),
135 { tags: ["provider:neon", "provider:neon:organizationvpcendpoint", "live"] },
136);
137
138const orgId = process.env.NEON_GOVERNANCE_TEST_ORG_ID;
139const regionId = process.env.NEON_GOVERNANCE_TEST_VPC_ENDPOINT_REGION;
140const vpcEndpointId = process.env.NEON_GOVERNANCE_TEST_VPC_ENDPOINT_ID;
141const enabled =
142 !!orgId &&
143 !!regionId &&
144 !!vpcEndpointId &&
145 process.env.NEON_GOVERNANCE_TEST_NETWORK === "1";
146const disposable = process.env.NEON_GOVERNANCE_TEST_VPC_UNREGISTER === "1";
147
148// The ordinary fixture must already be registered; unregistering it is irreversible.
149test.provider.skipIf(!enabled || disposable)(
150 "dedicated existing organization registration requires adoption and restores its exact label",
151 (stack) =>
152 Effect.gen(function* () {
153 yield* stack.destroy();
154 const scope = {
155 orgId: orgId!,
156 regionId: regionId!,
157 vpcEndpointId: vpcEndpointId!,
158 };
159 const request = {
160 org_id: scope.orgId,
161 region_id: scope.regionId,
162 vpc_endpoint_id: scope.vpcEndpointId,
163 };
164 const baseline = yield* SDK.getOrganizationVPCEndpointDetails(request);
165 const application = (label: string, takeOwnership = false) =>
166 OrganizationVPCEndpoint("Network", { ...scope, label }).pipe(
167 adopt(takeOwnership),
168 );
169 expect(
170 Result.isFailure(
171 yield* stack
172 .plan(application("Alchemy governance fixture"))
173 .pipe(Effect.result),
174 ),
175 ).toBe(true);
176 const adopted = yield* stack.deploy(
177 application("Alchemy governance fixture", true),
178 );
179 expect(adopted.initialLabel).toBe(baseline.label);
180 expect(
181 (yield* SDK.getOrganizationVPCEndpointDetails(request)).label,
182 ).toBe("Alchemy governance fixture");
183 yield* stack.deploy(application("Alchemy governance updated"));
184 yield* SDK.assignOrganizationVPCEndpoint({
185 ...request,
186 label: "External fixture label",
187 });
188 expect(Result.isFailure(yield* stack.destroy().pipe(Effect.result))).toBe(
189 true,
190 );
191 expect(
192 (yield* SDK.getOrganizationVPCEndpointDetails(request)).label,
193 ).toBe("External fixture label");
194 yield* SDK.assignOrganizationVPCEndpoint({
195 ...request,
196 label: "Alchemy governance updated",
197 });
198 yield* stack.destroy();
199 const restored = yield* SDK.getOrganizationVPCEndpointDetails(request);
200 expect(restored.label).toBe(baseline.label);
201 expect(restored.vpc_endpoint_id).toBe(baseline.vpc_endpoint_id);
202 expect(restored.num_restricted_projects).toBe(
203 baseline.num_restricted_projects,
204 );
205 yield* stack.destroy();
206 }),
207 {
208 tags: ["provider:neon", "provider:neon:organizationvpcendpoint", "live"],
209 timeout: 120_000,
210 exclusive: true,
211 },
212);
213
214test.provider.skipIf(!enabled || !disposable)(
215 "explicit disposable endpoint registration is removed from Neon",
216 (stack) =>
217 Effect.gen(function* () {
218 yield* stack.destroy();
219 const scope = {
220 orgId: orgId!,
221 regionId: regionId!,
222 vpcEndpointId: vpcEndpointId!,
223 };
224 const request = {
225 org_id: scope.orgId,
226 region_id: scope.regionId,
227 vpc_endpoint_id: scope.vpcEndpointId,
228 };
229 const list = yield* SDK.listOrganizationVPCEndpoints(request);
230 expect(
231 list.endpoints.some(
232 (endpoint) => endpoint.vpc_endpoint_id === scope.vpcEndpointId,
233 ),
234 ).toBe(false);
235 const created = yield* stack.deploy(
236 OrganizationVPCEndpoint("Network", {
237 ...scope,
238 label: "Alchemy disposable fixture",
239 }),
240 );
241 expect(created.initialLabel).toBeNull();
242 expect(
243 (yield* SDK.getOrganizationVPCEndpointDetails(request)).label,
244 ).toBe("Alchemy disposable fixture");
245 yield* stack.destroy();
246 expect(
247 (yield* SDK.listOrganizationVPCEndpoints(request)).endpoints.some(
248 (endpoint) => endpoint.vpc_endpoint_id === scope.vpcEndpointId,
249 ),
250 ).toBe(false);
251 yield* stack.destroy();
252 }),
253 {
254 tags: ["provider:neon", "provider:neon:organizationvpcendpoint", "live"],
255 timeout: 120_000,
256 exclusive: true,
257 },
258);