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(elasticloadbalancing): classic load balancer supports ec2 instances #24353

Merged
merged 14 commits into from
Mar 17, 2023
20 changes: 19 additions & 1 deletion packages/@aws-cdk/aws-elasticloadbalancing/lib/load-balancer.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import {
Connections, IConnectable, ISecurityGroup, IVpc, Peer, Port,
Connections, IConnectable, Instance, ISecurityGroup, IVpc, Peer, Port,
SecurityGroup, SelectedSubnets, SubnetSelection, SubnetType,
} from '@aws-cdk/aws-ec2';
import { Duration, Lazy, Resource } from '@aws-cdk/core';
Expand Down Expand Up @@ -400,6 +400,24 @@ export class LoadBalancer extends Resource implements IConnectable {
}
}

/**
* An EC2 instance that is the target for load balancing
*
rix0rrr marked this conversation as resolved.
Show resolved Hide resolved
* If you register a target of this type, you are responsible for making
* sure the load balancer's security group can connect to the instance.
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd rather we take of this for the user.

*/
export class InstanceTarget implements ILoadBalancerTarget {
/**
* Create a new Instance target.
*
* @param instance Instance to register to.
* @param connections The network connections associated with this resource.
*/
constructor(public readonly instance: Instance, public readonly connections: Connections) {
Copy link
Contributor

Choose a reason for hiding this comment

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

An Instance already has Connections, so you don't need to pass any additional ones.

Copy link
Contributor

Choose a reason for hiding this comment

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

I think we might need port as input though! How else are we going to know what port to forward to?

}
public attachToClassicLB(_loadBalancer: LoadBalancer): void {
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
public attachToClassicLB(_loadBalancer: LoadBalancer): void {
public attachToClassicLB(loadBalancer: LoadBalancer): void {

The _ is usually used to describe a property that has to be in the function definition, but not used in the function. Usually the case is when you are implementing an inherited function but some properties in the definition are not useful for your particular implementation. Here, you are using loadBalancer, so there's no need to add _ as a prefix.

}
kaizencc marked this conversation as resolved.
Show resolved Hide resolved
}
/**
* Reference to a listener's port just created.
*
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Template } from '@aws-cdk/assertions';
import { Connections, Peer, SubnetType, Vpc } from '@aws-cdk/aws-ec2';
import { AmazonLinuxGeneration, Connections, Instance, InstanceClass, InstanceSize, InstanceType, MachineImage, Peer, Port, SecurityGroup, SubnetType, Vpc } from '@aws-cdk/aws-ec2';
import { testDeprecated } from '@aws-cdk/cdk-build-tools';
import { Duration, Stack } from '@aws-cdk/core';
import { ILoadBalancerTarget, LoadBalancer, LoadBalancingProtocol } from '../lib';
import { ILoadBalancerTarget, InstanceTarget, LoadBalancer, LoadBalancingProtocol } from '../lib';

describe('tests', () => {
test('test specifying nonstandard port works', () => {
Expand Down Expand Up @@ -89,6 +89,78 @@ describe('tests', () => {
});
});

test('add an Instance as load balancing target', () => {
// GIVEN
const stack = new Stack();
const vpc = new Vpc(stack, 'VCP');
const securityGroup = new SecurityGroup(stack, 'simple-instance-1-sg',
{
vpc,
allowAllOutbound: true, // will let your instance send outboud traffic
securityGroupName: 'simple-instance-1-sg',
},
);

// lets use the security group to allow inbound traffic on specific ports
securityGroup.addIngressRule(
Peer.anyIpv4(),
Port.tcp(22),
'Allows SSH access from Internet',
);

securityGroup.addIngressRule(
Peer.anyIpv4(),
Port.tcp(80),
'Allows HTTP access from Internet',
);

securityGroup.addIngressRule(
Peer.anyIpv4(),
Port.tcp(443),
'Allows HTTPS access from Internet',
);
Copy link
Contributor

Choose a reason for hiding this comment

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

This looks like it's testing things about SecurityGroup, but we're not actually testing SecurityGroup here.

const instance = new Instance(stack, 'targetInstance', {
vpc: vpc,
instanceType: InstanceType.of( // t2.micro has free tier usage in aws
InstanceClass.T2,
InstanceSize.MICRO,
),
machineImage: MachineImage.latestAmazonLinux({
generation: AmazonLinuxGeneration.AMAZON_LINUX_2,
}),
securityGroup,
});
const connections = new Connections({
peer: Peer.ipv4('666.666.666.666/666'),
});
const elb = new LoadBalancer(stack, 'LB', {
vpc,
healthCheck: {
interval: Duration.minutes(1),
path: '/ping',
protocol: LoadBalancingProtocol.HTTPS,
port: 443,
},
Copy link
Contributor

Choose a reason for hiding this comment

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

We're also not testing health checks.

});

// WHEN
elb.addListener({ externalPort: 80, internalPort: 8080 });
elb.addTarget(new InstanceTarget(instance, connections));
Copy link
Contributor

Choose a reason for hiding this comment

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

OK I see that attachToClassicLB is tested via the addTarget API since elb.addTarget is implemented like this:

  public addTarget(target: ILoadBalancerTarget) {
    target.attachToClassicLB(this);

    this.newTarget(target);
  }

TO me, it seems like attachToClassicLB should be the place where we implement the 'attaching' code and it's quite odd that it's empty...


// THEN: at the very least it added a security group rule for the backend
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this really demonstrate that an instance has been attached to a load balancer?

Copy link
Contributor

Choose a reason for hiding this comment

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

Comment about security group should be updated to explain how the test works now.

Template.fromStack(stack).hasResourceProperties('AWS::EC2::SecurityGroup', {
SecurityGroupEgress: [
{
Description: 'Port 8080 LB to fleet',
CidrIp: '666.666.666.666/666',
FromPort: 8080,
IpProtocol: 'tcp',
ToPort: 8080,
},
],
});
});

test('enable cross zone load balancing', () => {
// GIVEN
const stack = new Stack();
Expand Down