Skip to content

Commit

Permalink
refactor(elbv2): make load balancer targets bind to interfaces (#4132)
Browse files Browse the repository at this point in the history
The `attachToApplicationTargetGroup()` (and similar for the NLB) methods
of the load balancer target interfaces took a concrete TargetGroup
class.

This deviates from established CDK standards, and prevents their use
with imported TargetGroups.

Bring the code in line with expectations.

Fixes #4121.
  • Loading branch information
rix0rrr authored Sep 25, 2019
1 parent 602bac2 commit 1180c1b
Show file tree
Hide file tree
Showing 8 changed files with 41 additions and 20 deletions.
17 changes: 13 additions & 4 deletions packages/@aws-cdk/aws-autoscaling/lib/auto-scaling-group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -294,7 +294,7 @@ abstract class AutoScalingGroupBase extends Resource implements IAutoScalingGrou
*/
public scaleOnRequestCount(id: string, props: RequestCountScalingProps): TargetTrackingScalingPolicy {
if (this.albTargetGroup === undefined) {
throw new Error('Attach the AutoScalingGroup to an Application Load Balancer before calling scaleOnRequestCount()');
throw new Error('Attach the AutoScalingGroup to a non-imported Application Load Balancer before calling scaleOnRequestCount()');
}

const resourceLabel = `${this.albTargetGroup.firstLoadBalancerFullName}/${this.albTargetGroup.targetGroupFullName}`;
Expand Down Expand Up @@ -545,17 +545,26 @@ export class AutoScalingGroup extends AutoScalingGroupBase implements
/**
* Attach to ELBv2 Application Target Group
*/
public attachToApplicationTargetGroup(targetGroup: elbv2.ApplicationTargetGroup): elbv2.LoadBalancerTargetProps {
public attachToApplicationTargetGroup(targetGroup: elbv2.IApplicationTargetGroup): elbv2.LoadBalancerTargetProps {
if (this.albTargetGroup !== undefined) {
throw new Error('Cannot add AutoScalingGroup to 2nd Target Group');
}

this.targetGroupArns.push(targetGroup.targetGroupArn);
this.albTargetGroup = targetGroup;
if (targetGroup instanceof elbv2.ApplicationTargetGroup) {
// Copy onto self if it's a concrete type. We need this for autoscaling
// based on request count, which we cannot do with an imported TargetGroup.
this.albTargetGroup = targetGroup;
}

targetGroup.registerConnectable(this);
return { targetType: elbv2.TargetType.INSTANCE };
}

/**
* Attach to ELBv2 Application Target Group
*/
public attachToNetworkTargetGroup(targetGroup: elbv2.NetworkTargetGroup): elbv2.LoadBalancerTargetProps {
public attachToNetworkTargetGroup(targetGroup: elbv2.INetworkTargetGroup): elbv2.LoadBalancerTargetProps {
this.targetGroupArns.push(targetGroup.targetGroupArn);
return { targetType: elbv2.TargetType.INSTANCE };
}
Expand Down
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-ecs/lib/base/base-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ export abstract class BaseService extends Resource
* Don't call this function directly. Instead, call `listener.addTargets()`
* to add this service to a load balancer.
*/
public attachToApplicationTargetGroup(targetGroup: elbv2.ApplicationTargetGroup): elbv2.LoadBalancerTargetProps {
public attachToApplicationTargetGroup(targetGroup: elbv2.IApplicationTargetGroup): elbv2.LoadBalancerTargetProps {
return this.defaultLoadBalancerTarget.attachToApplicationTargetGroup(targetGroup);
}

Expand Down Expand Up @@ -282,7 +282,7 @@ export abstract class BaseService extends Resource
* Don't call this function directly. Instead, call `listener.addTargets()`
* to add this service to a load balancer.
*/
public attachToNetworkTargetGroup(targetGroup: elbv2.NetworkTargetGroup): elbv2.LoadBalancerTargetProps {
public attachToNetworkTargetGroup(targetGroup: elbv2.INetworkTargetGroup): elbv2.LoadBalancerTargetProps {
return this.defaultLoadBalancerTarget.attachToNetworkTargetGroup(targetGroup);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export class InstanceIdTarget implements elbv2.IApplicationLoadBalancerTarget, e
* Don't call this, it is called automatically when you add the target to a
* load balancer.
*/
public attachToApplicationTargetGroup(targetGroup: elbv2.ApplicationTargetGroup): elbv2.LoadBalancerTargetProps {
public attachToApplicationTargetGroup(targetGroup: elbv2.IApplicationTargetGroup): elbv2.LoadBalancerTargetProps {
return this.attach(targetGroup);
}

Expand All @@ -33,7 +33,7 @@ export class InstanceIdTarget implements elbv2.IApplicationLoadBalancerTarget, e
* Don't call this, it is called automatically when you add the target to a
* load balancer.
*/
public attachToNetworkTargetGroup(targetGroup: elbv2.NetworkTargetGroup): elbv2.LoadBalancerTargetProps {
public attachToNetworkTargetGroup(targetGroup: elbv2.INetworkTargetGroup): elbv2.LoadBalancerTargetProps {
return this.attach(targetGroup);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ export class IpTarget implements elbv2.IApplicationLoadBalancerTarget, elbv2.INe
* Don't call this, it is called automatically when you add the target to a
* load balancer.
*/
public attachToApplicationTargetGroup(targetGroup: elbv2.ApplicationTargetGroup): elbv2.LoadBalancerTargetProps {
public attachToApplicationTargetGroup(targetGroup: elbv2.IApplicationTargetGroup): elbv2.LoadBalancerTargetProps {
return this.attach(targetGroup);
}

Expand All @@ -53,7 +53,7 @@ export class IpTarget implements elbv2.IApplicationLoadBalancerTarget, elbv2.INe
* Don't call this, it is called automatically when you add the target to a
* load balancer.
*/
public attachToNetworkTargetGroup(targetGroup: elbv2.NetworkTargetGroup): elbv2.LoadBalancerTargetProps {
public attachToNetworkTargetGroup(targetGroup: elbv2.INetworkTargetGroup): elbv2.LoadBalancerTargetProps {
return this.attach(targetGroup);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class LambdaTarget implements elbv2.IApplicationLoadBalancerTarget {
* Don't call this, it is called automatically when you add the target to a
* load balancer.
*/
public attachToApplicationTargetGroup(targetGroup: elbv2.ApplicationTargetGroup): elbv2.LoadBalancerTargetProps {
public attachToApplicationTargetGroup(targetGroup: elbv2.IApplicationTargetGroup): elbv2.LoadBalancerTargetProps {
this.fn.grantInvoke(new iam.ServicePrincipal('elasticloadbalancing.amazonaws.com'));
return this.attach(targetGroup);
}
Expand All @@ -28,7 +28,7 @@ export class LambdaTarget implements elbv2.IApplicationLoadBalancerTarget {
* Don't call this, it is called automatically when you add the target to a
* load balancer.
*/
public attachToNetworkTargetGroup(targetGroup: elbv2.NetworkTargetGroup): elbv2.LoadBalancerTargetProps {
public attachToNetworkTargetGroup(targetGroup: elbv2.INetworkTargetGroup): elbv2.LoadBalancerTargetProps {
this.fn.grantInvoke(new iam.ServicePrincipal('elasticloadbalancing.amazonaws.com'));
return this.attach(targetGroup);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,13 @@ export interface IApplicationTargetGroup extends ITargetGroup {
* Don't call this directly. It will be called by listeners.
*/
registerListener(listener: IApplicationListener, associatingConstruct?: IConstruct): void;

/**
* Register a connectable as a member of this target group.
*
* Don't call this directly. It will be called by load balancing targets.
*/
registerConnectable(connectable: ec2.IConnectable, portRange?: ec2.Port): void;
}

/**
Expand All @@ -346,6 +353,11 @@ export interface IApplicationTargetGroup extends ITargetGroup {
class ImportedApplicationTargetGroup extends ImportedTargetGroupBase implements IApplicationTargetGroup {
public registerListener(_listener: IApplicationListener, _associatingConstruct?: IConstruct) {
// Nothing to do, we know nothing of our members
this.node.addWarning(`Cannot register listener on imported target group -- security groups might need to be updated manually`);
}

public registerConnectable(_connectable: ec2.IConnectable, _portRange?: ec2.Port | undefined): void {
this.node.addWarning(`Cannot register connectable on imported target group -- security groups might need to be updated manually`);
}
}

Expand All @@ -359,5 +371,5 @@ export interface IApplicationLoadBalancerTarget {
* May return JSON to directly add to the [Targets] list, or return undefined
* if the target will register itself with the load balancer.
*/
attachToApplicationTargetGroup(targetGroup: ApplicationTargetGroup): LoadBalancerTargetProps;
attachToApplicationTargetGroup(targetGroup: IApplicationTargetGroup): LoadBalancerTargetProps;
}
Original file line number Diff line number Diff line change
Expand Up @@ -124,5 +124,5 @@ export interface INetworkLoadBalancerTarget {
* May return JSON to directly add to the [Targets] list, or return undefined
* if the target will register itself with the load balancer.
*/
attachToNetworkTargetGroup(targetGroup: NetworkTargetGroup): LoadBalancerTargetProps;
attachToNetworkTargetGroup(targetGroup: INetworkTargetGroup): LoadBalancerTargetProps;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { ApplicationTargetGroup, IApplicationLoadBalancerTarget } from "../alb/application-target-group";
import { INetworkLoadBalancerTarget, NetworkTargetGroup } from "../nlb/network-target-group";
import { IApplicationLoadBalancerTarget, IApplicationTargetGroup } from "../alb/application-target-group";
import { INetworkLoadBalancerTarget, INetworkTargetGroup } from "../nlb/network-target-group";
import { ITargetGroup, LoadBalancerTargetProps } from "./base-target-group";
import { TargetType } from "./enums";

Expand Down Expand Up @@ -27,7 +27,7 @@ export class InstanceTarget implements IApplicationLoadBalancerTarget, INetworkL
* Don't call this, it is called automatically when you add the target to a
* load balancer.
*/
public attachToApplicationTargetGroup(targetGroup: ApplicationTargetGroup): LoadBalancerTargetProps {
public attachToApplicationTargetGroup(targetGroup: IApplicationTargetGroup): LoadBalancerTargetProps {
return this.attach(targetGroup);
}

Expand All @@ -37,7 +37,7 @@ export class InstanceTarget implements IApplicationLoadBalancerTarget, INetworkL
* Don't call this, it is called automatically when you add the target to a
* load balancer.
*/
public attachToNetworkTargetGroup(targetGroup: NetworkTargetGroup): LoadBalancerTargetProps {
public attachToNetworkTargetGroup(targetGroup: INetworkTargetGroup): LoadBalancerTargetProps {
return this.attach(targetGroup);
}

Expand Down Expand Up @@ -94,7 +94,7 @@ export class IpTarget implements IApplicationLoadBalancerTarget, INetworkLoadBal
* Don't call this, it is called automatically when you add the target to a
* load balancer.
*/
public attachToApplicationTargetGroup(targetGroup: ApplicationTargetGroup): LoadBalancerTargetProps {
public attachToApplicationTargetGroup(targetGroup: IApplicationTargetGroup): LoadBalancerTargetProps {
return this.attach(targetGroup);
}

Expand All @@ -104,7 +104,7 @@ export class IpTarget implements IApplicationLoadBalancerTarget, INetworkLoadBal
* Don't call this, it is called automatically when you add the target to a
* load balancer.
*/
public attachToNetworkTargetGroup(targetGroup: NetworkTargetGroup): LoadBalancerTargetProps {
public attachToNetworkTargetGroup(targetGroup: INetworkTargetGroup): LoadBalancerTargetProps {
return this.attach(targetGroup);
}

Expand Down

2 comments on commit 1180c1b

@rob-gonz
Copy link

Choose a reason for hiding this comment

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

@rix0rrr ,
Sorry to call you out directly, but changes in at least this commit are directly hindering a deployment for us. At the very least, the error I'm encountering is from this commit. I've tried Stackoverflow, searching gitter history, reading aws docs, and actually trying stuff in the aws console. I have not found something that will help me with regards to formulating my infrastructure differently in aws-cdk. From what I can tell, what I'm trying is possible. I have live servers with the setup running right now.

This is getting triggered on cdk diff and cdk deploy:
1180c1b#diff-2db67fa7f5c77699be5c76d95371fcd5R550

It appears there is now a restriction on adding AutoScalingGroups to multiple Target Groups. I have had code that has been working fine since 0.8.0 and has not been modified (except for breaking changes). After upgrading beyond 1.13.0 I'm now encountering problems with no clear resolution available.

I need to have multiple Load Balancers(ALB's) point to the same ASG. Something must have changed with how Target groups are constructed in these later versions.

The reason for this setup is each website needs to have its own external IP, they cannot share. Thus each get's its own load balancer(ALB). I cannot deploy to my staging and then to production because of this.

Again, sorry for having to hit you up directly.

@hikeeba
Copy link

@hikeeba hikeeba commented on 1180c1b Mar 3, 2020

Choose a reason for hiding this comment

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

Agreed, this commit is causing us problems as well. We need an ASG to be attached multiple times to a target group because of multiple applications running on our instances with different ports.

Please sign in to comment.