Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(lambda): allow to delete log group of a lambda function when it is removed #21820

Closed
wants to merge 20 commits into from
Closed
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 @@ -116,6 +116,34 @@
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": "logs:DeleteLogGroup",
"Effect": "Allow",
"Resource": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":logs:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":log-group:/aws/lambda/",
{
"Ref": "AutoDeleteLogGroupF74A7E0D"
},
":*"
]
]
}
}
],
"Version": "2012-10-17"
Expand Down Expand Up @@ -296,6 +324,79 @@
},
"RetentionInDays": 365
}
},
"AutoDeleteLogGroupServiceRoleF3400DE1": {
"Type": "AWS::IAM::Role",
"Properties": {
"AssumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
}
}
],
"Version": "2012-10-17"
},
"ManagedPolicyArns": [
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
]
]
}
]
}
},
"AutoDeleteLogGroupF74A7E0D": {
"Type": "AWS::Lambda::Function",
"Properties": {
"Code": {
"ZipFile": "exports.handler = (event) => console.log(JSON.stringify(event));"
},
"Role": {
"Fn::GetAtt": [
"AutoDeleteLogGroupServiceRoleF3400DE1",
"Arn"
]
},
"Handler": "index.handler",
"Runtime": "nodejs14.x"
},
"DependsOn": [
"AutoDeleteLogGroupServiceRoleF3400DE1"
]
},
"AutoDeleteLogGroupLogRetentionAC501FFB": {
"Type": "Custom::LogRetention",
"Properties": {
"ServiceToken": {
"Fn::GetAtt": [
"LogRetentionaae0aa3c5b4d4f87b02d85b201efdd8aFD4BFC8A",
"Arn"
]
},
"LogGroupName": {
"Fn::Join": [
"",
[
"/aws/lambda/",
{
"Ref": "AutoDeleteLogGroupF74A7E0D"
}
]
]
},
"RemovalPolicy": "destroy"
}
}
},
"Parameters": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,24 @@
"data": "OneYearLogRetentionBD83A067"
}
],
"/aws-cdk-lambda-log-retention/AutoDeleteLogGroup/ServiceRole/Resource": [
{
"type": "aws:cdk:logicalId",
"data": "AutoDeleteLogGroupServiceRoleF3400DE1"
}
],
"/aws-cdk-lambda-log-retention/AutoDeleteLogGroup/Resource": [
{
"type": "aws:cdk:logicalId",
"data": "AutoDeleteLogGroupF74A7E0D"
}
],
"/aws-cdk-lambda-log-retention/AutoDeleteLogGroup/LogRetention/Resource": [
{
"type": "aws:cdk:logicalId",
"data": "AutoDeleteLogGroupLogRetentionAC501FFB"
}
],
"/aws-cdk-lambda-log-retention/BootstrapVersion": [
{
"type": "aws:cdk:logicalId",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,34 @@
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": "logs:DeleteLogGroup",
"Effect": "Allow",
"Resource": {
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":logs:",
{
"Ref": "AWS::Region"
},
":",
{
"Ref": "AWS::AccountId"
},
":log-group:/aws/lambda/",
{
"Ref": "AutoDeleteLogGroupF74A7E0D"
},
":*"
]
]
}
}
],
"Version": "2012-10-17"
Expand Down Expand Up @@ -517,6 +545,115 @@
"fqn": "aws-cdk-lib.CfnRule",
"version": "0.0.0"
}
},
"AutoDeleteLogGroup": {
"id": "AutoDeleteLogGroup",
"path": "aws-cdk-lambda-log-retention/AutoDeleteLogGroup",
"children": {
"ServiceRole": {
"id": "ServiceRole",
"path": "aws-cdk-lambda-log-retention/AutoDeleteLogGroup/ServiceRole",
"children": {
"Resource": {
"id": "Resource",
"path": "aws-cdk-lambda-log-retention/AutoDeleteLogGroup/ServiceRole/Resource",
"attributes": {
"aws:cdk:cloudformation:type": "AWS::IAM::Role",
"aws:cdk:cloudformation:props": {
"assumeRolePolicyDocument": {
"Statement": [
{
"Action": "sts:AssumeRole",
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
}
}
],
"Version": "2012-10-17"
},
"managedPolicyArns": [
{
"Fn::Join": [
"",
[
"arn:",
{
"Ref": "AWS::Partition"
},
":iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
]
]
}
]
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-iam.CfnRole",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-iam.Role",
"version": "0.0.0"
}
},
"Resource": {
"id": "Resource",
"path": "aws-cdk-lambda-log-retention/AutoDeleteLogGroup/Resource",
"attributes": {
"aws:cdk:cloudformation:type": "AWS::Lambda::Function",
"aws:cdk:cloudformation:props": {
"code": {
"zipFile": "exports.handler = (event) => console.log(JSON.stringify(event));"
},
"role": {
"Fn::GetAtt": [
"AutoDeleteLogGroupServiceRoleF3400DE1",
"Arn"
]
},
"handler": "index.handler",
"runtime": "nodejs14.x"
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-lambda.CfnFunction",
"version": "0.0.0"
}
},
"LogRetention": {
"id": "LogRetention",
"path": "aws-cdk-lambda-log-retention/AutoDeleteLogGroup/LogRetention",
"children": {
"Resource": {
"id": "Resource",
"path": "aws-cdk-lambda-log-retention/AutoDeleteLogGroup/LogRetention/Resource",
"constructInfo": {
"fqn": "@aws-cdk/core.CfnResource",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-logs.LogRetention",
"version": "0.0.0"
}
},
"LogGroup": {
"id": "LogGroup",
"path": "aws-cdk-lambda-log-retention/AutoDeleteLogGroup/LogGroup",
"constructInfo": {
"fqn": "@aws-cdk/core.Resource",
"version": "0.0.0"
}
}
},
"constructInfo": {
"fqn": "@aws-cdk/aws-lambda.Function",
"version": "0.0.0"
}
}
},
"constructInfo": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,5 +28,12 @@ new lambda.Function(stack, 'OneYear', {
logRetention: logs.RetentionDays.ONE_YEAR,
});

new lambda.Function(stack, 'AutoDeleteLogGroup', {
code: new lambda.InlineCode('exports.handler = (event) => console.log(JSON.stringify(event));'),
handler: 'index.handler',
runtime: lambda.Runtime.NODEJS_14_X,
autoDeleteLogGroup: true,
});

new IntegTest(app, 'LambdaLogRetentionInteg', { testCases: [stack] });
app.synth();
2 changes: 2 additions & 0 deletions packages/aws-cdk-lib/aws-lambda/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,8 @@ It is possible to obtain the function's log group as a `logs.ILogGroup` by calli
By default, CDK uses the AWS SDK retry options when creating a log group. The `logRetentionRetryOptions` property
allows you to customize the maximum number of retries and base backoff duration.

To automatically delete the associated log group for a Lambda function, you can use the `autoDeleteLogGroup` property.

*Note* that, if either `logRetention` is set or `logGroup` property is called, a [CloudFormation custom
resource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cfn-customresource.html) is added
to the stack that pre-creates the log group as part of the stack deployment, if it already doesn't exist, and sets the
Expand Down
17 changes: 13 additions & 4 deletions packages/aws-cdk-lib/aws-lambda/lib/function.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import * as kms from '../../aws-kms';
import * as logs from '../../aws-logs';
import * as sns from '../../aws-sns';
import * as sqs from '../../aws-sqs';
import { Annotations, ArnFormat, CfnResource, Duration, FeatureFlags, Fn, IAspect, Lazy, Names, Size, Stack, Token } from '../../core';
import { Annotations, ArnFormat, CfnResource, Duration, FeatureFlags, Fn, IAspect, Lazy, Names, RemovalPolicy, Size, Stack, Token } from '../../core';
import { LAMBDA_RECOGNIZE_LAYER_VERSION } from '../../cx-api';

/**
Expand Down Expand Up @@ -296,6 +296,14 @@ export interface FunctionOptions extends EventInvokeConfigOptions {
*/
readonly events?: IEventSource[];

/**
* Whether the associated CloudWatch log group should be automatically deleted
* when the function is removed from the stack or when the stack is deleted.
*
* @default false
*/
readonly autoDeleteLogGroup?: boolean;

/**
* The number of days log events are kept in CloudWatch Logs. When updating
* this property, unsetting it doesn't remove the log retention policy. To
Expand Down Expand Up @@ -866,12 +874,13 @@ export class Function extends FunctionBase {
}

// Log retention
if (props.logRetention) {
if (props.logRetention || props.autoDeleteLogGroup) {
const logRetention = new logs.LogRetention(this, 'LogRetention', {
logGroupName: `/aws/lambda/${this.functionName}`,
retention: props.logRetention,
retention: props.logRetention ?? logs.RetentionDays.INFINITE,
role: props.logRetentionRole,
logRetentionRetryOptions: props.logRetentionRetryOptions as logs.LogRetentionRetryOptions,
logRetentionRetryOptions: props.logRetentionRetryOptions,
removalPolicy: props.autoDeleteLogGroup ? RemovalPolicy.DESTROY : undefined,
});
this._logGroup = logs.LogGroup.fromLogGroupArn(this, 'LogGroup', logRetention.logGroupArn);
}
Expand Down
Loading