Skip to content

Commit

Permalink
feat(elasticloadbalancing): add subnet selection (#2833) (#3415)
Browse files Browse the repository at this point in the history
* feat(elasticloadbalancing): add subnet selection (#2833)

Add the ability to specify the subnets the classic load balancer is
deployed to.

closes (#2833)

* feat(elasticloadbalancing): add subnet selection (#2833)

Update subnetSelection property to follow API standards

closes(#2833)
  • Loading branch information
ScOut3R authored and mergify[bot] committed Aug 8, 2019
1 parent fa48e89 commit 14e4bc9
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 5 deletions.
33 changes: 29 additions & 4 deletions packages/@aws-cdk/aws-elasticloadbalancing/lib/load-balancer.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Connections, IConnectable, ISecurityGroup, ISubnet, IVpc, Peer, Port, SecurityGroup } from '@aws-cdk/aws-ec2';
import { Connections, IConnectable, ISecurityGroup, IVpc, Peer, Port,
SecurityGroup, SelectedSubnets, SubnetSelection, SubnetType } from '@aws-cdk/aws-ec2';
import { Construct, Duration, Lazy, Resource } from '@aws-cdk/core';
import { CfnLoadBalancer } from './elasticloadbalancing.generated';

Expand Down Expand Up @@ -57,6 +58,16 @@ export interface LoadBalancerProps {
* @default true
*/
readonly crossZone?: boolean;

/**
* Which subnets to deploy the load balancer
*
* Can be used to define a specific set of subnets to deploy the load balancer to.
* Useful multiple public or private subnets are covering the same availability zone.
*
* @default - Public subnets if internetFacing, Private subnets otherwise
*/
readonly subnetSelection?: SubnetSelection;
}

/**
Expand Down Expand Up @@ -226,18 +237,18 @@ export class LoadBalancer extends Resource implements IConnectable {
this.connections = new Connections({ securityGroups: [this.securityGroup] });

// Depending on whether the ELB has public or internal IPs, pick the right backend subnets
const subnets: ISubnet[] = props.internetFacing ? props.vpc.publicSubnets : props.vpc.privateSubnets;
const selectedSubnets: SelectedSubnets = loadBalancerSubnets(props);

this.elb = new CfnLoadBalancer(this, 'Resource', {
securityGroups: [ this.securityGroup.securityGroupId ],
subnets: subnets.map(s => s.subnetId),
subnets: selectedSubnets.subnetIds,
listeners: Lazy.anyValue({ produce: () => this.listeners }),
scheme: props.internetFacing ? 'internet-facing' : 'internal',
healthCheck: props.healthCheck && healthCheckToJSON(props.healthCheck),
crossZone: (props.crossZone === undefined || props.crossZone) ? true : false
});
if (props.internetFacing) {
this.elb.node.addDependency(...subnets.map(s => s.internetConnectivityEstablished));
this.elb.node.addDependency(selectedSubnets.internetConnectivityEstablished);
}

ifUndefined(props.listeners, []).forEach(b => this.addListener(b));
Expand Down Expand Up @@ -426,3 +437,17 @@ function healthCheckToJSON(healthCheck: HealthCheck): CfnLoadBalancer.HealthChec
unhealthyThreshold: ifUndefined(healthCheck.unhealthyThreshold, 5).toString(),
};
}

function loadBalancerSubnets(props: LoadBalancerProps): SelectedSubnets {
if (props.subnetSelection !== undefined) {
return props.vpc.selectSubnets(props.subnetSelection);
} else if (props.internetFacing) {
return props.vpc.selectSubnets({
subnetType: SubnetType.PUBLIC
});
} else {
return props.vpc.selectSubnets({
subnetType: SubnetType.PRIVATE
});
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { expect, haveResource } from '@aws-cdk/assert';
import { Connections, Peer, Vpc } from '@aws-cdk/aws-ec2';
import { Connections, Peer, SubnetType, Vpc } from '@aws-cdk/aws-ec2';
import { Duration, Stack } from '@aws-cdk/core';
import { Test } from 'nodeunit';
import { ILoadBalancerTarget, LoadBalancer, LoadBalancingProtocol } from '../lib';
Expand Down Expand Up @@ -151,6 +151,47 @@ export = {
test.done();
},

'use specified subnet'(test: Test) {
// GIVEN
const stack = new Stack();
const vpc = new Vpc(stack, 'VCP', {
subnetConfiguration: [
{
name: 'public',
subnetType: SubnetType.PUBLIC,
cidrMask: 21
},
{
name: 'private1',
subnetType: SubnetType.PRIVATE,
cidrMask: 21
},
{
name: 'private2',
subnetType: SubnetType.PRIVATE,
cidrMask: 21
}
],
});

// WHEN
new LoadBalancer(stack, 'LB', {
vpc,
subnetSelection: {
subnetName: 'private1'
},
});

// THEN
expect(stack).to(haveResource('AWS::ElasticLoadBalancing::LoadBalancer', {
Subnets: vpc.selectSubnets({
subnetName: 'private1'
}).subnetIds.map((subnetId: string) => stack.resolve(subnetId))
}));

test.done();
}

};

class FakeTarget implements ILoadBalancerTarget {
Expand Down

0 comments on commit 14e4bc9

Please sign in to comment.