Skip to content

Commit ad46b91

Browse files
committed
fix: improve nested stack check by using physical ids patterns instead of stack name based pattern
1 parent f11f080 commit ad46b91

File tree

2 files changed

+26
-20
lines changed

2 files changed

+26
-20
lines changed

reference-artifacts/Custom-Scripts/lza-upgrade/src/config/global-config.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,6 +2237,7 @@ export class GlobalConfig implements t.TypeOf<typeof GlobalConfigTypes.globalCon
22372237
const aseaStacks: t.AseaStackInfo[] = [];
22382238
for (const account of mappingJson) {
22392239
this.externalLandingZoneResources?.accountsDeployedExternally.push(account.accountId);
2240+
let nestedStackPhysicalIds: string[] = [];
22402241
for (const stack of account.stacksAndResourceMapList) {
22412242
const phaseIdentifierIndex = stack.stackName.indexOf('Phase') + 5;
22422243
let phase = stack.stackName[phaseIdentifierIndex];
@@ -2249,6 +2250,11 @@ export class GlobalConfig implements t.TypeOf<typeof GlobalConfigTypes.globalCon
22492250
// Delete outputs from template. IMPORT_ASEA_RESOURCES stage will write required information into SSM Parameter Store.
22502251
// delete stack.template.Outputs;
22512252
await fs.promises.writeFile(templatePath, JSON.stringify(stack.template, null, 2));
2253+
for (const cfnResource of stack.resourceMap) {
2254+
if (cfnResource.resourceType == 'AWS::CloudFormation::Stack') {
2255+
nestedStackPhysicalIds.push(cfnResource.physicalResourceId);
2256+
}
2257+
}
22522258
aseaStacks.push({
22532259
accountId: account.accountId,
22542260
accountKey: account.accountKey,
@@ -2257,14 +2263,15 @@ export class GlobalConfig implements t.TypeOf<typeof GlobalConfigTypes.globalCon
22572263
resources: stack.resourceMap as t.CfnResourceType[],
22582264
templatePath,
22592265
phase,
2260-
/**
2261-
* ASEA creates Nested stacks only for Phase1 and Phase2 and "stack.stackName.substring(phaseIdentifierIndex)" doesn't include accountName in it.
2262-
* It is safe to use string include to check if stack is nestedStack or not.
2263-
* Other option is to check for resource type in "Resources.physicalResourceId" using stackName
2264-
*/
2265-
nestedStack: stack.stackName.substring(phaseIdentifierIndex).includes('NestedStack'),
2266+
nestedStack: stack.parentStack ? true : false,
22662267
});
22672268
}
2269+
for (const physicalId of nestedStackPhysicalIds) {
2270+
const nestedStack = aseaStacks.findIndex((stack) => physicalId.includes(`:stack/${stack.stackName}/`));
2271+
if (nestedStack > -1) {
2272+
aseaStacks[nestedStack].nestedStack = true;
2273+
}
2274+
}
22682275
}
22692276
return aseaStacks;
22702277
}

reference-artifacts/Custom-Scripts/lza-upgrade/src/resource-mapping.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -268,19 +268,26 @@ export class ResourceMapping {
268268
(stackAndResource): stackAndResource is Promise<StacksAndResourceMap> => stackAndResource !== undefined,
269269
);
270270
const stackAndResourcesList = await Promise.all(validStackAndResourcePromises);
271+
272+
const allNestedStacksPhysicalIds: string[] = stackAndResourcesList.flatMap((stack) =>
273+
stack.resourceMap
274+
.filter((resource) => resource.resourceType == 'AWS::CloudFormation::Stack')
275+
.map((resource) => resource.physicalResourceId),
276+
);
277+
271278
const allNestedStacks = stackAndResourcesList.filter((stackAndResource) =>
272-
stackAndResource.stackName.includes('NestedStack'),
279+
allNestedStacksPhysicalIds.find((physicalId) => physicalId.includes(`:stack/${stackAndResource.stackName}/`)),
273280
);
281+
282+
const allNestedStackNames = allNestedStacks.map((stackAndResource) => stackAndResource.stackName);
283+
274284
stackAndResourcesList.forEach((stackAndResource) => {
275285
const nestedStacks = this.getNestedStacks(stackAndResource, allNestedStacks);
276286
if (nestedStacks) {
277287
stackAndResource.nestedStacks = nestedStacks;
278288
}
279-
const parentStack = this.getParentStack(stackAndResource);
280-
if (parentStack) {
281-
stackAndResource.parentStack = parentStack;
282-
}
283-
if (!stackAndResource.stackName.includes('NestedStack')) {
289+
290+
if (!allNestedStackNames.includes(stackAndResource.stackName)) {
284291
stackAndResourceMap.set(
285292
`${stackAndResource.environment.accountId}-${stackAndResource.environment.region}-${stackAndResource.stackName}`,
286293
stackAndResource,
@@ -291,14 +298,6 @@ export class ResourceMapping {
291298
return stackAndResourceMap;
292299
}
293300

294-
getParentStack(stackAndResource: StacksAndResourceMap) {
295-
if (stackAndResource.stackName.includes('NestedStack')) {
296-
const stackNameArr = stackAndResource.stackName.split('-');
297-
return `${stackAndResource.environment.accountId}|${stackAndResource.environment.region}|${stackNameArr[0]}-${stackNameArr[1]}-${stackNameArr[2]}`;
298-
}
299-
return undefined;
300-
}
301-
302301
getNestedStacks(stackAndResource: StacksAndResourceMap, nestedStacks: StacksAndResourceMap[]) {
303302
const phaseIndex = stackAndResource.stackName.toLowerCase().indexOf('phase');
304303
// checks the length of the stack to determine if it is the nested stack or parent stack

0 commit comments

Comments
 (0)