@@ -17,7 +17,7 @@ import type {
17
17
EnvironmentBootstrapResult ,
18
18
} from '../actions/bootstrap' ;
19
19
import { BootstrapSource } from '../actions/bootstrap' ;
20
- import { AssetBuildTime , HotswapMode , type DeployOptions } from '../actions/deploy' ;
20
+ import { AssetBuildTime , type DeployOptions , HotswapMode } from '../actions/deploy' ;
21
21
import {
22
22
buildParameterMap ,
23
23
createHotswapPropertyOverrides ,
@@ -28,7 +28,7 @@ import { type DestroyOptions } from '../actions/destroy';
28
28
import type { DiffOptions } from '../actions/diff' ;
29
29
import { appendObject , prepareDiff } from '../actions/diff/private' ;
30
30
import { type ListOptions } from '../actions/list' ;
31
- import type { RefactorOptions } from '../actions/refactor' ;
31
+ import type { MappingGroup , RefactorOptions } from '../actions/refactor' ;
32
32
import { type RollbackOptions } from '../actions/rollback' ;
33
33
import { type SynthOptions } from '../actions/synth' ;
34
34
import type { WatchOptions } from '../actions/watch' ;
@@ -50,21 +50,25 @@ import type { IoHelper } from '../api/io/private';
50
50
import { asIoHelper , IO , SPAN , withoutColor , withoutEmojis , withTrimmedWhitespace } from '../api/io/private' ;
51
51
import { CloudWatchLogEventMonitor , findCloudWatchLogGroups } from '../api/logs-monitor' ;
52
52
import { PluginHost } from '../api/plugin' ;
53
- import { AmbiguityError , ambiguousMovements , findResourceMovements , formatAmbiguousMappings , formatTypedMappings , fromManifestAndExclusionList , resourceMappings } from '../api/refactoring' ;
53
+ import {
54
+ AmbiguityError ,
55
+ ambiguousMovements ,
56
+ findResourceMovements ,
57
+ formatAmbiguousMappings ,
58
+ formatTypedMappings ,
59
+ fromManifestAndExclusionList ,
60
+ resourceMappings ,
61
+ usePrescribedMappings ,
62
+ } from '../api/refactoring' ;
63
+ import type { ResourceMapping } from '../api/refactoring/cloudformation' ;
54
64
import { ResourceMigrator } from '../api/resource-import' ;
55
65
import { tagsForStack } from '../api/tags' ;
56
66
import { DEFAULT_TOOLKIT_STACK_NAME } from '../api/toolkit-info' ;
57
- import type { Concurrency , AssetBuildNode , AssetPublishNode , StackNode } from '../api/work-graph' ;
67
+ import type { AssetBuildNode , AssetPublishNode , Concurrency , StackNode } from '../api/work-graph' ;
58
68
import { WorkGraphBuilder } from '../api/work-graph' ;
59
69
import type { AssemblyData , StackDetails , SuccessfulDeployStackResult } from '../payloads' ;
60
70
import { PermissionChangeType } from '../payloads' ;
61
- import {
62
- formatErrorMessage ,
63
- formatTime ,
64
- obscureTemplate ,
65
- serializeStructure ,
66
- validateSnsTopicArn ,
67
- } from '../util' ;
71
+ import { formatErrorMessage , formatTime , obscureTemplate , serializeStructure , validateSnsTopicArn } from '../util' ;
68
72
import { pLimit } from '../util/concurrency' ;
69
73
import { promiseWithResolvers } from '../util/promises' ;
70
74
@@ -967,27 +971,60 @@ export class Toolkit extends CloudAssemblySourceBuilder {
967
971
}
968
972
969
973
private async _refactor ( assembly : StackAssembly , ioHelper : IoHelper , options : RefactorOptions = { } ) : Promise < void > {
974
+ if ( options . mappings && options . exclude ) {
975
+ throw new ToolkitError ( "Cannot use both 'exclude' and 'mappings'." ) ;
976
+ }
977
+
978
+ if ( options . revert && ! options . mappings ) {
979
+ throw new ToolkitError ( "The 'revert' options can only be used with the 'mappings' option." ) ;
980
+ }
981
+
970
982
if ( ! options . dryRun ) {
971
983
throw new ToolkitError ( 'Refactor is not available yet. Too see the proposed changes, use the --dry-run flag.' ) ;
972
984
}
973
985
974
- const stacks = await assembly . selectStacksV2 ( ALL_STACKS ) ;
975
986
const sdkProvider = await this . sdkProvider ( 'refactor' ) ;
976
- const exclude = fromManifestAndExclusionList ( assembly . cloudAssembly . manifest , options . exclude ) ;
977
- const movements = await findResourceMovements ( stacks . stackArtifacts , sdkProvider , exclude ) ;
978
- const ambiguous = ambiguousMovements ( movements ) ;
979
- if ( ambiguous . length === 0 ) {
980
- const filteredStacks = await assembly . selectStacksV2 ( options . stacks ?? ALL_STACKS ) ;
981
- const mappings = resourceMappings ( movements , filteredStacks . stackArtifacts ) ;
987
+ try {
988
+ const mappings = await getMappings ( ) ;
982
989
const typedMappings = mappings . map ( m => m . toTypedMapping ( ) ) ;
983
990
await ioHelper . notify ( IO . CDK_TOOLKIT_I8900 . msg ( formatTypedMappings ( typedMappings ) , {
984
991
typedMappings,
985
992
} ) ) ;
986
- } else {
987
- const error = new AmbiguityError ( ambiguous ) ;
988
- const paths = error . paths ( ) ;
989
- await ioHelper . notify ( IO . CDK_TOOLKIT_I8900 . msg ( formatAmbiguousMappings ( paths ) , {
990
- ambiguousPaths : paths ,
993
+ } catch ( e ) {
994
+ if ( e instanceof AmbiguityError ) {
995
+ const paths = e . paths ( ) ;
996
+ await ioHelper . notify ( IO . CDK_TOOLKIT_I8900 . msg ( formatAmbiguousMappings ( paths ) , {
997
+ ambiguousPaths : paths ,
998
+ } ) ) ;
999
+ } else {
1000
+ throw e ;
1001
+ }
1002
+ }
1003
+
1004
+ async function getMappings ( ) : Promise < ResourceMapping [ ] > {
1005
+ if ( options . revert ) {
1006
+ return usePrescribedMappings ( revert ( options . mappings ?? [ ] ) , sdkProvider ) ;
1007
+ }
1008
+ if ( options . mappings != null ) {
1009
+ return usePrescribedMappings ( options . mappings ?? [ ] , sdkProvider ) ;
1010
+ } else {
1011
+ const stacks = await assembly . selectStacksV2 ( ALL_STACKS ) ;
1012
+ const exclude = fromManifestAndExclusionList ( assembly . cloudAssembly . manifest , options . exclude ) ;
1013
+ const movements = await findResourceMovements ( stacks . stackArtifacts , sdkProvider , exclude ) ;
1014
+ const ambiguous = ambiguousMovements ( movements ) ;
1015
+ if ( ambiguous . length === 0 ) {
1016
+ const filteredStacks = await assembly . selectStacksV2 ( options . stacks ?? ALL_STACKS ) ;
1017
+ return resourceMappings ( movements , filteredStacks . stackArtifacts ) ;
1018
+ } else {
1019
+ throw new AmbiguityError ( ambiguous ) ;
1020
+ }
1021
+ }
1022
+ }
1023
+
1024
+ function revert ( mappings : MappingGroup [ ] ) : MappingGroup [ ] {
1025
+ return mappings . map ( group => ( {
1026
+ ...group ,
1027
+ resources : Object . fromEntries ( Object . entries ( group . resources ) . map ( ( [ src , dst ] ) => ( [ dst , src ] ) ) ) ,
991
1028
} ) ) ;
992
1029
}
993
1030
}
0 commit comments