Skip to content

Commit

Permalink
feat(ecs): add a new API for registering ECS targets (#4212)
Browse files Browse the repository at this point in the history
* Add new API to register ECS targets

* Refactor registerContainerTargets

* Add more unit tests and integ tests

* Rebase and refactor to flat list for new API input

* Refactor to eliminate type union

* Minor refactoring and name change

* Add more comments and README

* Minor change to test name
  • Loading branch information
iamhopaul123 authored and mergify[bot] committed Oct 4, 2019
1 parent 032b70c commit de84c4a
Show file tree
Hide file tree
Showing 5 changed files with 1,110 additions and 0 deletions.
23 changes: 23 additions & 0 deletions packages/@aws-cdk/aws-ecs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,29 @@ const target = listener.addTargets('ECS', {
});
```

Alternatively, you can also create all load balancer targets to be registered in this service, add them to target groups, and attach target groups to listeners accordingly.

```ts
import elbv2 = require('@aws-cdk/aws-elasticloadbalancingv2');

const service = new ecs.FargateService(this, 'Service', { /* ... */ });

const lb = new elbv2.ApplicationLoadBalancer(this, 'LB', { vpc, internetFacing: true });
const listener = lb.addListener('Listener', { port: 80 });
service.registerLoadBalancerTargets(
{
containerTarget: {
containerName: 'web',
containerPort: 80,
},
targetGroupId: 'ECS',
listener: ecs.ListenerConfig.applicationListener(listener, {
protocol: elbv2.ApplicationProtocol.HTTPS
}),
},
);
```

### Include a classic load balancer
`Services` can also be directly attached to a classic load balancer as targets:

Expand Down
138 changes: 138 additions & 0 deletions packages/@aws-cdk/aws-ecs/lib/base/base-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import cloudmap = require('@aws-cdk/aws-servicediscovery');
import { Construct, Duration, IResolvable, IResource, Lazy, Resource, Stack } from '@aws-cdk/core';
import { LoadBalancerTargetOptions, NetworkMode, TaskDefinition } from '../base/task-definition';
import { ICluster } from '../cluster';
import { Protocol } from '../container-definition';
import { CfnService } from '../ecs.generated';
import { ScalableTaskCount } from './scalable-task-count';

Expand All @@ -23,6 +24,37 @@ export interface IService extends IResource {
readonly serviceArn: string;
}

export interface EcsTarget {
/**
* The name of the container.
*/
readonly containerName: string;

/**
* The port number of the container. Only applicable when using application/network load balancers.
*
* @default - Container port of the first added port mapping.
*/
readonly containerPort?: number;

/**
* The protocol used for the port mapping. Only applicable when using application load balancers.
*
* @default Protocol.TCP
*/
readonly protocol?: Protocol;

/**
* ID for a target group to be created.
*/
readonly newTargetGroupId: string;

/**
* Listener and properties for adding target group to the listener.
*/
readonly listener: ListenerConfig;
}

/**
* Interface for ECS load balancer target.
*/
Expand Down Expand Up @@ -116,6 +148,83 @@ export interface BaseServiceProps extends BaseServiceOptions {
readonly launchType: LaunchType;
}

/**
* Base class for configuring listener when registering targets.
*/
export abstract class ListenerConfig {
/**
* Create a config for adding target group to ALB listener.
*/
public static applicationListener(listener: elbv2.ApplicationListener, props?: elbv2.AddApplicationTargetsProps): ListenerConfig {
return new ApplicationListenerConfig(listener, props);
}

/**
* Create a config for adding target group to NLB listener.
*/
public static networkListener(listener: elbv2.NetworkListener, props?: elbv2.AddNetworkTargetsProps): ListenerConfig {
return new NetworkListenerConfig(listener, props);
}

/**
* Create and attach a target group to listener.
*/
public abstract addTargets(id: string, target: LoadBalancerTargetOptions, service: BaseService): void;
}

/**
* Class for configuring application load balancer listener when registering targets.
*/
class ApplicationListenerConfig extends ListenerConfig {
constructor(private readonly listener: elbv2.ApplicationListener, private readonly props?: elbv2.AddApplicationTargetsProps) {
super();
}

/**
* Create and attach a target group to listener.
*/
public addTargets(id: string, target: LoadBalancerTargetOptions, service: BaseService) {
const props = this.props || {};
const protocol = props.protocol;
const port = props.port !== undefined ? props.port : (protocol === undefined ? 80 :
(protocol === elbv2.ApplicationProtocol.HTTPS ? 443 : 80));
this.listener.addTargets(id, {
... props,
targets: [
service.loadBalancerTarget({
...target
})
],
port
});
}
}

/**
* Class for configuring network load balancer listener when registering targets.
*/
class NetworkListenerConfig extends ListenerConfig {
constructor(private readonly listener: elbv2.NetworkListener, private readonly props?: elbv2.AddNetworkTargetsProps) {
super();
}

/**
* Create and attach a target group to listener.
*/
public addTargets(id: string, target: LoadBalancerTargetOptions, service: BaseService) {
const port = this.props !== undefined ? this.props.port : 80;
this.listener.addTargets(id, {
... this.props,
targets: [
service.loadBalancerTarget({
...target
})
],
port
});
}
}

/**
* The base class for Ec2Service and FargateService services.
*/
Expand Down Expand Up @@ -283,6 +392,35 @@ export abstract class BaseService extends Resource
};
}

/**
* Use this function to create all load balancer targets to be registered in this service, add them to
* target groups, and attach target groups to listeners accordingly.
*
* @example
*
* service.registerLoadBalancerTargets(
* {
* containerTarget: {
* containerName: 'web',
* containerPort: 80,
* },
* targetGroupId: 'ECS',
* listener: ecs.ListenerConfig.applicationListener(listener, {
* protocol: elbv2.ApplicationProtocol.HTTPS
* }),
* },
* )
*/
public registerLoadBalancerTargets(...targets: EcsTarget[]) {
for (const target of targets) {
target.listener.addTargets(target.newTargetGroupId, {
containerName: target.containerName,
containerPort: target.containerPort,
protocol: target.protocol
}, this);
}
}

/**
* This method is called to attach this service to a Network Load Balancer.
*
Expand Down
Loading

0 comments on commit de84c4a

Please sign in to comment.