diff --git a/packages/@aws-cdk/integ-tests-alpha/README.md b/packages/@aws-cdk/integ-tests-alpha/README.md index 9ca5a2416d016..ff04b1cb477c1 100644 --- a/packages/@aws-cdk/integ-tests-alpha/README.md +++ b/packages/@aws-cdk/integ-tests-alpha/README.md @@ -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 `logRetention` 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 diff --git a/packages/@aws-cdk/integ-tests-alpha/lib/assertions/providers/provider.ts b/packages/@aws-cdk/integ-tests-alpha/lib/assertions/providers/provider.ts index 1fe737965c841..36d268ad37379 100644 --- a/packages/@aws-cdk/integ-tests-alpha/lib/assertions/providers/provider.ts +++ b/packages/@aws-cdk/integ-tests-alpha/lib/assertions/providers/provider.ts @@ -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 @@ -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; } /** @@ -75,18 +83,34 @@ class LambdaFunctionProvider extends Construct { }, }); + 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'), - }, + properties: functionProperties, }); this.serviceToken = Token.asString(handler.getAtt('Arn')); @@ -131,6 +155,7 @@ class SingletonFunction extends Construct { return new LambdaFunctionProvider(Stack.of(this), constructName, { handler: props.handler, + logRetention: props.logRetention, }); } @@ -204,6 +229,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; diff --git a/packages/@aws-cdk/integ-tests-alpha/lib/assertions/sdk.ts b/packages/@aws-cdk/integ-tests-alpha/lib/assertions/sdk.ts index d437f54c5ddbf..6a535f8fb2fac 100644 --- a/packages/@aws-cdk/integ-tests-alpha/lib/assertions/sdk.ts +++ b/packages/@aws-cdk/integ-tests-alpha/lib/assertions/sdk.ts @@ -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 @@ -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; @@ -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 * @@ -234,6 +244,7 @@ export class LambdaInvokeFunction extends AwsApiCall { InvocationType: props.invocationType, LogType: props.logType, Payload: props.payload, + RetentionDays: props.logRetention, }, }); diff --git a/packages/@aws-cdk/integ-tests-alpha/test/assertions/providers/provider.test.ts b/packages/@aws-cdk/integ-tests-alpha/test/assertions/providers/provider.test.ts index 823c297c8923b..03643d2c9779d 100644 --- a/packages/@aws-cdk/integ-tests-alpha/test/assertions/providers/provider.test.ts +++ b/packages/@aws-cdk/integ-tests-alpha/test/assertions/providers/provider.test.ts @@ -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(() => { @@ -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