Skip to content

(cloudformation-diff): changeImpact reports WILL_DESTROY for removals with DeletionPolicy RetainExceptOnCreate (and Snapshot) #1882

Description

@devkobby24

Describe the bug

ResourceDifference.changeImpact classifies a resource removal as WILL_ORPHAN only when DeletionPolicy is exactly 'Retain'; every other value falls through to WILL_DESTROY:

https://github.com/aws/aws-cdk-cli/blob/main/packages/%40aws-cdk/cloudformation-diff/lib/diff/types.ts#L725-L727

      if (this.resourceTypes.newType === undefined) {
        return this.oldValue!.DeletionPolicy === 'Retain'
          ? ResourceImpact.WILL_ORPHAN
          : ResourceImpact.WILL_DESTROY;
      }

The strings RetainExceptOnCreate and Snapshot do not appear anywhere else in the package, so there is no compensating handling.

Two distinct problems:

  1. RetainExceptOnCreateWILL_DESTROY is incorrect. For any resource that was successfully created, RetainExceptOnCreate behaves identically to Retain on stack update and delete — the physical resource is retained (DeletionPolicy attribute documentation). Since a resource being removed from an existing stack was by definition created previously, WILL_ORPHAN is the correct impact in effectively all cases this code path evaluates.

  2. SnapshotWILL_DESTROY is misleading and undocumented. The physical resource is deleted, but CloudFormation takes a final snapshot first, so the data is recoverable. That may be intentionally conservative for display purposes, but downstream consumers of changeImpact currently cannot distinguish "data destroyed" from "data recoverable from a snapshot." A dedicated impact (e.g. WILL_SNAPSHOT) would fix that; failing that, documenting on ResourceImpact.WILL_DESTROY that it also covers snapshot-protected deletions would at least make the behavior intentional.

Current Behavior

Observed impacts for a removed AWS::RDS::DBInstance by DeletionPolicy value (@aws-cdk/cloudformation-diff@2.187.3):

DeletionPolicy changeImpact Correct?
Delete WILL_DESTROY yes
Retain WILL_ORPHAN yes
RetainExceptOnCreate WILL_DESTROY no — resource is retained
Snapshot WILL_DESTROY misleading — final snapshot is taken

Reproduction Steps

const { fullDiff } = require('@aws-cdk/cloudformation-diff');

for (const policy of ['Delete', 'Retain', 'RetainExceptOnCreate', 'Snapshot']) {
  const before = { Resources: { Db: { Type: 'AWS::RDS::DBInstance', DeletionPolicy: policy } } };
  const after = { Resources: {} };
  console.log(String(policy).padEnd(22), '->', fullDiff(before, after).resources.get('Db').changeImpact);
}

Output:

Delete                 -> WILL_DESTROY
Retain                 -> WILL_ORPHAN
RetainExceptOnCreate   -> WILL_DESTROY
Snapshot               -> WILL_DESTROY

Expected Behavior

  • RetainExceptOnCreateWILL_ORPHAN
  • Snapshot → a dedicated impact, or explicit documentation that WILL_DESTROY includes snapshot-protected deletions

Possible Solution

For the clear-cut part:

return this.oldValue!.DeletionPolicy === 'Retain' || this.oldValue!.DeletionPolicy === 'RetainExceptOnCreate'
  ? ResourceImpact.WILL_ORPHAN
  : ResourceImpact.WILL_DESTROY;

Adding a WILL_SNAPSHOT member to ResourceImpact would address the second part, with the caveat that consumers switching exhaustively on the enum would see a new case. The === 'Retain' comparison occurs only at this one site in the package, so the fix is contained.

Environment

  • @aws-cdk/cloudformation-diff: 2.187.3 (also present on current main, permalink above)
  • Node.js: v24.18.0
  • OS: macOS 26.6.1

I'm happy to open a PR for the RetainExceptOnCreate fix referencing this issue, leaving the WILL_SNAPSHOT question to maintainers as an API decision.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions