AWS CDK自定义资源触发Lambda改日志保留期报错求助
问题:CloudFormation自定义资源Lambda报错
index.onEvent is undefined or not exported及日志查看问题 我需要修改/aws/codebuild/路径下CloudFormation日志的保留期来节约成本,已基于AWS Custom Resource做测试和调研,希望在onCreate、onUpdate、onDelete事件中触发Lambda脚本。但调试时出现问题:运行函数后收到错误提示:
Received response status [FAILED] from custom resource. Message returned: index.onEvent is undefined or not exported
且函数回滚后无法查看更多日志,现需相关解决指引。
相关代码
Custom-resource.ts
import * as cdk from "@aws-cdk/core"; import * as cr from "@aws-cdk/custom-resources"; import * as lambda from "@aws-cdk/aws-lambda"; import * as path from "path"; export class CfCustomResource extends cdk.Stack { constructor(scope: cdk.Construct, id: string, props?: CfStackProps) { super(scope, id, props); const retention = new lambda.Function(this, "OnEventFunction", { memorySize: 512, timeout: cdk.Duration.seconds(120), runtime: lambda.Runtime.NODEJS_14_X, handler: "onEvent", code: lambda.Code.fromAsset(path.join(__dirname, 'set_retention_policy')) }); const getParameter = new cr.AwsCustomResource(this, 'updateRetentionPeriod', { onCreate: { service: 'Lambda', action: 'invoke', parameters: { FunctionName: retention.functionName }, physicalResourceId: cr.PhysicalResourceId.of(Date.now().toString()), }, policy: cr.AwsCustomResourcePolicy.fromSdkCalls({ resources: cr.AwsCustomResourcePolicy.ANY_RESOURCE, }), }); console.log(getParameter); } }
index.ts(onEvent处理器)
import { CloudFormationCustomResourceEvent, CloudFormationCustomResourceDeleteEvent, CloudFormationCustomResourceUpdateEvent, CloudFormationCustomResourceCreateEvent } from "aws-lambda"; interface Response { PhysicalResourceId: string } export function onEvent( event: CloudFormationCustomResourceEvent, ): string { console.log("Event 👉", event); let response: Response; switch (event.RequestType){ case "Create": response = onCreate(event); break; case "Delete": response = onDelete(event); break; case "Update": response = onUpdate(event); break; default: throw new Error("Unknown Request Type of CloudFormation"); } console.log("Return value:", JSON.stringify(response)) return JSON.stringify(response); } function onCreate(event: CloudFormationCustomResourceCreateEvent) : Response { console.log("We are in the Create Event"); updateRetention(); return { PhysicalResourceId: "abcdef-" + event.RequestId } } function onDelete(event: CloudFormationCustomResourceDeleteEvent) : Response { console.log("We are in the Delete Event"); return { PhysicalResourceId: event.PhysicalResourceId || "" } } function onUpdate(event: CloudFormationCustomResourceUpdateEvent) : Response { console.log("We are in the Update Event"); return { PhysicalResourceId: event.PhysicalResourceId || "" } }
解决指引
1. 修正Lambda Handler配置
Lambda的handler格式必须为文件名.导出函数名,当前配置的"onEvent"缺少文件名前缀。修改Custom-resource.ts中的Lambda配置:
handler: "index.onEvent", // 替换原有的"onEvent"
2. 调整自定义资源返回值格式
CloudFormation要求自定义资源的Lambda返回JSON对象,而非JSON字符串。修改index.ts中的onEvent函数:
export function onEvent( event: CloudFormationCustomResourceEvent, ): Response { // 将返回类型从string改为Response console.log("Event 👉", event); let response: Response; switch (event.RequestType){ case "Create": response = onCreate(event); break; case "Delete": response = onDelete(event); break; case "Update": response = onUpdate(event); break; default: throw new Error("Unknown Request Type of CloudFormation"); } console.log("Return value:", JSON.stringify(response)) return response; // 直接返回Response对象,而非字符串化结果 }
3. 解决回滚后日志丢失问题
- 提前配置日志组保留策略:在Custom-resource.ts中为Lambda的日志组添加保留和不删除策略,确保回滚后日志依然存在:
import * as logs from "@aws-cdk/aws-logs"; // 创建Lambda函数后添加以下代码 new logs.LogGroup(this, "RetentionFunctionLogGroup", { logGroupName: `/aws/lambda/${retention.functionName}`, retention: logs.RetentionDays.THIRTY_DAYS, // 根据需求设置保留天数 removalPolicy: cdk.RemovalPolicy.RETAIN, // 栈删除/回滚时保留日志组 }); - 通过CloudFormation事件追踪日志:在CloudFormation控制台的栈事件中,找到失败的自定义资源事件,复制其物理资源ID(或请求ID),然后到CloudWatch日志中搜索该ID,定位相关日志记录。
4. 优化自定义资源调用方式
当前用AwsCustomResource调用Lambda的方式存在额外层级,建议改用cr.Provider直接关联自定义资源,更符合最佳实践:
// 替换原有的AwsCustomResource代码 const provider = new cr.Provider(this, "RetentionProvider", { onEventHandler: retention, }); new cdk.CustomResource(this, "UpdateRetention", { serviceToken: provider.serviceToken, properties: { // 可传递自定义参数,比如日志前缀、保留天数 LogPrefix: "/aws/codebuild/", RetentionDays: 30, }, });
内容的提问来源于stack exchange,提问作者Jeeva Suriyaa
相关产品推荐
相关产品推荐

