From a40b7ec175855a90e3483532e313347fe99f9ac7 Mon Sep 17 00:00:00 2001
From: Rico Hermans <rix0rrr@gmail.com>
Date: Fri, 10 Jan 2025 19:51:10 +0100
Subject: [PATCH] Revert "feat(cli): warn of non-existent stacks in `cdk
 destroy` (#32636)"

This reverts commit c199378667cb63ffe8636dda6b6316dcc6eb47e9.
---
 .../tests/cli-integ-tests/cli.integtest.ts    | 14 ----
 packages/aws-cdk/lib/cdk-toolkit.ts           | 54 ----------------
 packages/aws-cdk/test/cdk-toolkit.test.ts     | 64 -------------------
 3 files changed, 132 deletions(-)

diff --git a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cli.integtest.ts b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cli.integtest.ts
index 34526ece88265..f4736584a065f 100644
--- a/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cli.integtest.ts
+++ b/packages/@aws-cdk-testing/cli-integ/tests/cli-integ-tests/cli.integtest.ts
@@ -2634,20 +2634,6 @@ integTest('hotswap ECS deployment respects properties override', withDefaultFixt
   expect(describeServicesResponse.services?.[0].deploymentConfiguration?.maximumPercent).toEqual(ecsMaximumHealthyPercent);
 }));
 
-integTest('cdk destroy does not fail even if the stacks do not exist', withDefaultFixture(async (fixture) => {
-  const nonExistingStackName1 = 'non-existing-stack-1';
-  const nonExistingStackName2 = 'non-existing-stack-2';
-
-  await expect(fixture.cdkDestroy([nonExistingStackName1, nonExistingStackName2])).resolves.not.toThrow();
-}));
-
-integTest('cdk destroy with no force option exits without prompt if the stacks do not exist', withDefaultFixture(async (fixture) => {
-  const nonExistingStackName1 = 'non-existing-stack-1';
-  const nonExistingStackName2 = 'non-existing-stack-2';
-
-  await expect(fixture.cdk(['destroy', ...fixture.fullStackName([nonExistingStackName1, nonExistingStackName2])])).resolves.not.toThrow();
-}));
-
 async function listChildren(parent: string, pred: (x: string) => Promise<boolean>) {
   const ret = new Array<string>();
   for (const child of await fs.readdir(parent, { encoding: 'utf-8' })) {
diff --git a/packages/aws-cdk/lib/cdk-toolkit.ts b/packages/aws-cdk/lib/cdk-toolkit.ts
index 64fa955912e4d..32f6616e5cdb6 100644
--- a/packages/aws-cdk/lib/cdk-toolkit.ts
+++ b/packages/aws-cdk/lib/cdk-toolkit.ts
@@ -4,7 +4,6 @@ import * as cxapi from '@aws-cdk/cx-api';
 import * as chalk from 'chalk';
 import * as chokidar from 'chokidar';
 import * as fs from 'fs-extra';
-import { minimatch } from 'minimatch';
 import * as promptly from 'promptly';
 import * as uuid from 'uuid';
 import { DeploymentMethod, SuccessfulDeployStackResult } from './api';
@@ -800,16 +799,6 @@ export class CdkToolkit {
   public async destroy(options: DestroyOptions) {
     let stacks = await this.selectStacksForDestroy(options.selector, options.exclusively);
 
-    await this.suggestStacks({
-      selector: options.selector,
-      stacks,
-      exclusively: options.exclusively,
-    });
-    if (stacks.stackArtifacts.length === 0) {
-      warning(`No stacks match the name(s): ${chalk.red(options.selector.patterns.join(', '))}`);
-      return;
-    }
-
     // The stacks will have been ordered for deployment, so reverse them for deletion.
     stacks = stacks.reversed();
 
@@ -1173,49 +1162,6 @@ export class CdkToolkit {
     return stacks;
   }
 
-  private async suggestStacks(props: {
-    selector: StackSelector;
-    stacks: StackCollection;
-    exclusively?: boolean;
-  }) {
-    const assembly = await this.assembly();
-    const selectorWithoutPatterns: StackSelector = {
-      ...props.selector,
-      allTopLevel: true,
-      patterns: [],
-    };
-    const stacksWithoutPatterns = await assembly.selectStacks(selectorWithoutPatterns, {
-      extend: props.exclusively ? ExtendedStackSelection.None : ExtendedStackSelection.Downstream,
-      defaultBehavior: DefaultSelection.OnlySingle,
-    });
-
-    const patterns = props.selector.patterns.map(pattern => {
-      const notExist = !props.stacks.stackArtifacts.find(stack =>
-        minimatch(stack.hierarchicalId, pattern),
-      );
-
-      const closelyMatched = notExist ? stacksWithoutPatterns.stackArtifacts.map(stack => {
-        if (minimatch(stack.hierarchicalId.toLowerCase(), pattern.toLowerCase())) {
-          return stack.hierarchicalId;
-        }
-        return;
-      }).filter((stack): stack is string => stack !== undefined) : [];
-
-      return {
-        pattern,
-        notExist,
-        closelyMatched,
-      };
-    });
-
-    for (const pattern of patterns) {
-      if (pattern.notExist) {
-        const closelyMatched = pattern.closelyMatched.length > 0 ? ` Do you mean ${chalk.blue(pattern.closelyMatched.join(', '))}?` : '';
-        warning(`${chalk.red(pattern.pattern)} does not exist.${closelyMatched}`);
-      }
-    };
-  }
-
   /**
    * Validate the stacks for errors and warnings according to the CLI's current settings
    */
diff --git a/packages/aws-cdk/test/cdk-toolkit.test.ts b/packages/aws-cdk/test/cdk-toolkit.test.ts
index 5ae3a2f9a45ae..8dad7142baea7 100644
--- a/packages/aws-cdk/test/cdk-toolkit.test.ts
+++ b/packages/aws-cdk/test/cdk-toolkit.test.ts
@@ -953,70 +953,6 @@ describe('destroy', () => {
       });
     }).resolves;
   });
-
-  test('does not throw and warns if there are only non-existent stacks', async () => {
-    const toolkit = defaultToolkitSetup();
-
-    await toolkit.destroy({
-      selector: { patterns: ['Test-Stack-X', 'Test-Stack-Y'] },
-      exclusively: true,
-      force: true,
-      fromDeploy: true,
-    });
-
-    expect(flatten(stderrMock.mock.calls)).toEqual(
-      expect.arrayContaining([
-        expect.stringMatching(/Test-Stack-X does not exist./),
-        expect.stringMatching(/Test-Stack-Y does not exist./),
-        expect.stringMatching(/No stacks match the name\(s\): Test-Stack-X, Test-Stack-Y/),
-      ]),
-    );
-  });
-
-  test('does not throw and warns if there is a non-existent stack and the other exists', async () => {
-    const toolkit = defaultToolkitSetup();
-
-    await toolkit.destroy({
-      selector: { patterns: ['Test-Stack-X', 'Test-Stack-B'] },
-      exclusively: true,
-      force: true,
-      fromDeploy: true,
-    });
-
-    expect(flatten(stderrMock.mock.calls)).toEqual(
-      expect.arrayContaining([
-        expect.stringMatching(/Test-Stack-X does not exist./),
-      ]),
-    );
-    expect(flatten(stderrMock.mock.calls)).not.toEqual(
-      expect.arrayContaining([
-        expect.stringMatching(/Test-Stack-B does not exist./),
-      ]),
-    );
-    expect(flatten(stderrMock.mock.calls)).not.toEqual(
-      expect.arrayContaining([
-        expect.stringMatching(/No stacks match the name\(s\)/),
-      ]),
-    );
-  });
-
-  test('does not throw and suggests valid names if there is a non-existent but closely matching stack', async () => {
-    const toolkit = defaultToolkitSetup();
-
-    await toolkit.destroy({
-      selector: { patterns: ['test-stack-b'] },
-      exclusively: true,
-      force: true,
-      fromDeploy: true,
-    });
-
-    expect(flatten(stderrMock.mock.calls)).toEqual(
-      expect.arrayContaining([
-        expect.stringMatching(/test-stack-b does not exist. Do you mean Test-Stack-B?/),
-        expect.stringMatching(/No stacks match the name\(s\): test-stack-b/),
-      ]),
-    );
-  });
 });
 
 describe('watch', () => {