Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(elbv2): Supports new types of listener rule conditions #7848

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7247360
test(elbv2): expect to render new style listener rule condition
karupanerura May 1, 2020
b325bbc
feat(elbv2): supports new style listener rule conditions
karupanerura May 1, 2020
0351d81
test(elbv2): add test cases for new style listener rule condition tes…
karupanerura May 1, 2020
8b4f53e
refactor(elbv2): replate `setCondition` to `addCondition`
karupanerura May 1, 2020
9ac59e5
fix(elbv2): remove meaningless/broken validation
karupanerura May 1, 2020
5c73487
test(elbv2): fix aws-ecs-patterns test case
karupanerura May 1, 2020
8de2fd7
doc(elbv2): add example to use `addCondition` method
karupanerura May 1, 2020
c67387e
Revert "test(elbv2): expect to render new style listener rule condition"
karupanerura May 7, 2020
cc5841b
Revert "test(elbv2): fix aws-ecs-patterns test case"
karupanerura May 7, 2020
74cfa70
refactor(elbv2): reduce exported implements for simple
karupanerura May 7, 2020
318d82b
fix(elbv2): keep legacy cfn template format for deprecated interfaces
karupanerura May 7, 2020
07c4ae3
refactor(elbv2): remove unnecessary `removeCondition` method
karupanerura May 7, 2020
76a939d
refactor(elbv2): add `conditions` property for supports new style lis…
karupanerura May 7, 2020
f5f397c
doc(elbv2): use `conditions` in example
karupanerura May 7, 2020
5bfd267
Merge branch 'master' into feature/supports-new-alb-listener-rule2
karupanerura May 13, 2020
8b74223
refactor(elbv2): shorter names is better
karupanerura May 15, 2020
313ffed
doc(elbv2): remove obsoluted comment
karupanerura May 15, 2020
c370fad
refactor(elbv2): remove unnecesurry `field` property
karupanerura May 15, 2020
3e10e05
doc(elbv2): fix obsoluted class doc
karupanerura May 15, 2020
0d4b73a
refactor(elbv2): move condition definitions to `conditions.ts`
karupanerura May 15, 2020
173e89b
Merge branch 'master' into feature/supports-new-alb-listener-rule2
karupanerura May 19, 2020
d0df699
Merge branch 'master' into feature/supports-new-alb-listener-rule2
mergify[bot] May 21, 2020
679dd32
Merge branch 'master' into feature/supports-new-alb-listener-rule2
mergify[bot] May 21, 2020
9c43d31
Merge branch 'master' into feature/supports-new-alb-listener-rule2
mergify[bot] May 21, 2020
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
17 changes: 10 additions & 7 deletions packages/@aws-cdk/aws-elasticloadbalancingv2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,16 +64,17 @@ updated to allow the network traffic.
#### Conditions

It's possible to route traffic to targets based on conditions in the incoming
HTTP request. Path- and host-based conditions are supported. For example, the
following will route requests to the indicated AutoScalingGroup only if the
requested host in the request is either for `example.com/ok` or
`example.com/path`:
HTTP request. For example, the following will route requests to the indicated
AutoScalingGroup only if the requested host in the request is either for
`example.com/ok` or `example.com/path`:

