t3-code-android-nightly/.repos/alchemy-effect/packages/alchemy/test/AWS/NetworkFirewall/Firewall.test.ts
Julius Marminge 6f9cea00ae
chore(refs): sync Effect and Alchemy references to 4.0.1 and beta.80 (#16170)
Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-05 13:22:30 -07:00

155 lines
5.2 KiB
TypeScript

import * as AWS from "@/AWS";
import { Subnet, Vpc } from "@/AWS/EC2";
import { LogGroup } from "@/AWS/Logs";
import {
Firewall,
FirewallPolicy,
LoggingConfiguration,
} from "@/AWS/NetworkFirewall";
import * as Test from "@/Test/Alchemy";
import * as nfw from "@distilled.cloud/aws/network-firewall";
import { expect } from "alchemy-test";
import * as Effect from "effect/Effect";
import * as Schedule from "effect/Schedule";
const { test } = Test.make({ providers: AWS.providers() });
// Ungated typed-error probes: prove the distilled error union carries the
// not-found tags this provider's read/delete paths depend on.
test.provider(
"describeFirewall on a nonexistent firewall fails with ResourceNotFoundException",
() =>
Effect.gen(function* () {
const error = yield* Effect.flip(
nfw.describeFirewall({
FirewallName: "alchemy-nonexistent-nfw-firewall-probe",
}),
);
expect(error._tag).toBe("ResourceNotFoundException");
}),
{ tags: ["provider:aws", "provider:aws:networkfirewall", "live"] },
);
test.provider(
"describeLoggingConfiguration on a nonexistent firewall fails with ResourceNotFoundException",
() =>
Effect.gen(function* () {
const error = yield* Effect.flip(
nfw.describeLoggingConfiguration({
FirewallName: "alchemy-nonexistent-nfw-firewall-probe",
}),
);
expect(error._tag).toBe("ResourceNotFoundException");
}),
{ tags: ["provider:aws", "provider:aws:networkfirewall", "live"] },
);
const assertFirewallGone = (name: string) =>
Effect.gen(function* () {
const error = yield* Effect.flip(
nfw.describeFirewall({ FirewallName: name }),
);
if (error._tag !== "ResourceNotFoundException") {
return yield* Effect.fail(
new Error(`firewall '${name}' still exists (${error._tag})`),
);
}
}).pipe(
Effect.retry({
schedule: Schedule.max([
Schedule.fixed("10 seconds"),
Schedule.recurs(18),
]),
}),
);
// A firewall takes ~5-10 minutes to provision its endpoints and a similar
// window to deprovision on delete. The full lifecycle is gated behind
// AWS_TEST_NETWORKFIREWALL=1 and always destroys what it created.
test.provider.skipIf(!process.env.AWS_TEST_NETWORKFIREWALL)(
"create firewall with logging configuration, verify, destroy",
(stack) =>
Effect.gen(function* () {
yield* stack.destroy();
const { firewall, logging, policy } = yield* stack.deploy(
Effect.gen(function* () {
const vpc = yield* Vpc("Vpc", {
cidrBlock: "10.77.0.0/16",
tags: { fixture: "nfw-firewall" },
});
const subnet = yield* Subnet("FirewallSubnet", {
vpcId: vpc.vpcId,
cidrBlock: "10.77.1.0/24",
tags: { fixture: "nfw-firewall" },
});
const policy = yield* FirewallPolicy("Policy", {
firewallPolicy: {
StatelessDefaultActions: ["aws:pass"],
StatelessFragmentDefaultActions: ["aws:pass"],
},
});
const firewall = yield* Firewall("Firewall", {
firewallPolicyArn: policy.firewallPolicyArn,
vpcId: vpc.vpcId,
subnetMappings: [{ SubnetId: subnet.subnetId }],
description: "alchemy network firewall test",
tags: { fixture: "nfw-firewall" },
});
const logGroup = yield* LogGroup("FlowLogs", {
retention: "1 day",
});
const logging = yield* LoggingConfiguration("Logging", {
firewallArn: firewall.firewallArn,
logDestinationConfigs: [
{
LogType: "FLOW",
LogDestinationType: "CloudWatchLogs",
LogDestination: { logGroup: logGroup.logGroupName },
},
],
});
return { firewall, logging, policy };
}),
);
expect(firewall.firewallArn).toContain(":firewall/");
expect(firewall.firewallId).toBeDefined();
expect(firewall.endpointIds.length).toBe(1);
expect(firewall.endpointIds[0]).toMatch(/^vpce-/);
expect(logging.firewallArn).toBe(firewall.firewallArn);
// Out-of-band verification via distilled.
const observed = yield* nfw.describeFirewall({
FirewallName: firewall.firewallName,
});
expect(observed.FirewallStatus?.Status).toBe("READY");
expect(observed.Firewall?.FirewallPolicyArn).toBe(
policy.firewallPolicyArn,
);
const observedLogging = yield* nfw.describeLoggingConfiguration({
FirewallArn: firewall.firewallArn,
});
expect(
observedLogging.LoggingConfiguration?.LogDestinationConfigs?.[0]
?.LogType,
).toBe("FLOW");
// Destroy immediately (delete waits for endpoint deprovisioning) and
// verify the firewall is gone out-of-band.
yield* stack.destroy();
yield* assertFirewallGone(firewall.firewallName);
}),
// firewall create (~10 min) + delete (~10 min), one test.
{
tags: [
"provider:aws",
"provider:aws:ec2",
"provider:aws:logs",
"provider:aws:networkfirewall",
"live",
],
timeout: 2_400_000,
},
);