Skip to content

Commit

Permalink
Allow users to override log retention days
Browse files Browse the repository at this point in the history
  • Loading branch information
GavinZZ committed Mar 8, 2024
1 parent 412231f commit 3c22841
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 24 deletions.
22 changes: 22 additions & 0 deletions packages/@aws-cdk/integ-tests-alpha/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,28 @@ invoke.expect(ExpectedResult.objectLike({
}));
```

The above example will by default create a CloudWatch log group that's never
expired. If you want to configure it with custom log retention days, you need
to specify the `logRenteion` property.

```ts
import * as logs from 'aws-cdk-lib/aws-logs';

declare const lambdaFunction: lambda.IFunction;
declare const app: App;

const stack = new Stack(app, 'cdk-integ-lambda-bundling');

const integ = new IntegTest(app, 'IntegTest', {
testCases: [stack],
});

const invoke = integ.assertions.invokeFunction({
functionName: lambdaFunction.functionName,
logRetention: logs.RetentionDays.ONE_WEEK,
});
```

#### Make an AWS API Call

In this example there is a StepFunctions state machine that is executed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import * as path from 'path';
import { Duration, CfnResource, AssetStaging, Stack, FileAssetPackaging, Token, Lazy, Reference } from 'aws-cdk-lib/core';
import { Construct } from 'constructs';
import { awsSdkToIamAction } from 'aws-cdk-lib/custom-resources/lib/helpers-internal';
import { RetentionDays } from 'aws-cdk-lib/aws-logs';

/**
* Properties for a lambda function provider
Expand All @@ -13,6 +14,13 @@ export interface LambdaFunctionProviderProps {
* @default index.handler
*/
readonly handler?: string;

/**
* How long, in days, the log contents will be retained.
*
* @default - no retention days specified
*/
readonly logRetention?: RetentionDays;
}

/**
Expand Down Expand Up @@ -75,29 +83,34 @@ class LambdaFunctionProvider extends Construct {
},
});

const logGroup = new CfnResource(this, 'LogGroup', {
type: 'AWS::Logs::LogGroup',
properties: {
LogGroupName: `/aws/lambda/${id}`,
RetentionInDays: '14',
const functionProperties: any = {
Runtime: 'nodejs18.x',
Code: {
S3Bucket: asset.bucketName,
S3Key: asset.objectKey,
},
});
Timeout: Duration.minutes(2).toSeconds(),
Handler: props?.handler ?? 'index.handler',
Role: role.getAtt('Arn'),
};

if (props?.logRetention) {
const logGroup = new CfnResource(this, 'LogGroup', {
type: 'AWS::Logs::LogGroup',
properties: {
LogGroupName: `/aws/lambda/${id}`,
RetentionInDays: props.logRetention,
},
});

functionProperties.LoggingConfig = {
LogGroup: logGroup.ref,
};
}

const handler = new CfnResource(this, 'Handler', {
type: 'AWS::Lambda::Function',
properties: {
Runtime: 'nodejs18.x',
Code: {
S3Bucket: asset.bucketName,
S3Key: asset.objectKey,
},
Timeout: Duration.minutes(2).toSeconds(),
Handler: props?.handler ?? 'index.handler',
Role: role.getAtt('Arn'),
LoggingConfig: {
LogGroup: logGroup.ref,
},
},
properties: functionProperties,
});

this.serviceToken = Token.asString(handler.getAtt('Arn'));
Expand All @@ -118,6 +131,13 @@ interface SingletonFunctionProps extends LambdaFunctionProviderProps {
* We recommend generating a UUID per provider.
*/
readonly uuid: string;

/**
* How long, in days, the log contents will be retained.
*
* @default - no retention days specified
*/
readonly logRetention?: RetentionDays;
}

/**
Expand All @@ -142,6 +162,7 @@ class SingletonFunction extends Construct {

return new LambdaFunctionProvider(Stack.of(this), constructName, {
handler: props.handler,
logRetention: props.logRetention,
});
}

Expand Down Expand Up @@ -215,6 +236,7 @@ export class AssertionsProvider extends Construct {
this.handler = new SingletonFunction(this, 'AssertionsProvider', {
handler: props?.handler,
uuid: props?.uuid ?? '1488541a-7b23-4664-81b6-9b4408076b81',
logRetention: props?.logRetention,
});

this.handlerRoleArn = this.handler.lambdaFunction.roleArn;
Expand Down
13 changes: 12 additions & 1 deletion packages/@aws-cdk/integ-tests-alpha/lib/assertions/sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { ApiCallBase, IApiCall } from './api-call-base';
import { ExpectedResult } from './common';
import { AssertionsProvider, SDK_RESOURCE_TYPE_PREFIX } from './providers';
import { WaiterStateMachine, WaiterStateMachineOptions } from './waiter-state-machine';
import { RetentionDays } from 'aws-cdk-lib/aws-logs';

/**
* Options to perform an AWS JavaScript V2 API call
Expand Down Expand Up @@ -75,7 +76,9 @@ export class AwsApiCall extends ApiCallBase {
constructor(scope: Construct, id: string, props: AwsApiCallProps) {
super(scope, id);

this.provider = new AssertionsProvider(this, 'SdkProvider');
this.provider = new AssertionsProvider(this, 'SdkProvider', {
logRetention: props.parameters?.RetentionDays,
});
this.provider.addPolicyStatementFromSdkCall(props.service, props.api);
this.name = `${props.service}${props.api}`;
this.api = props.api;
Expand Down Expand Up @@ -210,6 +213,13 @@ export interface LambdaInvokeFunctionProps {
*/
readonly logType?: LogType;

/**
* How long, in days, the log contents will be retained.
*
* @default - no retention days specified
*/
readonly logRetention?: RetentionDays;

/**
* Payload to send as part of the invoke
*
Expand All @@ -234,6 +244,7 @@ export class LambdaInvokeFunction extends AwsApiCall {
InvocationType: props.invocationType,
LogType: props.logType,
Payload: props.payload,
RetentionDays: props.logRetention,
},
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Template } from 'aws-cdk-lib/assertions';
import { Stack } from 'aws-cdk-lib';
import { AssertionsProvider } from '../../../lib/assertions';
import { RetentionDays } from 'aws-cdk-lib/aws-logs';

let stack: Stack;
beforeEach(() => {
Expand All @@ -20,6 +21,25 @@ describe('AssertionProvider', () => {
});
});

test('default', () => {
// WHEN
const provider = new AssertionsProvider(stack, 'AssertionProvider', {
logRetention: RetentionDays.ONE_WEEK,
});

// THEN
const template = Template.fromStack(stack);
template.resourceCountIs('AWS::Logs::LogGroup', 1);
expect(stack.resolve(provider.serviceToken)).toEqual({ 'Fn::GetAtt': ['SingletonFunction1488541a7b23466481b69b4408076b81HandlerCD40AE9F', 'Arn'] });
Template.fromStack(stack).hasResourceProperties('AWS::Lambda::Function', {
Handler: 'index.handler',
Timeout: 120,
});
template.hasResourceProperties('AWS::Logs::LogGroup', {
RetentionInDays: 7,
});
});

describe('addPolicyStatementForSdkCall', () => {
test('default', () => {
// WHEN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,11 @@ describe('AwsApiCall', () => {
// THEN
const template = Template.fromStack(deplossert.scope);
template.resourceCountIs('AWS::Lambda::Function', 1);
template.resourceCountIs('AWS::Logs::LogGroup', 1);
template.hasResourceProperties('Custom::DeployAssert@SdkCallMyServiceMyApi', {
service: 'MyService',
api: 'MyApi',
parameters: Match.absent(),
});
template.hasResourceProperties('AWS::Logs::LogGroup', {
RetentionInDays: '14',
});
});

test('parameters', () => {
Expand Down

0 comments on commit 3c22841

Please sign in to comment.