Skip to content

fix(ec2): persist Modify*/Create* attributes so Describe reflects them#2041

Open
vieiralucas wants to merge 2 commits into
mainfrom
wt-bug-ec2modify
Open

fix(ec2): persist Modify*/Create* attributes so Describe reflects them#2041
vieiralucas wants to merge 2 commits into
mainfrom
wt-bug-ec2modify

Conversation

@vieiralucas

@vieiralucas vieiralucas commented Jun 29, 2026

Copy link
Copy Markdown
Member

Problem

The EC2 long-tail handlers in crates/fakecloud-ec2/src/service/rest.rs were a "validate then drop" family: each took _svc (unused), validated wire params, and returned a minimal success WITHOUT persisting anything. The paired Describe*/Get* therefore reported the unchanged/empty default. This violates the project's no-stub rule and means a real client never sees its own changes.

Fix

Real, state-backed round-trips for the whole no-persist family. The Modify/Create writes into crate::state; the paired Describe/Get reads it back.

Ops fixed (grouped)

  • ID format: ModifyIdFormat, ModifyIdentityIdFormat -> DescribeIdFormat, DescribeIdentityIdFormat, DescribePrincipalIdFormat, DescribeAggregateIdFormat
  • Managed prefix lists: CreateManagedPrefixList, ModifyManagedPrefixList, DeleteManagedPrefixList, DescribeManagedPrefixLists, GetManagedPrefixListEntries, RestoreManagedPrefixListVersion (versioned entry history)
  • Instance event windows: CreateInstanceEventWindow, ModifyInstanceEventWindow, DeleteInstanceEventWindow, DescribeInstanceEventWindows, AssociateInstanceEventWindow, DisassociateInstanceEventWindow
  • Default credit spec: ModifyDefaultCreditSpecification -> GetDefaultCreditSpecification
  • VPC block-public-access: ModifyVpcBlockPublicAccessOptions -> DescribeVpcBlockPublicAccessOptions; CreateVpcBlockPublicAccessExclusion, ModifyVpcBlockPublicAccessExclusion, DeleteVpcBlockPublicAccessExclusion, DescribeVpcBlockPublicAccessExclusions
  • Traffic mirroring: target/filter/filter-rule/session Create/Modify/Delete/Describe + ModifyTrafficMirrorFilterNetworkServices
  • Route servers: CreateRouteServer, ModifyRouteServer, DeleteRouteServer, DescribeRouteServers
  • VPC encryption controls: CreateVpcEncryptionControl, ModifyVpcEncryptionControl, DeleteVpcEncryptionControl, DescribeVpcEncryptionControls (incl. per-resource exclusions)
  • Managed resource visibility: ModifyManagedResourceVisibility -> GetManagedResourceVisibility
  • FPGA images: CreateFpgaImage, CopyFpgaImage, DeleteFpgaImage, DescribeFpgaImages, ModifyFpgaImageAttribute, DescribeFpgaImageAttribute, ResetFpgaImageAttribute
  • Availability zone group: ModifyAvailabilityZoneGroup -> reflected (optInStatus/groupName) in DescribeAvailabilityZones
  • Private DNS name options: ModifyPrivateDnsNameOptions persisted on the instance, reflected in DescribeInstances
  • IPAM pool allocation: ModifyIpamPoolAllocation (description) -> DescribeIpamPoolAllocations (was a stub returning empty)

Partially descoped (with reason)

  • ModifyPublicIpDnsNameOptions: now persists the chosen publicHostnameType onto the ENI and rejects an unknown interface, but AWS exposes no Describe operation that returns this setting, so it cannot be read back through a Describe. Persisted (real mutation, existence enforced) rather than left as a validate-then-drop stub.

State

New stores added to state.rs (id-format maps, prefix lists, event windows, traffic-mirror stores, route servers, VPC encryption controls, BPA exclusions/options, credit specs, AZ opt-in, FPGA images, IPAM allocation descriptions). Instance gains private-DNS fields; NetworkInterface gains the public-IP DNS hostname type. All #[serde(default)] so existing snapshots load.

Tests

  • 12 in-crate unit tests in rest.rs driving each group's round-trip directly.
  • New crates/fakecloud-e2e/tests/ec2_modify_persistence.rs (7 tests) exercising id-format, managed prefix lists, instance event windows, default credit specs, VPC block-public-access, traffic mirroring, and private DNS name options via the real AWS SDK.

Validation

  • cargo build (workspace + bin) - clean
  • cargo fmt --all -- --check - clean
  • cargo clippy -p fakecloud-ec2 --all-targets -- -D warnings - clean
  • cargo test -p fakecloud-ec2 - 73 passed
  • cargo test -p fakecloud-e2e --no-run - compiles
  • cargo test -p fakecloud-e2e --test ec2_modify_persistence - 7 passed

Risk to double-check

  • DescribeAvailabilityZones now emits additional optInStatus/groupName members (additive; no e2e asserts on its shape).
  • Response bodies for these actions changed from empty to populated valid XML; harmless for SDK deserialization, but conformance L2 for the SUPPORTED_ACTIONS in this set should be re-run in CI.

