Skip to content

Commit 667ed30

Browse files
fix(lambda): add Token.isUnresolved checks to provisioned poller config validation (#37197)
### Issue # (if applicable) None ### Reason for this change The `provisionedPollerConfig` validation in both `EventSourceMapping` (aws-lambda) and `StreamEventSource` (aws-lambda-event-sources) throws errors when unresolved CDK tokens are passed as `minimumPollers` or `maximumPollers` values (e.g. `CfnParameter`, `Lazy.number()`). These values cannot be validated at synthesis time and should be skipped, as is already done for other numeric validations like `maxConcurrency` and `tumblingWindow`. ### Description of changes Added `Token.isUnresolved()` guards to provisioned poller config validation in: - `packages/aws-cdk-lib/aws-lambda/lib/event-source-mapping.ts` - `packages/aws-cdk-lib/aws-lambda-event-sources/lib/stream.ts` This follows the same pattern already used for `maxConcurrency` (line 542 of event-source-mapping.ts) and `tumblingWindow` (line 563). ### Describe any new or updated permissions being added None ### Description of how you validated changes Add unit tests. ### Checklist - [x] My code adheres to the [CONTRIBUTING GUIDE](https://github.com/aws/aws-cdk/blob/main/CONTRIBUTING.md) and [DESIGN GUIDELINES](https://github.com/aws/aws-cdk/blob/main/docs/DESIGN_GUIDELINES.md) ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 927dd60 commit 667ed30

4 files changed

Lines changed: 64 additions & 7 deletions

File tree

packages/aws-cdk-lib/aws-lambda-event-sources/lib/stream.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { S3OnFailureDestination } from './s3-onfailuire-destination';
22
import type { IKey } from '../../aws-kms';
33
import type * as lambda from '../../aws-lambda';
44
import type { Duration } from '../../core';
5-
import { UnscopedValidationError } from '../../core';
5+
import { Token, UnscopedValidationError } from '../../core';
66
import { lit } from '../../core/lib/private/literal-string';
77

88
/**
@@ -186,17 +186,19 @@ export abstract class StreamEventSource implements lambda.IEventSource {
186186
protected constructor(protected readonly props: StreamEventSourceProps) {
187187
if (props.provisionedPollerConfig) {
188188
const { minimumPollers, maximumPollers } = props.provisionedPollerConfig;
189-
if (minimumPollers != undefined) {
189+
const isMinimumPollersDefinedAndResolved = minimumPollers != undefined && !Token.isUnresolved(minimumPollers);
190+
const isMaximumPollersDefinedAndResolved = maximumPollers != undefined && !Token.isUnresolved(maximumPollers);
191+
if (isMinimumPollersDefinedAndResolved) {
190192
if (minimumPollers < 1 || minimumPollers > 200) {
191193
throw new UnscopedValidationError(lit`MustBeMinimumProvisionedPollers`, 'Minimum provisioned pollers must be between 1 and 200 inclusive');
192194
}
193195
}
194-
if (maximumPollers != undefined) {
196+
if (isMaximumPollersDefinedAndResolved) {
195197
if (maximumPollers < 1 || maximumPollers > 2000) {
196198
throw new UnscopedValidationError(lit`MustBeMaximumProvisionedPollers`, 'Maximum provisioned pollers must be between 1 and 2000 inclusive');
197199
}
198200
}
199-
if (minimumPollers != undefined && maximumPollers != undefined) {
201+
if (isMinimumPollersDefinedAndResolved && isMaximumPollersDefinedAndResolved) {
200202
if (minimumPollers > maximumPollers) {
201203
throw new UnscopedValidationError(lit`MustBeMinimumProvisionedPollers`, 'Minimum provisioned pollers must be less than or equal to maximum provisioned pollers');
202204
}

packages/aws-cdk-lib/aws-lambda-event-sources/test/kafka.test.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -577,6 +577,27 @@ describe('KafkaEventSource', () => {
577577
}))).toThrow(/Minimum provisioned pollers must be less than or equal to maximum provisioned pollers/);
578578
});
579579

580+
test('provisioned pollers with unresolved tokens should not throw', () => {
581+
const stack = new cdk.Stack();
582+
const testLambdaFunction = new TestFunction(stack, 'Fn');
583+
const clusterArn = 'some-arn';
584+
const kafkaTopic = 'some-topic';
585+
const bucket = Bucket.fromBucketName(stack, 'BucketByName', 'my-bucket');
586+
const s3OnFailureDestination = new sources.S3OnFailureDestination(bucket);
587+
588+
expect(() => testLambdaFunction.addEventSource(new sources.ManagedKafkaEventSource(
589+
{
590+
clusterArn,
591+
topic: kafkaTopic,
592+
startingPosition: lambda.StartingPosition.TRIM_HORIZON,
593+
onFailure: s3OnFailureDestination,
594+
provisionedPollerConfig: {
595+
minimumPollers: cdk.Lazy.number({ produce: () => 1 }),
596+
maximumPollers: cdk.Lazy.number({ produce: () => 3 }),
597+
},
598+
}))).not.toThrow();
599+
});
600+
580601
test('MetricsConfig validation - empty metrics array', () => {
581602
// GIVEN
582603
const stack = new cdk.Stack();
@@ -1439,6 +1460,25 @@ describe('KafkaEventSource', () => {
14391460
}))).toThrow(/Minimum provisioned pollers must be less than or equal to maximum provisioned pollers/);
14401461
});
14411462

1463+
test('provisioned pollers with unresolved tokens should not throw', () => {
1464+
// GIVEN
1465+
const stack = new cdk.Stack();
1466+
const fn = new TestFunction(stack, 'Fn');
1467+
const clusterArn = 'some-arn';
1468+
const kafkaTopic = 'some-topic';
1469+
1470+
expect(() => fn.addEventSource(new sources.ManagedKafkaEventSource(
1471+
{
1472+
clusterArn,
1473+
topic: kafkaTopic,
1474+
startingPosition: lambda.StartingPosition.TRIM_HORIZON,
1475+
provisionedPollerConfig: {
1476+
minimumPollers: cdk.Lazy.number({ produce: () => 1 }),
1477+
maximumPollers: cdk.Lazy.number({ produce: () => 3 }),
1478+
},
1479+
}))).not.toThrow();
1480+
});
1481+
14421482
test('MetricsConfig validation - empty metrics array', () => {
14431483
// GIVEN
14441484
const stack = new cdk.Stack();

packages/aws-cdk-lib/aws-lambda/lib/event-source-mapping.ts

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -515,17 +515,19 @@ export class EventSourceMapping extends cdk.Resource implements IEventSourceMapp
515515

516516
if (props.provisionedPollerConfig) {
517517
const { minimumPollers, maximumPollers } = props.provisionedPollerConfig;
518-
if (minimumPollers != undefined) {
518+
const isMinimumPollersDefinedAndResolved = minimumPollers != undefined && !cdk.Token.isUnresolved(minimumPollers);
519+
const isMaximumPollersDefinedAndResolved = maximumPollers != undefined && !cdk.Token.isUnresolved(maximumPollers);
520+
if (isMinimumPollersDefinedAndResolved) {
519521
if (minimumPollers < 1 || minimumPollers > 200) {
520522
throw new ValidationError(lit`MinimumProvisionedPollersInclusive`, 'Minimum provisioned pollers must be between 1 and 200 inclusive', this);
521523
}
522524
}
523-
if (maximumPollers != undefined) {
525+
if (isMaximumPollersDefinedAndResolved) {
524526
if (maximumPollers < 1 || maximumPollers > 2000) {
525527
throw new ValidationError(lit`MaximumProvisionedPollersInclusive`, 'Maximum provisioned pollers must be between 1 and 2000 inclusive', this);
526528
}
527529
}
528-
if (minimumPollers != undefined && maximumPollers != undefined) {
530+
if (isMinimumPollersDefinedAndResolved && isMaximumPollersDefinedAndResolved) {
529531
if (minimumPollers > maximumPollers) {
530532
throw new ValidationError(lit`MinimumProvisionedPollersLessEqual`, 'Minimum provisioned pollers must be less than or equal to maximum provisioned pollers', this);
531533
}

packages/aws-cdk-lib/aws-lambda/test/event-source-mapping.test.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -602,4 +602,17 @@ describe('event source mapping', () => {
602602
},
603603
})).toThrow(/Minimum provisioned pollers must be less than or equal to maximum provisioned pollers/);
604604
});
605+
606+
test('provisioned pollers with unresolved tokens should not throw', () => {
607+
expect(() => new EventSourceMapping(stack, 'test', {
608+
target: fn,
609+
eventSourceArn: '',
610+
startingPosition: StartingPosition.AT_TIMESTAMP,
611+
startingPositionTimestamp: 1640995200,
612+
provisionedPollerConfig: {
613+
minimumPollers: cdk.Lazy.number({ produce: () => 1 }),
614+
maximumPollers: cdk.Lazy.number({ produce: () => 3 }),
615+
},
616+
})).not.toThrow();
617+
});
605618
});

0 commit comments

Comments
 (0)