A CLI tool to force delete CloudFormation Stacks
Tags: aws, awscommunitybuilder, cloudformation, cdk
Published: 2023-03-13 15:18:06

A CloudFormation (or AWS CDK, etc...) stack sometimes fail to be deleted (for the status of DELETE_FAILED). For example, when the stack contains: non-empty S3 or ECR, etc...

So I have released a CLI tool in OSS that can force delete the **entire** AWS CloudFormation stack with just one command, **even if it contains resources that fail to delete by the CloudFormation delete operation**.

The name of this tool is **delstack**, and it is implemented in golang.(see [the GitHub Link](https://github.com/go-to-k/delstack)!)

## Resource Types that can be forced to delete

Among the resources that fail in the normal CloudFormation stack deletion, this tool supports the following resources.

If you want to delete the unsupported resources, please create an issue at [GitHub](https://github.com/go-to-k/delstack/issues).

All resources that do not fail normal deletion can be deleted as is.

|  RESOURCE TYPE  |  DETAILS  |
| ---- | ---- |
|  AWS::S3::Bucket  |  S3 Buckets, including buckets with **Non-empty or Versioning enabled** and DeletionPolicy **not Retain**.(Because "Retain" buckets should not be deleted.)  |
|  AWS::IAM::Role  |  IAM Roles, including roles **with policies from outside the stack**.  |
|  AWS::ECR::Repository  |  ECR Repositories, including repositories **containing images**.  |
|  AWS::Backup::BackupVault  |  Backup Vaults, including vaults **containing recovery points**.  |
|  AWS::CloudFormation::Stack  |  **Nested Child Stacks** that failed to delete. If any of the other resources are included in the child stack, **they too will be deleted**.  |
|  Custom::Xxx  |  Custom Resources, but they will be deleted on its own.  |

This tool can be used **even for stacks that do not contain any of the above targets** for forced deletion. So **all stack deletions can basically be done with this tool!!**

Rest assured! **"Termination Protection" stacks will not be deleted.** Because it probably really should not want to delete it.

Deletion of resources that fail to be deleted because they are used by other stack resources, i.e., **resources that are referenced (depended on) from outside the stack, is not supported**. Only forced deletion of resources that can be completed only within the stack is supported.

## Interactive Mode

### StackName Selection

If you do not specify a stack name in command options in the interactive mode (`-i, --interactive`), you can search stack names in a **case-insensitive** and select a stack.

It can be **empty**.

```sh
❯ delstack -i
Filter a keyword of stack names(case-insensitive): goto
```

Then you select stack names in the UI.

```sh
? Select StackNames.
Nested child stacks, XXX_IN_PROGRESS(e.g. ROLLBACK_IN_PROGRESS) status stacks and EnableTerminationProtection stacks are not displayed.
  [Use arrows to move, space to select, <right> to all, <left> to none, type to filter]
  [x]  dev-goto-04-TestStack
  [ ]  dev-GOTO-03-TestStack
> [x]  dev-Goto-02-TestStack
  [ ]  dev-goto-01-TestStack
```

### ResourceTypes

The `-i, --interactive` option allows you to select the ResourceTypes **you wish to force delete even if DELETE_FAILED**. This feature allows you to **protect resources** you really do not want to delete by **"do not select the ResourceTypes"**!

However, if a resource can be deleted **without becoming DELETE_FAILED** by the **normal** CloudFormation stack deletion feature, the resource will be deleted **even if you do not select that resource type**. This tool is not intended to protect specific resources from the normal CloudFormation stack deletion feature, so I implemented this feature with the nuance that **only those resources that really should not be deleted will not be forced to be deleted**.

```sh
❯ delstack -i -s dev-goto-01-TestStack
? dev-goto-01-TestStack
Select ResourceTypes you wish to delete even if DELETE_FAILED.
However, if a resource can be deleted without becoming DELETE_FAILED by the normal CloudFormation stack deletion feature, the resource will be deleted even if you do not select that resource type.
  [Use arrows to move, space to select, <right> to all, <left> to none, type to filter]
  [x]  AWS::S3::Bucket
  [ ]  AWS::IAM::Role
> [x]  AWS::ECR::Repository
  [ ]  AWS::Backup::BackupVault
  [ ]  AWS::CloudFormation::Stack
  [ ]  Custom::
```

## GitHub Actions

You can use delstack with parameters **"stack-name" and "region"** in GitHub Actions Workflow. To delete multiple stacks, specify stack names separated by commas.

```yaml
jobs:
  delstack:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v3
        with:
          role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
          # Or specify access keys.
          # aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          # aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1
      - name: Delete stack
        uses: go-to-k/delstack@main # Or specify the version instead of main
        with:
          stack-name: YourStack
          # stack-name: YourStack1, YourStack2, YourStack3 # To delete multiple stacks
          region: us-east-1
```

You can also run raw commands after installing the delstack binary.

```yaml
jobs:
  delstack:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v3
      - name: Configure AWS credentials
        uses: aws-actions/configure-aws-credentials@v3
        with:
          role-to-assume: arn:aws:iam::123456789100:role/my-github-actions-role
          # Or specify access keys.
          # aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          # aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: us-east-1
      - name: Install delstack
        uses: go-to-k/delstack@main # Or specify the version instead of main
      - name: Run delstack
        run: |
          echo "delstack"
          delstack -v
          delstack -s YourStack1 -s YourStack2 -r us-east-1
```

## Finally

Please feel free to use [this tool](https://github.com/go-to-k/delstack)! I would be happy to help you.
Have fun with CloudFormation and CDK!