Skip to content

Commit 576d034

Browse files
authored
feat(elasticloadbalancingv2): health check interval greater than timeout (#29075)
Closes #29062. ---- *By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
1 parent 2dbb381 commit 576d034

File tree

5 files changed

+96
-4
lines changed

5 files changed

+96
-4
lines changed

Diff for: packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/nlb/network-target-group.ts

-3
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,6 @@ export class NetworkTargetGroup extends TargetGroupBase implements INetworkTarge
280280
if (timeoutSeconds < lowHealthCheckTimeout || timeoutSeconds > highHealthCheckTimeout) {
281281
ret.push(`Health check timeout '${timeoutSeconds}' not supported. Must be a number between ${lowHealthCheckTimeout} and ${highHealthCheckTimeout}.`);
282282
}
283-
if (healthCheck.interval && healthCheck.interval.toSeconds() < timeoutSeconds) {
284-
ret.push(`Health check timeout '${timeoutSeconds}' must not be greater than the interval '${healthCheck.interval.toSeconds()}'`);
285-
}
286283
}
287284

288285
return ret;

Diff for: packages/aws-cdk-lib/aws-elasticloadbalancingv2/lib/shared/base-target-group.ts

+17
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ export abstract class TargetGroupBase extends Construct implements ITargetGroup
280280
this.targetGroupName = this.resource.attrTargetGroupName;
281281
this.defaultPort = additionalProps.port;
282282

283+
this.node.addValidation({ validate: () => this.validateHealthCheck() });
283284
this.node.addValidation({ validate: () => this.validateTargetGroup() });
284285
}
285286

@@ -351,6 +352,22 @@ export abstract class TargetGroupBase extends Construct implements ITargetGroup
351352

352353
return ret;
353354
}
355+
356+
protected validateHealthCheck(): string[] {
357+
const ret = new Array<string>();
358+
359+
const intervalSeconds = this.healthCheck.interval?.toSeconds();
360+
const timeoutSeconds = this.healthCheck.timeout?.toSeconds();
361+
362+
if (intervalSeconds && timeoutSeconds) {
363+
if (intervalSeconds < timeoutSeconds) {
364+
// < instead of <= for backwards compatibility, see discussion in https://github.com/aws/aws-cdk/pull/26031
365+
ret.push('Health check interval must be greater than or equal to the timeout; received interval ' +
366+
`${intervalSeconds}, timeout ${timeoutSeconds}.`);
367+
}
368+
}
369+
return ret;
370+
}
354371
}
355372

356373
/**

Diff for: packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/alb/target-group.test.ts

+39
Original file line numberDiff line numberDiff line change
@@ -549,6 +549,45 @@ describe('tests', () => {
549549
}).toThrow('Healthcheck interval 1 minute must be greater than the timeout 2 minute');
550550
});
551551

552+
test('Throws error for health check interval less than timeout', () => {
553+
const app = new cdk.App();
554+
const stack = new cdk.Stack(app, 'Stack');
555+
const vpc = new ec2.Vpc(stack, 'Vpc');
556+
557+
new elbv2.ApplicationTargetGroup(stack, 'TargetGroup', {
558+
vpc,
559+
port: 80,
560+
healthCheck: {
561+
interval: cdk.Duration.seconds(10),
562+
timeout: cdk.Duration.seconds(20),
563+
},
564+
});
565+
566+
expect(() => {
567+
app.synth();
568+
}).toThrow('Health check interval must be greater than or equal to the timeout; received interval 10, timeout 20.');
569+
});
570+
571+
// for backwards compatibility these can be equal, see discussion in https://github.com/aws/aws-cdk/pull/26031
572+
test('Throws error for health check interval less than timeout', () => {
573+
const app = new cdk.App();
574+
const stack = new cdk.Stack(app, 'Stack');
575+
const vpc = new ec2.Vpc(stack, 'Vpc');
576+
577+
new elbv2.ApplicationTargetGroup(stack, 'TargetGroup', {
578+
vpc,
579+
port: 80,
580+
healthCheck: {
581+
interval: cdk.Duration.seconds(10),
582+
timeout: cdk.Duration.seconds(20),
583+
},
584+
});
585+
586+
expect(() => {
587+
app.synth();
588+
}).toThrow('Health check interval must be greater than or equal to the timeout; received interval 10, timeout 20.');
589+
});
590+
552591
test('imported targetGroup has targetGroupName', () => {
553592
// GIVEN
554593
const app = new cdk.App();

Diff for: packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/nlb/listener.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ describe('tests', () => {
408408
// THEN
409409
const validationErrors: string[] = targetGroup.node.validate();
410410
expect(validationErrors).toEqual([
411-
"Health check timeout '40' must not be greater than the interval '30'",
411+
'Health check interval must be greater than or equal to the timeout; received interval 30, timeout 40.',
412412
]);
413413
});
414414

Diff for: packages/aws-cdk-lib/aws-elasticloadbalancingv2/test/nlb/target-group.test.ts

+39
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,45 @@ describe('tests', () => {
144144
}).toThrow(/Health check interval '3' not supported. Must be between 5 and 300./);
145145
});
146146

147+
test('Throws error for health check interval less than timeout', () => {
148+
const app = new cdk.App();
149+
const stack = new cdk.Stack(app, 'Stack');
150+
const vpc = new ec2.Vpc(stack, 'Vpc');
151+
152+
new elbv2.NetworkTargetGroup(stack, 'Group', {
153+
vpc,
154+
port: 80,
155+
healthCheck: {
156+
interval: cdk.Duration.seconds(10),
157+
timeout: cdk.Duration.seconds(20),
158+
},
159+
});
160+
161+
expect(() => {
162+
app.synth();
163+
}).toThrow('Health check interval must be greater than or equal to the timeout; received interval 10, timeout 20.');
164+
});
165+
166+
// for backwards compatibility these can be equal, see discussion in https://github.com/aws/aws-cdk/pull/26031
167+
test('No error for health check interval == timeout', () => {
168+
const app = new cdk.App();
169+
const stack = new cdk.Stack(app, 'Stack');
170+
const vpc = new ec2.Vpc(stack, 'Vpc');
171+
172+
new elbv2.NetworkTargetGroup(stack, 'Group', {
173+
vpc,
174+
port: 80,
175+
healthCheck: {
176+
interval: cdk.Duration.seconds(10),
177+
timeout: cdk.Duration.seconds(10),
178+
},
179+
});
180+
181+
expect(() => {
182+
app.synth();
183+
}).not.toThrow();
184+
});
185+
147186
test('targetGroupName unallowed: more than 32 characters', () => {
148187
// GIVEN
149188
const app = new cdk.App();

0 commit comments

Comments
 (0)