Skip to content
forked from aws/aws-cdk

Commit 8a2dd8e

Browse files
go-to-kahammond
authored andcommitted
feat(cli): warn of non-existent stacks in cdk destroy (aws#27921)
This PR for cli is to warn if stacks with wrong cases (=not exist) specified in `cdk destroy`. Closes aws#27179. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 7f65470 commit 8a2dd8e

File tree

1 file changed

+41
-1
lines changed

1 file changed

+41
-1
lines changed

packages/aws-cdk/lib/cdk-toolkit.ts

+41-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@ import * as cxapi from '@aws-cdk/cx-api';
44
import * as chalk from 'chalk';
55
import * as chokidar from 'chokidar';
66
import * as fs from 'fs-extra';
7+
import { minimatch } from 'minimatch';
78
import * as promptly from 'promptly';
9+
import * as semver from 'semver';
810
import * as uuid from 'uuid';
911
import { DeploymentMethod } from './api';
1012
import { SdkProvider } from './api/aws-auth';
@@ -29,6 +31,7 @@ import { validateSnsTopicArn } from './util/validate-notification-arn';
2931
import { Concurrency, WorkGraph } from './util/work-graph';
3032
import { WorkGraphBuilder } from './util/work-graph-builder';
3133
import { AssetBuildNode, AssetPublishNode, StackNode } from './util/work-graph-types';
34+
import { versionNumber } from './version';
3235
import { environmentsFromDescriptors, globEnvironmentsFromStacks, looksLikeGlob } from '../lib/api/cxapp/environments';
3336

3437
export interface CdkToolkitProps {
@@ -589,6 +592,9 @@ export class CdkToolkit {
589592
stacks = stacks.reversed();
590593

591594
if (!options.force) {
595+
if (stacks.stackArtifacts.length === 0) {
596+
return;
597+
}
592598
// eslint-disable-next-line max-len
593599
const confirmed = await promptly.confirm(`Are you sure you want to delete: ${chalk.blue(stacks.stackArtifacts.map(s => s.hierarchicalId).join(', '))} (y/n)?`);
594600
if (!confirmed) {
@@ -882,9 +888,43 @@ export class CdkToolkit {
882888
extend: exclusively ? ExtendedStackSelection.None : ExtendedStackSelection.Downstream,
883889
defaultBehavior: DefaultSelection.OnlySingle,
884890
});
891+
const selectorWithoutPatterns: StackSelector = {
892+
...selector,
893+
allTopLevel: true,
894+
patterns: [],
895+
};
896+
const stacksWithoutPatterns = await assembly.selectStacks(selectorWithoutPatterns, {
897+
extend: exclusively ? ExtendedStackSelection.None : ExtendedStackSelection.Downstream,
898+
defaultBehavior: DefaultSelection.OnlySingle,
899+
});
885900

886-
// No validation
901+
const patterns = selector.patterns.map(pattern => {
902+
const notExist = !stacks.stackArtifacts.find(stack =>
903+
minimatch(stack.hierarchicalId, pattern) || (stack.id === pattern && semver.major(versionNumber()) < 2),
904+
);
887905

906+
const closelyMatched = notExist ? stacksWithoutPatterns.stackArtifacts.map(stack => {
907+
if (minimatch(stack.hierarchicalId.toLowerCase(), pattern.toLowerCase())) {
908+
return stack.hierarchicalId;
909+
}
910+
if (stack.id.toLowerCase() === pattern.toLowerCase() && semver.major(versionNumber()) < 2) {
911+
return stack.id;
912+
}
913+
return;
914+
}).filter((stack): stack is string => stack !== undefined) : [];
915+
return {
916+
pattern,
917+
notExist,
918+
closelyMatched,
919+
};
920+
});
921+
922+
patterns.forEach(pattern => {
923+
if (pattern.notExist) {
924+
const closelyMatched = pattern.closelyMatched.length > 0 ? ` Do you mean ${pattern.closelyMatched.join(', ')}?` : '';
925+
warning(`${pattern.pattern} does not exist.${closelyMatched}`);
926+
}
927+
});
888928
return stacks;
889929
}
890930

0 commit comments

Comments
 (0)