Skip to content

Commit

Permalink
feat(logs): delete associated log group when stack is deleted (#21113)
Browse files Browse the repository at this point in the history
----
Motivation: The log group created by LogRetention lingers after the stack is deleted. This commit allows users to choose whether to retain or destroy associated logs of the deleted stack.

Use case: To avoid having hundreds of dead log groups after the stack is deleted.

most salient design aspects:
Added an enum LogDeletionPolicy and set LogDeletionPolicy in the LogRetetion custom resource. Added an API deleteLogGroup and added an event 'Delete' to the handler of LogRetetion to delete the log group.

closes [#11549](#11549)

### All Submissions:

* [x] Have you followed the guidelines in our [Contributing guide?](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md)

### Adding new Unconventional Dependencies:

* [ ] This PR adds new unconventional dependencies following the process described [here](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md/#adding-new-unconventional-dependencies)

### New Features

* [x] Have you added the new feature to an [integration test](https://github.com/aws/aws-cdk/blob/main/INTEGRATION_TESTS.md)?
	* [x] Did you use `yarn integ` to deploy the infrastructure and generate the snapshot (i.e. `yarn integ` without `--dry-run`)?

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
YichenQian09 authored Aug 8, 2022
1 parent 0767873 commit 2bdd504
Show file tree
Hide file tree
Showing 27 changed files with 1,326 additions and 495 deletions.
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-logs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ By default, the log group will be created in the same region as the stack. The `
log groups in other regions. This is typically useful when controlling retention for log groups auto-created by global services that
publish their log group to a specific region, such as AWS Chatbot creating a log group in `us-east-1`.

By default, the log group created by LogRetention will be retained after the stack is deleted. If the RemovalPolicy is set to DESTROY, then the log group will be deleted when the stack is deleted.

## Resource Policy

CloudWatch Resource Policies allow other AWS services or IAM Principals to put log events into the log groups.
Expand Down
35 changes: 35 additions & 0 deletions packages/@aws-cdk/aws-logs/lib/log-retention-provider/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,35 @@ async function createLogGroupSafe(logGroupName: string, region?: string, options
} while (true); // exit happens on retry count check
}

//delete a log group
async function deleteLogGroup(logGroupName: string, region?: string, options?: SdkRetryOptions) {
let retryCount = options?.maxRetries == undefined ? 10 : options.maxRetries;
const delay = options?.retryOptions?.base == undefined ? 10 : options.retryOptions.base;
do {
try {
const cloudwatchlogs = new AWS.CloudWatchLogs({ apiVersion: '2014-03-28', region, ...options });
await cloudwatchlogs.deleteLogGroup({ logGroupName }).promise();
return;
} catch (error) {
if (error.code === 'ResourceNotFoundException') {
// The log group doesn't exist
return;
}
if (error.code === 'OperationAbortedException') {
if (retryCount > 0) {
retryCount--;
await new Promise(resolve => setTimeout(resolve, delay));
continue;
} else {
// The log group is still being deleted by another execution but we are out of retries
throw new Error('Out of attempts to delete a logGroup');
}
}
throw error;
}
} while (true); // exit happens on retry count check
}

/**
* Puts or deletes a retention policy on a log group.
*
Expand Down Expand Up @@ -124,6 +153,12 @@ export async function handler(event: AWSLambda.CloudFormationCustomResourceEvent
}
}

//When the requestType is delete, delete the log group if the removal policy is delete
if (event.RequestType === 'Delete' && event.ResourceProperties.RemovalPolicy === 'destroy') {
await deleteLogGroup(logGroupName, logGroupRegion, retryOptions);
//else retain the log group
}

await respond('SUCCESS', 'OK', logGroupName);
} catch (e) {
console.log(e);
Expand Down
30 changes: 30 additions & 0 deletions packages/@aws-cdk/aws-logs/lib/log-retention.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,12 @@ export interface LogRetentionProps {
* @default - AWS SDK default retry options
*/
readonly logRetentionRetryOptions?: LogRetentionRetryOptions;

/**
* The removalPolicy for the log group when the stack is deleted
* @default RemovalPolicy.RETAIN
*/
readonly removalPolicy?: cdk.RemovalPolicy;
}

/**
Expand Down Expand Up @@ -93,6 +99,7 @@ export class LogRetention extends Construct {
base: retryOptions.base?.toMilliseconds(),
} : undefined,
RetentionInDays: props.retention === RetentionDays.INFINITE ? undefined : props.retention,
RemovalPolicy: props.removalPolicy,
},
});

Expand Down Expand Up @@ -151,6 +158,29 @@ class LogRetentionFunction extends Construct implements cdk.ITaggable {
// creates a CF circular dependency.
resources: ['*'],
}));
// if removalPolicy is DESTROY, add action for DeleteLogGroup and DeleteLogStream
if (props.removalPolicy === cdk.RemovalPolicy.DESTROY) {
role.addToPrincipalPolicy(new iam.PolicyStatement({
actions: ['logs:DeleteLogGroup'],
//Only allow deleting the specific log group.
resources: [cdk.Stack.of(this).formatArn({
service: 'logs',
resource: 'log-group',
resourceName: `${props.logGroupName}:*`,
arnFormat: ArnFormat.COLON_RESOURCE_NAME,
})],
}));
role.addToPrincipalPolicy(new iam.PolicyStatement({
actions: ['logs:DeleteLogStream'],
//Only allow deleting the specific log group.
resources: [cdk.Stack.of(this).formatArn({
service: 'logs',
resource: `log-group:${props.logGroupName}:log-stream`,
resourceName: '*',
arnFormat: ArnFormat.COLON_RESOURCE_NAME,
})],
}));
}

// Lambda function
const resource = new cdk.CfnResource(this, 'Resource', {
Expand Down
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-logs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
"@aws-cdk/assertions": "0.0.0",
"@aws-cdk/cdk-build-tools": "0.0.0",
"@aws-cdk/integ-runner": "0.0.0",
"@aws-cdk/integ-tests": "0.0.0",
"@aws-cdk/cfn2ts": "0.0.0",
"@aws-cdk/pkglint": "0.0.0",
"@types/aws-lambda": "^8.10.101",
Expand Down

This file was deleted.

This file was deleted.

119 changes: 0 additions & 119 deletions packages/@aws-cdk/aws-logs/test/cdk-integ.out.expose-metric/tree.json

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit 2bdd504

Please sign in to comment.