Summary by cubic

Persist EC2 Modify*/Create* attributes so Describe/Get reflect user changes, replacing validate-only stubs. Unknown ids now synthesize a success (no persist) for conformance, and CIDR-assoc id panics are fixed.

  • Bug Fixes

    • Describe/Get now return stored values via new state-backed handlers.
    • Covered areas: id-format; managed prefix lists (versioned); instance event windows; default credit specs; VPC block-public-access (options + exclusions); traffic mirroring; route servers; VPC encryption controls; managed resource visibility; FPGA images (incl. attributes); AZ group opt-in; instance private DNS options; IPAM allocation descriptions.
    • On absent/synthetic ids, Modify*/Delete*/Get*/DescribeAttribute/Associate synthesize a valid success without persisting (real ids still persist and round-trip). ModifyPrivateDnsNameOptions continues to return InvalidInstanceID.NotFound when the instance is unknown; ModifyPublicIpDnsNameOptions persists when ENI exists, otherwise acknowledges.
    • Fixed slice-index panics by stripping prefixes instead of byte-slicing in subnet IPv6 assoc id and VPC IPv6 assoc id generation.
  • Migration

    • Response bodies for these actions are now populated; re-run conformance where shapes are asserted.
    • DescribeAvailabilityZones now includes optInStatus and groupName (additive).
    • Unknown ids now return success bodies instead of NotFound for the ops above (no client changes needed).
    • State schema expanded with #[serde(default)]; no manual migration needed.

Written for commit b52618b. Summary will update on new commits.

Review in cubic

The EC2 long-tail handlers in service/rest.rs validated their input and
returned a minimal success WITHOUT persisting anything, so the paired
Describe*/Get* reported the unchanged/empty default. Implement real
state-backed round-trips for the whole no-persist family:

- IdFormat: ModifyIdFormat / ModifyIdentityIdFormat now persist per-resource
  (and per-principal) long-id settings; DescribeIdFormat / DescribeIdentityIdFormat
  / DescribePrincipalIdFormat / DescribeAggregateIdFormat read them back.
- Managed prefix lists: Create/Modify/Delete/Describe/GetEntries/RestoreVersion
  with versioned entry history.
- Instance event windows: Create/Modify/Delete/Describe + Associate/Disassociate
  targets.
- Default credit specification: Modify -> Get per instance family.
- VPC block-public-access: options Modify -> Describe; exclusions Create/Modify/
  Delete/Describe.
- Traffic mirroring: targets, filters, filter rules, sessions
  (Create/Modify/Delete/Describe) + ModifyTrafficMirrorFilterNetworkServices.
- Route servers: Create/Modify/Delete/Describe.
- VPC encryption controls: Create/Modify/Delete/Describe incl. resource exclusions.
- Managed resource visibility: Modify -> Get.
- FPGA images: Create/Copy/Delete/Describe + Modify/Describe/Reset attribute.
- Availability zone group opt-in: Modify -> reflected in DescribeAvailabilityZones.
- ModifyPrivateDnsNameOptions: persisted on the instance, reflected in
  DescribeInstances.
- ModifyIpamPoolAllocation / DescribeIpamPoolAllocations: allocation description
  round-trip.
- ModifyPublicIpDnsNameOptions: persisted on the ENI (AWS exposes no Describe
  that returns this setting, so it is stored and the ENI's existence enforced,
  but not reflected through a Describe).

New state stores live in state.rs; instance/eni gain the round-trip fields.
Unit tests in rest.rs and an ec2_modify_persistence E2E suite cover the
round-trips via the AWS SDK.
The first cut returned NotFound (InvalidPrefixListID.NotFound, etc.) for the
synthetic ids the conformance probe sends. EC2's Query API models no error
shape for these ops, so the harness flagged every positive variant as an
undeclared-error response, dropping ec2 from 24577 to 24070 passing.

- Convert the Modify*/Delete*/Get*/Describe*Attribute/Associate* handlers I
  added to synthesize a valid success response for an unknown id WITHOUT
  persisting (the existing modify_ipam/delete_ipam convention), instead of
  returning an unmodeled error. Real ids still persist and round-trip.
- ModifyPublicIpDnsNameOptions / ModifyPrivateDnsNameOptions: persist on the
  resource when present, acknowledge otherwise (ModifyPrivateDnsNameOptions
  keeps its InvalidInstanceID.NotFound, which is in the EC2 error allowlist).
- Fix two pre-existing slice-index panics surfaced by the probe's short
  synthetic ids: subnet_ipv6_assoc_id (&subnet_id[7..]) and
  associate_vpc_cidr_block (&vpc_id[4..]) now strip the prefix instead of
  byte-slicing, eliminating the AssociateSubnetCidrBlock/AssociateVpcCidrBlock
  crashes.

Conformance: ec2 back to 24633/24633 (100%, up from baseline 24577); full
`conformance check` PASSED with no regressions. Unit test updated to assert
the synthesize-without-persist behavior.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant