1import * as AWS from "@/AWS";
2import { Policy } from "@/AWS/IoT";
3import * as Test from "@/Test/Alchemy";
4import * as iot from "@distilled.cloud/aws/iot";
5import { describe, expect } from "alchemy-test";
6import * as Effect from "effect/Effect";
7import * as Schedule from "effect/Schedule";
8
9const { test } = Test.make({ providers: AWS.providers() });
10
11const assertPolicyGone = (policyName: string) =>
12 iot.getPolicy({ policyName }).pipe(
13 Effect.flatMap(() =>
14 Effect.fail(new Error(`policy ${policyName} still exists`)),
15 ),
16 Effect.catchTag("ResourceNotFoundException", () => Effect.void),
17 Effect.retry({
18 while: (e) => e instanceof Error,
19 schedule: Schedule.max([
20 Schedule.fixed("2 seconds"),
21 Schedule.recurs(10),
22 ]),
23 }),
24 );
25
26describe.sequential(
27 "AWS.IoT.Policy",
28 { tags: ["provider:aws", "provider:aws:iot", "live"] },
29 () => {
30 test.provider(
31 "creates a policy, updates the document to a new default version, and deletes it",
32 (stack) =>
33 Effect.gen(function* () {
34 yield* stack.destroy();
35
36 const created = yield* stack.deploy(
37 Effect.gen(function* () {
38 const policy = yield* Policy("DevicePolicy", {
39 policyDocument: {
40 Version: "2012-10-17",
41 Statement: [
42 { Effect: "Allow", Action: "iot:Connect", Resource: "*" },
43 ],
44 },
45 });
46 return { policyName: policy.policyName };
47 }),
48 );
49
50 const observed = yield* iot.getPolicy({
51 policyName: created.policyName,
52 });
53 expect(observed.policyDocument).toContain("iot:Connect");
54 const firstVersion = observed.defaultVersionId;
55
56 // Update the document — creates a new default version.
57 yield* stack.deploy(
58 Effect.gen(function* () {
59 yield* Policy("DevicePolicy", {
60 policyDocument: {
61 Version: "2012-10-17",
62 Statement: [
63 { Effect: "Allow", Action: "iot:Connect", Resource: "*" },
64 { Effect: "Allow", Action: "iot:Publish", Resource: "*" },
65 ],
66 },
67 });
68 }),
69 );
70 const updated = yield* iot.getPolicy({
71 policyName: created.policyName,
72 });
73 expect(updated.policyDocument).toContain("iot:Publish");
74 expect(updated.defaultVersionId).not.toEqual(firstVersion);
75
76 yield* stack.destroy();
77 yield* assertPolicyGone(created.policyName);
78 }),
79 { timeout: 180_000 },
80 );
81 },
82);