```ts
listener.addTargets('Example.Com Fleet', {
priority: 10,
pathPatterns: ['/ok', '/path'],
hostHeader: 'example.com',
conditions: [
ListenerCondition.hostHeaders(['example.com']),
ListenerCondition.pathPatterns(['/ok', '/path']),
],
port: 8080,
targets: [asg]
});
Expand Down Expand Up @@ -126,8 +127,10 @@ Here's an example of serving a fixed response at the `/ok` URL:

```ts
listener.addAction('Fixed', {
pathPatterns: ['/ok'],
priority: 10,
conditions: [
ListenerCondition.pathPatterns(['/ok']),
],
action: ListenerAction.fixedResponse(200, {
contentType: elbv2.ContentType.TEXT_PLAIN,
messageBody: 'OK',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { IListenerAction } from '../shared/listener-action';
import { IApplicationListener } from './application-listener';
import { ListenerAction } from './application-listener-action';
import { IApplicationTargetGroup } from './application-target-group';
import { ListenerCondition } from './conditions';

/**
* Basic properties for defining a rule on a listener
Expand Down Expand Up @@ -58,6 +59,15 @@ export interface BaseApplicationListenerRuleProps {
*/
readonly redirectResponse?: RedirectResponse;

/**
* Rule applies if matches the conditions.
*
* @see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html
*
* @default - No conditions.
*/
readonly conditions?: ListenerCondition[];

/**
* Rule applies if the requested host matches the indicated host
*
Expand All @@ -66,6 +76,7 @@ export interface BaseApplicationListenerRuleProps {
* @see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html#host-conditions
*
* @default - No host condition.
* @deprecated Use `conditions` instead.
*/
readonly hostHeader?: string;

Expand All @@ -74,7 +85,7 @@ export interface BaseApplicationListenerRuleProps {
*
* @see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html#path-conditions
* @default - No path condition.
* @deprecated Use `pathPatterns` instead.
* @deprecated Use `conditions` instead.
*/
readonly pathPattern?: string;

Expand All @@ -85,6 +96,7 @@ export interface BaseApplicationListenerRuleProps {
*
* @see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html#path-conditions
* @default - No path conditions.
* @deprecated Use `conditions` instead.
*/
readonly pathPatterns?: string[];
}
Expand Down Expand Up @@ -187,17 +199,20 @@ export class ApplicationListenerRule extends cdk.Construct {
*/
public readonly listenerRuleArn: string;

private readonly conditions: {[key: string]: string[] | undefined} = {};
private readonly conditions: ListenerCondition[];
private readonly legacyConditions: {[key: string]: string[]} = {};

private readonly listener: IApplicationListener;
private action?: IListenerAction;

constructor(scope: cdk.Construct, id: string, props: ApplicationListenerRuleProps) {
super(scope, id);

this.conditions = props.conditions || [];

const hasPathPatterns = props.pathPatterns || props.pathPattern;
if (!props.hostHeader && !hasPathPatterns) {
throw new Error('At least one of \'hostHeader\', \'pathPattern\' or \'pathPatterns\' is required when defining a load balancing rule.');
if (this.conditions.length === 0 && !props.hostHeader && !hasPathPatterns) {
throw new Error('At least one of \'conditions\', \'hostHeader\', \'pathPattern\' or \'pathPatterns\' is required when defining a load balancing rule.');
}

const possibleActions: Array<keyof ApplicationListenerRuleProps> = ['action', 'targetGroups', 'fixedResponse', 'redirectResponse'];
Expand Down Expand Up @@ -248,9 +263,25 @@ export class ApplicationListenerRule extends cdk.Construct {

/**
* Add a non-standard condition to this rule
*
* If the condition conflicts with an already set condition, it will be overwritten by the one you specified.
*
* @deprecated use `addCondition` instead.
*/
public setCondition(field: string, values: string[] | undefined) {
this.conditions[field] = values;
if (values === undefined) {
delete this.legacyConditions[field];
return;
}

this.legacyConditions[field] = values;
}

/**
* Add a non-standard condition to this rule
*/
public addCondition(condition: ListenerCondition) {
this.conditions.push(condition);
}

/**
Expand Down Expand Up @@ -322,20 +353,28 @@ export class ApplicationListenerRule extends cdk.Construct {
if (this.action === undefined) {
return ['Listener rule needs at least one action'];
}

const legacyConditionFields = Object.keys(this.legacyConditions);
if (legacyConditionFields.length === 0 && this.conditions.length === 0) {
return ['Listener rule needs at least one condition'];
}

return [];
}

/**
* Render the conditions for this rule
*/
private renderConditions() {
const ret = new Array<{ field: string, values: string[] }>();
for (const [field, values] of Object.entries(this.conditions)) {
if (values !== undefined) {
ret.push({ field, values });
}
}
return ret;
private renderConditions(): any {
const legacyConditions = Object.entries(this.legacyConditions).map(([field, values]) => {
return { field, values };
});
const conditions = this.conditions.map(condition => condition.renderRawCondition());

return [
...legacyConditions,
...conditions,
];
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { ApplicationListenerCertificate } from './application-listener-certifica
import { ApplicationListenerRule, FixedResponse, RedirectResponse, validateFixedResponse, validateRedirectResponse } from './application-listener-rule';
import { IApplicationLoadBalancer } from './application-load-balancer';
import { ApplicationTargetGroup, IApplicationLoadBalancerTarget, IApplicationTargetGroup } from './application-target-group';
import { ListenerCondition } from './conditions';

/**
* Basic properties for an ApplicationListener
Expand Down Expand Up @@ -274,6 +275,7 @@ export class ApplicationListener extends BaseListener implements IApplicationLis
// TargetGroup.registerListener is called inside ApplicationListenerRule.
new ApplicationListenerRule(this, id + 'Rule', {
listener: this,
conditions: props.conditions,
hostHeader: props.hostHeader,
pathPattern: props.pathPattern,
pathPatterns: props.pathPatterns,
Expand Down Expand Up @@ -319,6 +321,7 @@ export class ApplicationListener extends BaseListener implements IApplicationLis
});

this.addTargetGroups(id, {
conditions: props.conditions,
hostHeader: props.hostHeader,
pathPattern: props.pathPattern,
pathPatterns: props.pathPatterns,
Expand Down Expand Up @@ -618,6 +621,15 @@ export interface AddRuleProps {
*/
readonly priority?: number;

/**
* Rule applies if matches the conditions.
*
* @see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html
*
* @default - No conditions.
*/
readonly conditions?: ListenerCondition[];

/**
* Rule applies if the requested host matches the indicated host
*
Expand All @@ -628,6 +640,7 @@ export interface AddRuleProps {
* @see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html#host-conditions
*
* @default No host condition
* @deprecated Use `conditions` instead.
*/
readonly hostHeader?: string;

Expand All @@ -640,7 +653,7 @@ export interface AddRuleProps {
*
* @see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html#path-conditions
* @default No path condition
* @deprecated Use `pathPatterns` instead.
* @deprecated Use `conditions` instead.
*/
readonly pathPattern?: string;

Expand All @@ -653,6 +666,7 @@ export interface AddRuleProps {
*
* @see https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-listeners.html#path-conditions
* @default - No path condition.
* @deprecated Use `conditions` instead.
*/
readonly pathPatterns?: string[];
}
Expand Down Expand Up @@ -770,7 +784,11 @@ export interface AddRedirectResponseProps extends AddRuleProps, RedirectResponse
}

function checkAddRuleProps(props: AddRuleProps) {
if ((props.hostHeader !== undefined || props.pathPattern !== undefined || props.pathPatterns !== undefined) !== (props.priority !== undefined)) {
throw new Error('Setting \'pathPattern\' or \'hostHeader\' also requires \'priority\', and vice versa');
const conditionsCount = props.conditions?.length || 0;
const hasAnyConditions = conditionsCount !== 0 ||
props.hostHeader !== undefined || props.pathPattern !== undefined || props.pathPatterns !== undefined;
const hasPriority = props.priority !== undefined;
if (hasAnyConditions !== hasPriority) {
throw new Error('Setting \'conditions\', \'pathPattern\' or \'hostHeader\' also requires \'priority\', and vice versa');
}
}
Loading