Skip to content
Open
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,14 @@ export class ApplicationTargetGroup extends TargetGroupBase implements IApplicat
this.setAttribute('load_balancing.algorithm.anomaly_mitigation', props.enableAnomalyMitigation ? 'on' : 'off');
}
}

// Add a warning if protocol wasn't explicitly specified for non-Lambda targets
if (props.protocol === undefined && this.targetType !== TargetType.LAMBDA) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is also sufficient to provide port number for stack to be deployable. We can check if both of those are undefined, otherwise ask it to provide either one of them. In the scenario where port number is provided, I can still get this validation error, even though I do not have any issue.

Reference to documentation: https://docs.aws.amazon.com/cdk/api/v2/docs/aws-cdk-lib.aws_elasticloadbalancingv2.ApplicationTargetGroup.html#port

This change would require an update in the unit tests as well

Annotations.of(this).addWarningV2(
'@aws-cdk/aws-elbv2:target-group-protocol-default',
'ApplicationTargetGroup protocol not specified. Please specify protocol explicitly (e.g., ApplicationProtocol.HTTP or ApplicationProtocol.HTTPS). Note: Missing protocol will cause deployment failures.',
);
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This validation should remain in the validateTargetGroup method to maintain consistency with existing validation patterns. This change weakens validation by converting an error to a warning and moves logic outside the dedicated validation method.

I noticed also that the original validation logic was incorrect (used || instead of &&). We can fix this since, changing it to && logic actually loosens the validation, so it's not a breaking change.

We can do:

  1. Fix the existing error validation in validateTargetGroup (change || to && logic)
  2. Add the warning annotation as supplementary feedback within validateTargetGroup when targetType is undefined


public get metrics(): IApplicationTargetGroupMetrics {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,81 @@ describe('tests', () => {
expect(() => app.synth()).toThrow(/port\/protocol should not be specified for Lambda targets/);
});

test('ApplicationTargetGroup shows warning when protocol not specified', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'Stack');
const vpc = new ec2.Vpc(stack, 'Vpc');

// WHEN - Create ApplicationTargetGroup without protocol but with port
new elbv2.ApplicationTargetGroup(stack, 'TG', {
vpc,
port: 80, // Providing port satisfies the "at least one of port or protocol" requirement
// protocol is missing - this should generate a warning
});

// THEN - Should synthesize successfully but show warning
const assembly = app.synth();
const stackArtifact = assembly.getStackByName(stack.stackName);
const warnings = stackArtifact.messages.filter(m => m.level === 'warning');
expect(warnings.some(w => w.entry.data.includes('ApplicationTargetGroup protocol not specified'))).toBe(true);
});

test('ApplicationTargetGroup with protocol should not throw validation error', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'Stack');
const vpc = new ec2.Vpc(stack, 'Vpc');

// WHEN - Create ApplicationTargetGroup with protocol
new elbv2.ApplicationTargetGroup(stack, 'TG', {
vpc,
port: 80,
protocol: elbv2.ApplicationProtocol.HTTP,
});

// THEN - Should not throw
expect(() => app.synth()).not.toThrow();
});

test('ApplicationTargetGroup with Lambda target does not require protocol', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'Stack');

// WHEN - Create ApplicationTargetGroup for Lambda without protocol
new elbv2.ApplicationTargetGroup(stack, 'TG', {
targetType: elbv2.TargetType.LAMBDA,
// protocol is missing but should be allowed for Lambda
});

// THEN - Should not throw
expect(() => app.synth()).not.toThrow();
});

test('ApplicationTargetGroup requires protocol even when targets added later', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'Stack');
const vpc = new ec2.Vpc(stack, 'Vpc');

// WHEN - Create ApplicationTargetGroup without protocol but with port, then add non-Lambda target
const tg = new elbv2.ApplicationTargetGroup(stack, 'TG', {
vpc,
port: 80, // Providing port satisfies the "at least one of port or protocol" requirement
// protocol is missing - this should generate a warning
});

// Add a non-Lambda target
tg.addTarget(new elbv2.InstanceTarget('i-1234'));

// THEN - Should synthesize successfully but show warning
const assembly = app.synth();
const stackArtifact = assembly.getStackByName(stack.stackName);
const warnings = stackArtifact.messages.filter(m => m.level === 'warning');
expect(warnings.some(w => w.entry.data.includes('ApplicationTargetGroup protocol not specified'))).toBe(true);
});

test('Can add self-registering target to imported TargetGroup', () => {
// GIVEN
const app = new cdk.App();
Expand Down
Loading