1import * as AWS from "@/AWS";
2import { ServiceIntegration } from "@/AWS/DevOpsGuru/ServiceIntegration.ts";
3import * as Test from "@/Test/Alchemy";
4import * as devopsguru from "@distilled.cloud/aws/devops-guru";
5import { expect } from "alchemy-test";
6import * as Effect from "effect/Effect";
7
8const { test } = Test.make({ providers: AWS.providers() });
9
10// Observe the account's integration out-of-band. Absent sections/statuses
11// mean the account default (disabled / AWS-owned key).
12const observed = devopsguru.describeServiceIntegration({}).pipe(
13 Effect.map(({ ServiceIntegration: config }) => ({
14 opsCenter: config?.OpsCenter?.OptInStatus === "ENABLED",
15 logsAnomalyDetection:
16 config?.LogsAnomalyDetection?.OptInStatus === "ENABLED",
17 encryptionType:
18 config?.KMSServerSideEncryption?.Type ?? "AWS_OWNED_KMS_KEY",
19 })),
20);
21
22// Ungated typed probe: describeServiceIntegration always answers with the
23// typed response shape — never an untyped catch-all.
24test.provider(
25 "describeServiceIntegration returns typed results",
26 () =>
27 Effect.gen(function* () {
28 const config = yield* observed;
29 expect(typeof config.opsCenter).toBe("boolean");
30 expect(typeof config.logsAnomalyDetection).toBe("boolean");
31 }),
32 { tags: ["provider:aws", "provider:aws:devopsguru", "live"] },
33);
34
35// The integration is an account/region singleton. This test only runs when
36// the account is at the defaults — it must never clobber a configuration
37// the user already operates.
38test.provider(
39 "lifecycle: enable log anomaly detection, add OpsCenter, restore defaults",
40 (stack) =>
41 Effect.gen(function* () {
42 const preexisting = yield* observed;
43 if (
44 preexisting.opsCenter ||
45 preexisting.logsAnomalyDetection ||
46 preexisting.encryptionType !== "AWS_OWNED_KMS_KEY"
47 ) {
48 yield* Effect.logInfo(
49 "DevOps Guru service integration already configured — skipping destructive lifecycle test",
50 );
51 return;
52 }
53
54 yield* stack.destroy();
55
56 // Create — enable log anomaly detection only.
57 const created = yield* stack.deploy(
58 Effect.gen(function* () {
59 return yield* ServiceIntegration("Integration", {
60 logsAnomalyDetection: true,
61 });
62 }),
63 );
64 expect(created.logsAnomalyDetection).toBe(true);
65 expect(created.opsCenter).toBe(false);
66 expect(created.encryptionType).toBe("AWS_OWNED_KMS_KEY");
67
68 // Out-of-band verification via distilled.
69 const afterCreate = yield* observed;
70 expect(afterCreate.logsAnomalyDetection).toBe(true);
71 expect(afterCreate.opsCenter).toBe(false);
72
73 // Update — enable OpsCenter too; only the drifted section is updated.
74 const updated = yield* stack.deploy(
75 Effect.gen(function* () {
76 return yield* ServiceIntegration("Integration", {
77 logsAnomalyDetection: true,
78 opsCenter: true,
79 });
80 }),
81 );
82 expect(updated.logsAnomalyDetection).toBe(true);
83 expect(updated.opsCenter).toBe(true);
84 const afterUpdate = yield* observed;
85 expect(afterUpdate.opsCenter).toBe(true);
86
87 // Destroy — the account defaults are restored.
88 yield* stack.destroy();
89 const after = yield* observed;
90 expect(after.opsCenter).toBe(false);
91 expect(after.logsAnomalyDetection).toBe(false);
92 expect(after.encryptionType).toBe("AWS_OWNED_KMS_KEY");
93 }),
94 {
95 tags: ["provider:aws", "provider:aws:devopsguru", "live"],
96 timeout: 180_000,
97 },
98);