Skip to content

fsx: DeleteFileSystem wraps its body, reports an off-enum DELETED, and drops ClientRequestToken #1210

Description

@scttfrdmn

What

FSx's DeleteFileSystem answers a wrapped body where AWS publishes a flat one, reports a lifecycle
value the enum does not contain, and discards the idempotency token its page marks as the mechanism for
safe retries.

1. The response is wrapped

fsx_plugin.go:319-321 answers

{"FileSystem": {"FileSystemId": "fs-…", "Lifecycle": "DELETED", }}

API_DeleteFileSystem's Response Syntax is flat and publishes exactly three members:

{
  "FileSystemId": "string",
  "LifecycleStatus": "string",
  "WindowsResponse": { }
}

Two things are wrong at once: the extra FileSystem wrapper, and the member name — AWS publishes
LifecycleStatus on this operation, not Lifecycle (which is the member name on
API_FileSystem, a different shape). An SDK decoding the delete response reads neither member.

2. DELETED is not a published lifecycle value

fsx_plugin.go:310 writes Lifecycle = "DELETED". API_DeleteFileSystem's LifecycleStatus
publishes Valid Values: AVAILABLE | CREATING | FAILED | DELETING | MISCONFIGURED | UPDATING | MISCONFIGURED_UNAVAILABLE, and the operation's own prose says the file system moves to DELETING
the deletion is asynchronous, which is precisely the wait loop a consumer writes. DELETED appears
nowhere in the enum, so a consumer's while status == "DELETING" loop never starts and a
switch over the published values takes no branch.

3. ClientRequestToken is never read

API_DeleteFileSystem publishes ClientRequestToken with "(Optional) A string of up to 63 ASCII
characters that specifies the... idempotent deletion"
semantics, and API_CreateFileSystem
publishes the same member for creation. Substrate reads neither, so a retried delete or create with
the same token performs the operation twice rather than being recognised as a repeat. A consumer whose
retry logic depends on the token — which is what the token is for — cannot test it.

4. The stale comment that must go with this

fsx_errors.go:28-31 documents a 404-versus-400 divergence in FSx that does not exist: all three
not-found sites already answer http.StatusBadRequest (fsx_plugin.go:230, :244, :300), which is
what every FSx page publishes. The comment is a false claim about the tree, and it enlists FSx in a
cross-service sweep it does not belong to. Delete or rewrite it here, since this issue is already in
these files.

A second comment in the same area: fsx_plugin.go:75 names the X-Amz-Target prefix as
AmazonFSx.<Op>, where routing.go:310-317 and parser.go:305-307 both use
AWSSimbaAPIService_v20180301 — the real prefix, and the one AWS publishes. The comment describes a
prefix the code does not use.

Why this matters

The wrapped delete response is the sharpest of the four because it makes the successful path
undecodable while the failure paths decode fine — so a consumer's happy-path test is the one that
breaks, and it breaks in the SDK rather than at an assertion, which sends the reader looking in the
wrong place.

The DELETED value is the one that defeats a consumer's wait loop, and a deletion wait loop is
exactly the kind of poll/retry code CLAUDE.md says substrate exists to let a consumer test. A
lifecycle value outside the published enum means the loop cannot be written against substrate at all:
either it spins forever or it falls through every case.

The two false comments matter less but cost more than they look: fsx_errors.go:28-31 asserts a
divergence that is not there, so a future reader either "fixes" correct code to match a wrong comment,
or adds FSx to a sweep where it has no site. A comment that is wrong about the tree is worse than no
comment, because it is load-bearing for someone's next decision.

Acceptance criteria

  • DeleteFileSystem answers the flat published body with FileSystemId and LifecycleStatus,
    not a FileSystem wrapper, and includes WindowsResponse where the type calls for it.
  • The lifecycle value on deletion is DELETING, a published enum member. Decide whether the file
    system then progresses to absent through a seeded count of observations — which is what AWS's
    asynchronous prose describes — or is removed immediately, and record which; the
    terminal-at-birth issue in this batch owns the progression mechanism, so cross-reference rather
    than duplicate it.
  • ClientRequestToken is read on both CreateFileSystem and DeleteFileSystem, and a repeated
    token is recognised as a retry rather than performed twice. A test asserts a doubled call with
    one token has the effect of one call.
  • fsx_errors.go:28-31 is deleted or rewritten to describe the tree, and FSx is removed from any
    list of services with a 404-versus-400 divergence.
  • fsx_plugin.go:75 names the prefix the code actually matches.
  • A test asserts the raw JSON of the delete response against the published shape, following
    iam_shape_members_test.go:115 — a test decoding into substrate's own struct cannot see a
    wrapper.
  • docs/services.md's FSx section states the delete response shape, the lifecycle values FSx
    reports, and that the request token is honoured.

Provenance

The flat Response Syntax, the three published members, LifecycleStatus' Valid Values, the asynchronous
DELETING prose, and ClientRequestToken's idempotency semantics are all from
API_DeleteFileSystem and API_CreateFileSystem in the Amazon FSx API Reference; Lifecycle as
distinct from LifecycleStatus is from API_FileSystem. The AWSSimbaAPIService_v20180301 target
prefix is the one FSx publishes and the one substrate's own router uses.

In-tree: emulator/fsx_plugin.go:310, :319-321, :230, :244, :300, :75;
emulator/fsx_errors.go:28-31; emulator/routing.go:310-317; emulator/parser.go:305-307. Line
citations are from the tree at the commit this issue was filed against.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions