Skip to content

Commit

Permalink
feat(elbv2): use addAction() on an imported application listener (#…
Browse files Browse the repository at this point in the history
…19293)

This PR adds the ability to call `addAction()` on an imported
`IApplicationListener`.

Fixes #10902


----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
corymhall committed Mar 31, 2022
1 parent e8142e9 commit 18a6b0c
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -508,6 +508,21 @@ export interface IApplicationListener extends IResource, ec2.IConnectable {
* Don't call this directly. It is called by ApplicationTargetGroup.
*/
registerConnectable(connectable: ec2.IConnectable, portRange: ec2.Port): void;

/**
* Perform the given action on incoming requests
*
* This allows full control of the default action of the load balancer,
* including Action chaining, fixed responses and redirect responses. See
* the `ListenerAction` class for all options.
*
* It's possible to add routing conditions to the Action added in this way.
*
* It is not possible to add a default action to an imported IApplicationListener.
* In order to add actions to an imported IApplicationListener a `priority`
* must be provided.
*/
addAction(id: string, props: AddApplicationActionProps): void;
}

/**
Expand Down Expand Up @@ -627,6 +642,36 @@ abstract class ExternalApplicationListener extends Resource implements IApplicat
// eslint-disable-next-line max-len
throw new Error('Can only call addTargets() when using a constructed ApplicationListener; construct a new TargetGroup and use addTargetGroup.');
}

/**
* Perform the given action on incoming requests
*
* This allows full control of the default action of the load balancer,
* including Action chaining, fixed responses and redirect responses. See
* the `ListenerAction` class for all options.
*
* It's possible to add routing conditions to the Action added in this way.
*
* It is not possible to add a default action to an imported IApplicationListener.
* In order to add actions to an imported IApplicationListener a `priority`
* must be provided.
*/
public addAction(id: string, props: AddApplicationActionProps): void {
checkAddRuleProps(props);

if (props.priority !== undefined) {
// New rule
//
// TargetGroup.registerListener is called inside ApplicationListenerRule.
new ApplicationListenerRule(this, id + 'Rule', {
listener: this,
priority: props.priority,
...props,
});
} else {
throw new Error('priority must be set for actions added to an imported listener');
}
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -707,6 +707,85 @@ describe('tests', () => {
});
});

test('Can add actions to an imported listener', () => {
// GIVEN
const stack = new cdk.Stack();
const stack2 = new cdk.Stack();
const vpc = new ec2.Vpc(stack, 'VPC');
const lb = new elbv2.ApplicationLoadBalancer(stack, 'LoadBalancer', {
vpc,
});
const listener = lb.addListener('Listener', {
port: 80,
});

// WHEN
listener.addAction('Default', {
action: elbv2.ListenerAction.fixedResponse(404, {
contentType: 'text/plain',
messageBody: 'Not Found',
}),
});

const importedListener = elbv2.ApplicationListener.fromApplicationListenerAttributes(stack2, 'listener', {
listenerArn: 'listener-arn',
defaultPort: 443,
securityGroup: ec2.SecurityGroup.fromSecurityGroupId(stack2, 'SG', 'security-group-id', {
allowAllOutbound: false,
}),
});
importedListener.addAction('Hello', {
action: elbv2.ListenerAction.fixedResponse(503),
conditions: [elbv2.ListenerCondition.pathPatterns(['/hello'])],
priority: 10,
});

// THEN
Template.fromStack(stack).hasResourceProperties('AWS::ElasticLoadBalancingV2::Listener', {
DefaultActions: [
{
FixedResponseConfig: {
ContentType: 'text/plain',
MessageBody: 'Not Found',
StatusCode: '404',
},
Type: 'fixed-response',
},
],
});

Template.fromStack(stack2).hasResourceProperties('AWS::ElasticLoadBalancingV2::ListenerRule', {
ListenerArn: 'listener-arn',
Priority: 10,
Actions: [
{
FixedResponseConfig: {
StatusCode: '503',
},
Type: 'fixed-response',
},
],
});
});

test('actions added to an imported listener must have a priority', () => {
// GIVEN
const stack = new cdk.Stack();

const importedListener = elbv2.ApplicationListener.fromApplicationListenerAttributes(stack, 'listener', {
listenerArn: 'listener-arn',
defaultPort: 443,
securityGroup: ec2.SecurityGroup.fromSecurityGroupId(stack, 'SG', 'security-group-id', {
allowAllOutbound: false,
}),
});
expect(() => {
importedListener.addAction('Hello', {
action: elbv2.ListenerAction.fixedResponse(503),
});
}).toThrow(/priority must be set for actions added to an imported listener/);
});

testDeprecated('Can add redirect responses', () => {
// GIVEN
const stack = new cdk.Stack();
Expand Down

0 comments on commit 18a6b0c

Please sign in to comment.