UNPKG

lambda-live-debugger

Version:

Debug Lambda functions locally like it is running in the cloud

137 lines (136 loc) 4.93 kB
import { AwsCredentials } from './awsCredentials.mjs'; import { Logger } from './logger.mjs'; import * as yaml from 'yaml'; let cloudFormationClient; const originalConsoleError = console.error; /** * Get CloudFormation stack template * @param stackName * @param awsConfiguration * @returns */ async function getCloudFormationStackTemplate(stackName, awsConfiguration) { const { GetTemplateCommand } = await import('@aws-sdk/client-cloudformation'); const command = new GetTemplateCommand({ StackName: stackName }); const cloudFormationClient = await getCloudFormationClient(awsConfiguration); try { const response = await cloudFormationClient.send(command); if (!response.TemplateBody) { throw new Error(`No template found for stack ${stackName}`); } let cfTemplate; try { cfTemplate = JSON.parse(response.TemplateBody); } catch (parseError) { if (parseError.message.includes('is not valid JSON')) { // If the template is not JSON, try parsing it as YAML cfTemplate = yaml.parse(response.TemplateBody); } else { throw parseError; } } return cfTemplate; } catch (error) { if (error.name === 'ValidationError') { Logger.error(`Stack ${stackName} not found. Try specifying a region. Error: ${error.message}`, error); return undefined; } else { throw error; } } } /** * Get CloudFormation client * @param awsConfiguration * @returns */ async function getCloudFormationClient(awsConfiguration) { if (!cloudFormationClient) { const { CloudFormationClient } = await import('@aws-sdk/client-cloudformation'); cloudFormationClient = new CloudFormationClient({ region: awsConfiguration.region, credentials: AwsCredentials.getCredentialsProvider(awsConfiguration), }); } return cloudFormationClient; } /** * Get CloudFormation resources * @param stackName * @param awsConfiguration * @returns */ async function getCloudFormationResources(stackName, awsConfiguration) { let ListStackResourcesCommand; // temporary disable console.error because SAM framework outputs useless errors try { console.error = function () { }; const clientCloudFormation = await import('@aws-sdk/client-cloudformation'); ListStackResourcesCommand = clientCloudFormation.ListStackResourcesCommand; } finally { console.error = originalConsoleError; } const cloudFormationClient = await getCloudFormationClient(awsConfiguration); try { let nextToken = undefined; const items = []; do { const command = new ListStackResourcesCommand({ StackName: stackName, NextToken: nextToken, }); const response = await cloudFormationClient.send(command); if (response.StackResourceSummaries) { items.push(...response.StackResourceSummaries); } nextToken = response.NextToken; } while (nextToken); return items; } catch (error) { if (error.name === 'ValidationError') { Logger.error(`Stack ${stackName} not found. Try specifying a region. Error: ${error.message}`, error); return undefined; } else { throw error; } } } /** * Get Lambdas in stack * @param stackName * @param awsConfiguration * @returns */ async function getLambdasInStack(stackName, awsConfiguration, stackLogicalId) { const response = await getCloudFormationResources(stackName, awsConfiguration); const lambdaResources = response?.filter((resource) => resource.ResourceType === 'AWS::Lambda::Function'); const nestedStacks = response?.filter((resource) => resource.ResourceType === 'AWS::CloudFormation::Stack'); const lambdas = lambdaResources?.map((resource) => { return { lambdaName: resource.PhysicalResourceId, logicalId: resource.LogicalResourceId, stackName: stackName, stackLogicalId: stackLogicalId ?? stackName, }; }) ?? []; const lambdasInNestedStacks = await Promise.all((nestedStacks ?? []).map(async (nestedStack) => { if (!nestedStack.PhysicalResourceId) return []; const lambdasInNestedStack = await getLambdasInStack(nestedStack.PhysicalResourceId, awsConfiguration, nestedStack.LogicalResourceId); return lambdasInNestedStack; })); const flattenedLambdasInNestedStacks = lambdasInNestedStacks.flat(); const allLambdas = [...lambdas, ...flattenedLambdasInNestedStacks]; return allLambdas; } export const CloudFormation = { getCloudFormationStackTemplate, getLambdasInStack, };