diff --git a/packages/aws-cdk/lib/api/nested-stack-helpers.ts b/packages/aws-cdk/lib/api/nested-stack-helpers.ts index acbbb1e2a9245..26d0086d859c9 100644 --- a/packages/aws-cdk/lib/api/nested-stack-helpers.ts +++ b/packages/aws-cdk/lib/api/nested-stack-helpers.ts @@ -1,5 +1,6 @@ import * as path from 'path'; import * as cxapi from '@aws-cdk/cx-api'; +import { CloudFormation } from 'aws-sdk'; import * as fs from 'fs-extra'; import { ISDK } from './aws-auth'; import { LazyListStackResources, ListStackResources } from './evaluate-cloudformation-template'; @@ -20,6 +21,14 @@ export interface TemplateWithNestedStackCount { readonly nestedStackCount: number; } +export type NestedChangeSet = CloudFormation.DescribeChangeSetOutput & { + Changes?: CloudFormation.Changes & { + ResourceChange?: { + NestedChanges?: CloudFormation.DescribeChangeSetOutput | NestedChangeSet, + }, + }[], +}; + /** * Reads the currently deployed template from CloudFormation and adds a * property, `NestedTemplate`, to any nested stacks that appear in either @@ -68,6 +77,27 @@ export async function loadCurrentTemplate( return loadCurrentStackTemplate(stackArtifact.stackName, sdk, retrieveProcessedTemplate); } +/** + * inlines changesets of all nested stacks in rootChangeSet into rootChangeSet + */ +export async function populateNestedChangeSet(rootChangeSet: NestedChangeSet, cfn: CloudFormation) { + const changes = rootChangeSet.Changes; + if (changes) { + for (const change of changes) { + if (change.Type === 'Resource' && change.ResourceChange) { + if (change.ResourceChange && change.ResourceChange.ResourceType === 'AWS::CloudFormation::Stack') { + const nestedChangeSetId = change.ResourceChange.ChangeSetId; + const nestedChangeSet = await cfn.describeChangeSet({ + ChangeSetName: nestedChangeSetId!, + }).promise(); + await populateNestedChangeSet(nestedChangeSet, cfn); + change.ResourceChange.NestedChanges = nestedChangeSet; + } + } + } + } +} + async function loadCurrentStackTemplate( stackName: string, sdk: ISDK, retrieveProcessedTemplate: boolean = false, ) : Promise