1import * as AWS from "@/AWS";
2import { OriginRequestPolicy } from "@/AWS/CloudFront";
3import * as Provider from "@/Provider";
4import * as Test from "@/Test/Alchemy";
5import * as cloudfront from "@distilled.cloud/aws/cloudfront";
6import { describe, expect } from "alchemy-test";
7import * as Effect from "effect/Effect";
8import * as Schedule from "effect/Schedule";
9
10const { test } = Test.make({ providers: AWS.providers() });
11
12describe(
13 "AWS.CloudFront.OriginRequestPolicy",
14 { tags: ["provider:aws", "provider:aws:cloudfront", "live"] },
15 () => {
16 test.provider(
17 "create, update, and delete an origin request policy",
18 (stack) =>
19 Effect.gen(function* () {
20 yield* stack.destroy();
21
22 const created = yield* stack.deploy(
23 Effect.gen(function* () {
24 return yield* OriginRequestPolicy("AppOriginRequest", {
25 comment: "initial",
26 headersConfig: {
27 HeaderBehavior: "whitelist",
28 Headers: { Quantity: 1, Items: ["Authorization"] },
29 },
30 cookiesConfig: { CookieBehavior: "none" },
31 queryStringsConfig: { QueryStringBehavior: "all" },
32 });
33 }),
34 );
35
36 const initial = yield* cloudfront.getOriginRequestPolicy({
37 Id: created.originRequestPolicyId,
38 });
39 expect(initial.OriginRequestPolicy?.Id).toEqual(
40 created.originRequestPolicyId,
41 );
42 expect(
43 initial.OriginRequestPolicy?.OriginRequestPolicyConfig?.Comment,
44 ).toEqual("initial");
45 expect(
46 initial.OriginRequestPolicy?.OriginRequestPolicyConfig
47 ?.HeadersConfig?.Headers?.Items,
48 ).toEqual(["Authorization"]);
49
50 const updated = yield* stack.deploy(
51 Effect.gen(function* () {
52 return yield* OriginRequestPolicy("AppOriginRequest", {
53 comment: "updated",
54 headersConfig: {
55 HeaderBehavior: "whitelist",
56 Headers: {
57 Quantity: 2,
58 Items: ["Authorization", "Accept-Language"],
59 },
60 },
61 cookiesConfig: { CookieBehavior: "all" },
62 queryStringsConfig: { QueryStringBehavior: "all" },
63 });
64 }),
65 );
66
67 expect(updated.originRequestPolicyId).toEqual(
68 created.originRequestPolicyId,
69 );
70
71 // Control-plane reads are eventually consistent — poll until the
72 // update is visible, then assert.
73 const after = yield* cloudfront
74 .getOriginRequestPolicy({ Id: updated.originRequestPolicyId })
75 .pipe(
76 Effect.repeat({
77 schedule: Schedule.fixed("2 seconds"),
78 until: (r) =>
79 r.OriginRequestPolicy?.OriginRequestPolicyConfig?.Comment ===
80 "updated",
81 times: 15,
82 }),
83 );
84 expect(
85 after.OriginRequestPolicy?.OriginRequestPolicyConfig?.Comment,
86 ).toEqual("updated");
87 expect(
88 after.OriginRequestPolicy?.OriginRequestPolicyConfig?.HeadersConfig
89 ?.Headers?.Items,
90 ).toEqual(["Authorization", "Accept-Language"]);
91 expect(
92 after.OriginRequestPolicy?.OriginRequestPolicyConfig?.CookiesConfig
93 ?.CookieBehavior,
94 ).toEqual("all");
95
96 yield* stack.destroy();
97 yield* assertOriginRequestPolicyDeleted(
98 updated.originRequestPolicyId,
99 );
100 }),
101 300_000,
102 );
103
104 test.provider(
105 "list enumerates the deployed origin request policy",
106 (stack) =>
107 Effect.gen(function* () {
108 yield* stack.destroy();
109
110 const deployed = yield* stack.deploy(
111 Effect.gen(function* () {
112 return yield* OriginRequestPolicy("ListOriginRequest", {
113 comment: "list",
114 headersConfig: { HeaderBehavior: "none" },
115 cookiesConfig: { CookieBehavior: "none" },
116 queryStringsConfig: { QueryStringBehavior: "none" },
117 });
118 }),
119 );
120
121 const provider = yield* Provider.findProvider(OriginRequestPolicy);
122 const all = yield* provider.list();
123
124 expect(
125 all.some(
126 (p) => p.originRequestPolicyId === deployed.originRequestPolicyId,
127 ),
128 ).toBe(true);
129
130 yield* stack.destroy();
131 yield* assertOriginRequestPolicyDeleted(
132 deployed.originRequestPolicyId,
133 );
134 }),
135 { timeout: 300_000 },
136 );
137 },
138);
139
140const assertOriginRequestPolicyDeleted = (id: string) =>
141 cloudfront.getOriginRequestPolicy({ Id: id }).pipe(
142 Effect.flatMap(() =>
143 Effect.fail(new Error("OriginRequestPolicyStillExists")),
144 ),
145 Effect.catchTag("NoSuchOriginRequestPolicy", () => Effect.void),
146 Effect.retry({
147 while: (error) =>
148 error instanceof Error &&
149 error.message === "OriginRequestPolicyStillExists",
150 schedule: Schedule.max([
151 Schedule.fixed("5 seconds"),
152 Schedule.recurs(24),
153 ]),
154 }),
155 );