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): default config for internal load balancer will fall back to Isolated subnets #5696

Merged
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ export interface BaseLoadBalancerProps {
/**
* Where in the VPC to place the load balancer
*
* @default - Public subnets if internetFacing, otherwise private subnets.
* @default - Public subnets if internetFacing, Private subnets if internal and
* there are Private subnets, Isolated subnets if internal and there are no
* Private subnets.
*/
readonly vpcSubnets?: ec2.SubnetSelection;

Expand Down Expand Up @@ -127,8 +129,29 @@ export abstract class BaseLoadBalancer extends Resource {

const internetFacing = ifUndefined(baseProps.internetFacing, false);

const hasPrivateSubnets = baseProps.vpc.privateSubnets !== undefined && baseProps.vpc.privateSubnets.length > 0;
const hasPublicSubnets = baseProps.vpc.publicSubnets !== undefined && baseProps.vpc.publicSubnets.length > 0;
const hasIsolatedSubnets = baseProps.vpc.isolatedSubnets !== undefined && baseProps.vpc.isolatedSubnets.length > 0;

let vpcSubnetType;
if (internetFacing) {
if (!hasPublicSubnets) {
throw new Error("Internet-facing load balancer requires 'Public' subnets, but none were found.");
} else {
vpcSubnetType = ec2.SubnetType.PUBLIC;
}
} else {
if (hasPrivateSubnets) {
vpcSubnetType = ec2.SubnetType.PRIVATE;
} else if (hasIsolatedSubnets) {
vpcSubnetType = ec2.SubnetType.ISOLATED;
} else {
throw new Error("Internal load balancer requires 'Private' or 'Isolated' subnets, but none were found.");
flemjame-at-amazon marked this conversation as resolved.
Show resolved Hide resolved
}
}

const vpcSubnets = ifUndefined(baseProps.vpcSubnets,
{ subnetType: internetFacing ? ec2.SubnetType.PUBLIC : ec2.SubnetType.PRIVATE });
{ subnetType: vpcSubnetType });
Copy link
Contributor

Choose a reason for hiding this comment

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

I recently updated Vpc to have some of this behavior already (private => isolated as a fallback).

Can you try the following and see if that behaves the same?

const vpcSubnets = ... (internetFacing ? { subnetType: PUBLIC } : {});

I.e. leave subnetType empty, rely on the Vpc default to try private => isolated => public in that order?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That just worked, no additional changes to tests needed.


const { subnetIds, internetConnectivityEstablished } = baseProps.vpc.selectSubnets(vpcSubnets);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,110 @@ export = {
Name: 'myLoadBalancer'
}));
test.done();
}
},
'Trivial construction: internal with Isolated subnets only'(test: Test) {
// GIVEN
const stack = new cdk.Stack();
const vpc = new ec2.Vpc(stack, 'VPC', {
subnetConfiguration: [{
cidrMask: 20,
name: 'Isolated',
subnetType: ec2.SubnetType.ISOLATED,
}]
});

// WHEN
new elbv2.NetworkLoadBalancer(stack, 'LB', {
vpc,
internetFacing: false,
});

// THEN
expect(stack).to(haveResource('AWS::ElasticLoadBalancingV2::LoadBalancer', {
Scheme: "internal",
Subnets: [
{ Ref: "VPCIsolatedSubnet1SubnetEBD00FC6" },
{ Ref: "VPCIsolatedSubnet2Subnet4B1C8CAA" },
],
Type: "network"
}));

test.done();
},
'Internal with Public, Private, and Isolated subnets'(test: Test) {
// GIVEN
const stack = new cdk.Stack();
const vpc = new ec2.Vpc(stack, 'VPC', {
subnetConfiguration: [{
cidrMask: 24,
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC,
}, {
cidrMask: 24,
name: 'Private',
subnetType: ec2.SubnetType.PRIVATE,
}, {
cidrMask: 28,
name: 'Isolated',
subnetType: ec2.SubnetType.ISOLATED,
}
]
});

// WHEN
new elbv2.NetworkLoadBalancer(stack, 'LB', {
vpc,
internetFacing: false,
});

// THEN
expect(stack).to(haveResource('AWS::ElasticLoadBalancingV2::LoadBalancer', {
Scheme: "internal",
Subnets: [
{ Ref: "VPCPrivateSubnet1Subnet8BCA10E0" },
{ Ref: "VPCPrivateSubnet2SubnetCFCDAA7A" },
],
Type: "network"
}));

test.done();
},
'Internet-facing with Public, Private, and Isolated subnets'(test: Test) {
// GIVEN
const stack = new cdk.Stack();
const vpc = new ec2.Vpc(stack, 'VPC', {
subnetConfiguration: [{
cidrMask: 24,
name: 'Public',
subnetType: ec2.SubnetType.PUBLIC,
}, {
cidrMask: 24,
name: 'Private',
subnetType: ec2.SubnetType.PRIVATE,
}, {
cidrMask: 28,
name: 'Isolated',
subnetType: ec2.SubnetType.ISOLATED,
}
]
});

// WHEN
new elbv2.NetworkLoadBalancer(stack, 'LB', {
vpc,
internetFacing: true,
});

// THEN
expect(stack).to(haveResource('AWS::ElasticLoadBalancingV2::LoadBalancer', {
Scheme: "internet-facing",
Subnets: [
{ Ref: "VPCPublicSubnet1SubnetB4246D30" },
{ Ref: "VPCPublicSubnet2Subnet74179F39" },
],
Type: "network"
}));

test.done();
}
};