Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ describe('createUnifiedCategoryView', () => {
ResourceType: 'AWS::CloudFormation::Stack',
Action: ChangeAction.Modify,
ChangeSetId: nestedChangeSetId,
PhysicalResourceId: 'arn:aws:cloudformation:us-east-1:123:stack/nested-api-stack/abc',
nestedChanges: [
{
LogicalResourceId: 'Schema',
Expand All @@ -173,12 +174,12 @@ describe('createUnifiedCategoryView', () => {
"
API Schema
Template Drift: S3 and deployed templates differ
Changeset Id: https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/changesets/details?changeSetId=arn%3Aaws%3Acloudformation%3Aus-east-1%3A123%3AchangeSet%2Fnested-api-cs%2Fdef
Changeset Id: https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/changesets/changes?stackId=arn%3Aaws%3Acloudformation%3Aus-east-1%3A123%3Astack%2Fnested-api-stack%2Fabc&changeSetId=arn%3Aaws%3Acloudformation%3Aus-east-1%3A123%3AchangeSet%2Fnested-api-cs%2Fdef
~ AWS::AppSync::GraphQLSchema

API NewResolver
Template Drift: S3 and deployed templates differ
Changeset Id: https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/changesets/details?changeSetId=arn%3Aaws%3Acloudformation%3Aus-east-1%3A123%3AchangeSet%2Fnested-api-cs%2Fdef
Changeset Id: https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/changesets/changes?stackId=arn%3Aaws%3Acloudformation%3Aus-east-1%3A123%3Astack%2Fnested-api-stack%2Fabc&changeSetId=arn%3Aaws%3Acloudformation%3Aus-east-1%3A123%3AchangeSet%2Fnested-api-cs%2Fdef
+ AWS::AppSync::Resolver

"
Expand Down Expand Up @@ -374,12 +375,14 @@ describe('createUnifiedCategoryView', () => {
ResourceType: 'AWS::CloudFormation::Stack',
Action: ChangeAction.Modify,
ChangeSetId: outerChangeSetId,
PhysicalResourceId: 'arn:aws:cloudformation:us-east-1:123:stack/outer-stack/abc',
nestedChanges: [
{
LogicalResourceId: 'apiMyGraphQLGraphQLAPI',
ResourceType: 'AWS::CloudFormation::Stack',
Action: ChangeAction.Modify,
ChangeSetId: deepChangeSetId,
PhysicalResourceId: 'arn:aws:cloudformation:us-east-1:123:stack/deep-stack/ghi',
nestedChanges: [
{
LogicalResourceId: 'Schema',
Expand All @@ -399,7 +402,7 @@ describe('createUnifiedCategoryView', () => {
"
API Schema
Template Drift: S3 and deployed templates differ
Changeset Id: https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/changesets/details?changeSetId=arn%3Aaws%3Acloudformation%3Aus-east-1%3A123%3AchangeSet%2Fdeep-cs%2Fghi
Changeset Id: https://us-east-1.console.aws.amazon.com/cloudformation/home?region=us-east-1#/stacks/changesets/changes?stackId=arn%3Aaws%3Acloudformation%3Aus-east-1%3A123%3Astack%2Fdeep-stack%2Fghi&changeSetId=arn%3Aaws%3Acloudformation%3Aus-east-1%3A123%3AchangeSet%2Fdeep-cs%2Fghi
~ AWS::AppSync::GraphQLSchema

"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ interface DriftBlock {
driftDetectionId?: string;
templateChange?: ResourceChangeWithNested;
changeSetId?: string;
stackArn?: string;
}

/**
Expand Down Expand Up @@ -76,12 +77,12 @@ function cfnDriftConsoleUrl(stackArn: string): string | undefined {
/**
* Build CloudFormation console URL for a changeset details page
*/
function cfnChangesetConsoleUrl(changeSetArn: string): string | undefined {
function cfnChangesetConsoleUrl(changeSetArn: string, stackArn?: string): string | undefined {
const region = regionFromArn(changeSetArn);
if (!region) return undefined;
return `https://${region}.console.aws.amazon.com/cloudformation/home?region=${region}#/stacks/changesets/details?changeSetId=${encodeURIComponent(
changeSetArn,
)}`;
const encodedStackId = encodeURIComponent(stackArn || '');
const encodedChangeSetId = encodeURIComponent(changeSetArn);
return `https://${region}.console.aws.amazon.com/cloudformation/home?region=${region}#/stacks/changesets/changes?stackId=${encodedStackId}&changeSetId=${encodedChangeSetId}`;
}

/**
Expand Down Expand Up @@ -114,10 +115,20 @@ function collectDriftBlocks(phase1: CloudFormationDriftResults, phase2: Template

// Phase 2: One block per template change (flatten nested stacks to leaf resources)
if (!phase2.skipped && phase2.changes.length > 0) {
const flattenChanges = (changes: ResourceChangeWithNested[], fallbackCategory: string, fallbackChangeSetId?: string): void => {
const flattenChanges = (
changes: ResourceChangeWithNested[],
fallbackCategory: string,
fallbackChangeSetId?: string,
parentStackArn?: string,
): void => {
for (const change of changes) {
if (change.ResourceType === 'AWS::CloudFormation::Stack' && change.nestedChanges && change.nestedChanges.length > 0) {
flattenChanges(change.nestedChanges, extractCategory(change.LogicalResourceId), change.ChangeSetId || fallbackChangeSetId);
flattenChanges(
change.nestedChanges,
extractCategory(change.LogicalResourceId),
change.ChangeSetId || fallbackChangeSetId,
change.PhysicalResourceId || parentStackArn,
);
} else {
const resourceCategory = extractCategory(change.LogicalResourceId);
blocks.push({
Expand All @@ -126,6 +137,7 @@ function collectDriftBlocks(phase1: CloudFormationDriftResults, phase2: Template
type: 'template',
templateChange: change,
changeSetId: change.ChangeSetId || fallbackChangeSetId,
stackArn: parentStackArn,
});
}
}
Expand Down Expand Up @@ -210,7 +222,7 @@ function formatBlock(block: DriftBlock): string {

output += ` Template Drift: S3 and deployed templates differ\n`;
if (block.changeSetId) {
const changesetUrl = cfnChangesetConsoleUrl(block.changeSetId);
const changesetUrl = cfnChangesetConsoleUrl(block.changeSetId, block.stackArn);
output += ` Changeset Id: ${changesetUrl || block.changeSetId}\n`;
}
output += ` ${colorResourceLine(symbol, `${symbol} ${change.ResourceType || 'Unknown'}`)}\n`;
Expand Down
Loading