Skip to content

Commit 5a6ab77

Browse files
fix: Handling nested stack
1 parent 4cdd371 commit 5a6ab77

File tree

1 file changed

+73
-10
lines changed

1 file changed

+73
-10
lines changed

src/frameworks/samFramework.ts

Lines changed: 73 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,12 @@ export class SamFramework implements IFramework {
110110

111111
const lambdas: any[] = [];
112112

113-
// get all resources of type AWS::Serverless::Function
114-
for (const resourceName in template.Resources) {
115-
const resource = template.Resources[resourceName];
116-
if (resource.Type === 'AWS::Serverless::Function') {
117-
lambdas.push({
118-
Name: resourceName,
119-
...resource,
120-
});
121-
}
122-
}
113+
// Recursively parse templates to find all Lambda functions, including those in nested stacks
114+
await this.parseLambdasFromTemplate(
115+
template,
116+
path.dirname(path.resolve(samTemplateFile)),
117+
lambdas,
118+
);
123119

124120
const lambdasDiscovered: LambdaResource[] = [];
125121

@@ -130,11 +126,19 @@ export class SamFramework implements IFramework {
130126
awsConfiguration,
131127
);
132128

129+
const stackAndNestedStackNames = [
130+
...new Set(lambdasInStack.map((l) => l.stackName)),
131+
];
132+
133133
Logger.verbose(
134134
`[SAM] Found Lambdas in stack ${stackName}:`,
135135
JSON.stringify(lambdasInStack, null, 2),
136136
);
137137

138+
Logger.verbose(
139+
`[SAM] Found the following stacks and nested stacks: ${stackAndNestedStackNames.join(', ')}`,
140+
);
141+
138142
// get tags for each Lambda
139143
for (const func of lambdas) {
140144
const handlerFull = path.join(
@@ -221,6 +225,65 @@ export class SamFramework implements IFramework {
221225

222226
return lambdasDiscovered;
223227
}
228+
229+
/**
230+
* Recursively parse templates to find all Lambda functions, including nested stacks
231+
* @param template The parsed CloudFormation/SAM template
232+
* @param templateDir The directory containing the template file
233+
* @param lambdas The array to collect Lambda functions into
234+
*/
235+
private async parseLambdasFromTemplate(
236+
template: any,
237+
templateDir: string,
238+
lambdas: any[],
239+
): Promise<void> {
240+
if (!template.Resources) {
241+
return;
242+
}
243+
244+
for (const resourceName in template.Resources) {
245+
const resource = template.Resources[resourceName];
246+
247+
// Check if it's a Lambda function
248+
if (resource.Type === 'AWS::Serverless::Function') {
249+
lambdas.push({
250+
Name: resourceName,
251+
...resource,
252+
});
253+
}
254+
// Check if it's a nested stack
255+
else if (
256+
resource.Type === 'AWS::Serverless::Application' ||
257+
resource.Type === 'AWS::CloudFormation::Stack'
258+
) {
259+
const nestedTemplateLocation = resource.Properties?.Location;
260+
if (nestedTemplateLocation) {
261+
try {
262+
const nestedTemplatePath = path.resolve(
263+
templateDir,
264+
nestedTemplateLocation,
265+
);
266+
const nestedTemplateContent = await fs.readFile(
267+
nestedTemplatePath,
268+
'utf-8',
269+
);
270+
const nestedTemplate = yaml.parse(nestedTemplateContent);
271+
272+
// Recursively parse the nested template
273+
await this.parseLambdasFromTemplate(
274+
nestedTemplate,
275+
path.dirname(nestedTemplatePath),
276+
lambdas,
277+
);
278+
} catch (err: any) {
279+
Logger.warn(
280+
`[SAM] Could not parse nested template at ${nestedTemplateLocation}: ${err.message}`,
281+
);
282+
}
283+
}
284+
}
285+
}
286+
}
224287
}
225288

226289
export const samFramework = new SamFramework();

0 commit comments

Comments
 (0)