From 2e576f458c829dfbd9179626eeb1e9cc7aad0832 Mon Sep 17 00:00:00 2001 From: Austin Ely Date: Wed, 11 Dec 2019 10:47:29 -0800 Subject: [PATCH 1/6] feat(ecs-patterns): allow imported load balancers in alb/nlb constructs --- .../application-load-balanced-service-base.ts | 11 +- .../network-load-balanced-service-base.ts | 10 +- .../aws-ecs-patterns/test/ec2/test.l3s.ts | 146 ++++++++++++++++- .../test.load-balanced-fargate-service.ts | 151 +++++++++++++++++- .../lib/alb/application-listener.ts | 2 +- .../lib/alb/application-load-balancer.ts | 13 +- .../lib/nlb/network-listener.ts | 2 +- .../lib/nlb/network-load-balancer.ts | 10 +- .../lib/shared/base-load-balancer.ts | 7 +- .../test/alb/test.load-balancer.ts | 43 +++++ .../test/nlb/test.load-balancer.ts | 31 +++- 11 files changed, 403 insertions(+), 23 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts index b6a0980732b10..92a3ba2a15454 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts @@ -1,7 +1,8 @@ import { DnsValidatedCertificate, ICertificate } from '@aws-cdk/aws-certificatemanager'; import { IVpc } from '@aws-cdk/aws-ec2'; import { AwsLogDriver, BaseService, CloudMapOptions, Cluster, ContainerImage, ICluster, LogDriver, PropagatedTagSource, Secret } from '@aws-cdk/aws-ecs'; -import { ApplicationListener, ApplicationLoadBalancer, ApplicationProtocol, ApplicationTargetGroup, ListenerCertificate } from '@aws-cdk/aws-elasticloadbalancingv2'; +import { ApplicationListener, ApplicationLoadBalancer, ApplicationProtocol, ApplicationTargetGroup, + IApplicationLoadBalancer, ListenerCertificate} from '@aws-cdk/aws-elasticloadbalancingv2'; import { IRole } from '@aws-cdk/aws-iam'; import { AddressRecordTarget, ARecord, IHostedZone } from '@aws-cdk/aws-route53'; import { LoadBalancerTarget } from '@aws-cdk/aws-route53-targets'; @@ -124,7 +125,7 @@ export interface ApplicationLoadBalancedServiceBaseProps { * * @default - a new load balancer will be created. */ - readonly loadBalancer?: ApplicationLoadBalancer; + readonly loadBalancer?: IApplicationLoadBalancer; /** * Listener port of the application load balancer that will serve traffic to the service. @@ -297,12 +298,14 @@ export abstract class ApplicationLoadBalancedServiceBase extends cdk.Construct { internetFacing }; - this.loadBalancer = props.loadBalancer !== undefined ? props.loadBalancer : new ApplicationLoadBalancer(this, 'LB', lbProps); + this.loadBalancer = props.loadBalancer !== undefined ? props.loadBalancer as ApplicationLoadBalancer + : new ApplicationLoadBalancer(this, 'LB', lbProps); if (props.certificate !== undefined && props.protocol !== undefined && props.protocol !== ApplicationProtocol.HTTPS) { throw new Error('The HTTPS protocol must be used when a certificate is given'); } - const protocol = props.protocol !== undefined ? props.protocol : (props.certificate ? ApplicationProtocol.HTTPS : ApplicationProtocol.HTTP); + const protocol = props.protocol !== undefined ? props.protocol : + (props.certificate ? ApplicationProtocol.HTTPS : ApplicationProtocol.HTTP); const targetProps = { port: 80 diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts index 7e0e355b01b5b..81fc4542b7862 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts @@ -1,6 +1,6 @@ import { IVpc } from '@aws-cdk/aws-ec2'; import { AwsLogDriver, BaseService, CloudMapOptions, Cluster, ContainerImage, ICluster, LogDriver, PropagatedTagSource, Secret } from '@aws-cdk/aws-ecs'; -import { NetworkListener, NetworkLoadBalancer, NetworkTargetGroup } from '@aws-cdk/aws-elasticloadbalancingv2'; +import { INetworkLoadBalancer, NetworkListener, NetworkLoadBalancer, NetworkTargetGroup } from '@aws-cdk/aws-elasticloadbalancingv2'; import { IRole } from '@aws-cdk/aws-iam'; import { AddressRecordTarget, ARecord, IHostedZone } from '@aws-cdk/aws-route53'; import { LoadBalancerTarget } from '@aws-cdk/aws-route53-targets'; @@ -102,7 +102,7 @@ export interface NetworkLoadBalancedServiceBaseProps { * * @default - a new load balancer will be created. */ - readonly loadBalancer?: NetworkLoadBalancer; + readonly loadBalancer?: INetworkLoadBalancer; /** * Listener port of the network load balancer that will serve traffic to the service. @@ -268,7 +268,7 @@ export abstract class NetworkLoadBalancedServiceBase extends cdk.Construct { internetFacing }; - this.loadBalancer = props.loadBalancer !== undefined ? props.loadBalancer : new NetworkLoadBalancer(this, 'LB', lbProps); + this.loadBalancer = props.loadBalancer !== undefined ? props.loadBalancer as NetworkLoadBalancer : new NetworkLoadBalancer(this, 'LB', lbProps); const listenerPort = props.listenerPort !== undefined ? props.listenerPort : 80; @@ -291,7 +291,9 @@ export abstract class NetworkLoadBalancedServiceBase extends cdk.Construct { }); } - new cdk.CfnOutput(this, 'LoadBalancerDNS', { value: this.loadBalancer.loadBalancerDnsName }); + if (props.loadBalancer === undefined) { + new cdk.CfnOutput(this, 'LoadBalancerDNS', { value: this.loadBalancer.loadBalancerDnsName }); + } } /** diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts index 825c2cd6129f9..9fd21500d3dfd 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts @@ -2,7 +2,7 @@ import { expect, haveResource, haveResourceLike } from '@aws-cdk/assert'; import { Certificate } from '@aws-cdk/aws-certificatemanager'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as ecs from '@aws-cdk/aws-ecs'; -import { ApplicationProtocol } from '@aws-cdk/aws-elasticloadbalancingv2'; +import { ApplicationLoadBalancer, ApplicationProtocol, NetworkLoadBalancer } from '@aws-cdk/aws-elasticloadbalancingv2'; import { PublicHostedZone } from '@aws-cdk/aws-route53'; import * as cloudmap from '@aws-cdk/aws-servicediscovery'; import * as cdk from '@aws-cdk/core'; @@ -785,7 +785,6 @@ export = { test.done(); }, - 'ALBFargate - having *HealthyPercent properties'(test: Test) { // GIVEN const stack = new cdk.Stack(); @@ -901,4 +900,147 @@ export = { test.done(); }, + + 'NetworkLoadbalancedEC2Service accepts previously created load balancer'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'Vpc'); + const cluster = new ecs.Cluster(stack, "Cluster", {vpc, clusterName: "MyCluster" }); + cluster.addCapacity("Capacity", {instanceType: new ec2.InstanceType('t2.micro')}); + const nlb = new NetworkLoadBalancer(stack, 'NLB', { vpc }); + const taskDef = new ecs.Ec2TaskDefinition(stack, 'TaskDef'); + const container = taskDef.addContainer('Container', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 1024, + }); + container.addPortMappings({ containerPort: 80 }); + + // WHEN + new ecsPatterns.NetworkLoadBalancedEc2Service(stack, 'Service', { + cluster, + loadBalancer: nlb, + taskDefinition: taskDef, + }); + + // THEN + expect(stack).to(haveResourceLike('AWS::ECS::Service', { + LaunchType: 'EC2' + })); + test.done(); + }, + + 'NetworkLoadBalancedEC2Service accepts imported load balancer'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const nlbArn = "arn:aws:elasticloadbalancing::000000000000::dummyloadbalancer"; + const vpc = new ec2.Vpc(stack, "Vpc"); + const cluster = new ecs.Cluster(stack, "Cluster", {vpc, clusterName: "MyCluster" }); + cluster.addCapacity("Capacity", {instanceType: new ec2.InstanceType('t2.micro')}); + const nlb = NetworkLoadBalancer.fromNetworkLoadBalancerAttributes(stack, "NLB", { + loadBalancerArn: nlbArn, + loadBalancerVpc: vpc, + }); + const taskDef = new ecs.Ec2TaskDefinition(stack, 'TaskDef'); + const container = taskDef.addContainer('Container', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 1024, + }); + container.addPortMappings({ + containerPort: 80, + }); + + // WHEN + new ecsPatterns.NetworkLoadBalancedEc2Service(stack, "Service", { + cluster, + loadBalancer: nlb, + desiredCount: 1, + taskDefinition: taskDef + }); + + // THEN + expect(stack).to(haveResourceLike('AWS::ECS::Service', { + LaunchType: 'EC2', + LoadBalancers: [{ContainerName: 'Container', ContainerPort: 80}] + })); + expect(stack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::TargetGroup')); + expect(stack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::Listener', { + LoadBalancerArn: nlb.loadBalancerArn, + Port: 80, + })); + test.done(); + }, + + 'ApplicationLoadBalancedEC2Service accepts previously created load balancer'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'Vpc'); + const cluster = new ecs.Cluster(stack, "Cluster", {vpc, clusterName: "MyCluster" }); + cluster.addCapacity("Capacity", {instanceType: new ec2.InstanceType('t2.micro')}); + const sg = new ec2.SecurityGroup(stack, 'SG', { vpc }); + const alb = new ApplicationLoadBalancer(stack, 'NLB', { + vpc, + securityGroup: sg, + }); + const taskDef = new ecs.Ec2TaskDefinition(stack, 'TaskDef'); + const container = taskDef.addContainer('Container', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 1024, + }); + container.addPortMappings({ containerPort: 80 }); + + // WHEN + new ecsPatterns.ApplicationLoadBalancedEc2Service(stack, 'Service', { + cluster, + loadBalancer: alb, + taskDefinition: taskDef, + }); + + // THEN + expect(stack).to(haveResourceLike('AWS::ECS::Service', { + LaunchType: 'EC2' + })); + test.done(); + }, + + 'ApplicationLoadBalancedEC2Service accepts imported load balancer'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const albArn = "arn:aws:elasticloadbalancing::000000000000::dummyloadbalancer"; + const vpc = new ec2.Vpc(stack, "Vpc"); + const cluster = new ecs.Cluster(stack, "Cluster", {vpc, clusterName: "MyCluster" }); + cluster.addCapacity("Capacity", {instanceType: new ec2.InstanceType('t2.micro')}); + const sg = new ec2.SecurityGroup(stack, "SG", { vpc, }); + const alb = ApplicationLoadBalancer.fromApplicationLoadBalancerAttributes(stack, 'ALB', { + loadBalancerArn: albArn, + vpc, + securityGroupId: sg.securityGroupId, + loadBalancerDnsName: "MyName" + }); + const taskDef = new ecs.Ec2TaskDefinition(stack, 'TaskDef'); + const container = taskDef.addContainer('Container', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 1024, + }); + container.addPortMappings({ + containerPort: 80, + }); + // WHEN + new ecsPatterns.ApplicationLoadBalancedEc2Service(stack, "Service", { + cluster, + loadBalancer: alb, + taskDefinition: taskDef, + }); + // THEN + expect(stack).to(haveResourceLike('AWS::ECS::Service', { + LaunchType: 'EC2', + LoadBalancers: [{ContainerName: 'Container', ContainerPort: 80}] + })); + expect(stack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::TargetGroup')); + expect(stack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::Listener', { + LoadBalancerArn: alb.loadBalancerArn, + Port: 80, + })); + + test.done(); + }, }; diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts index 8cc4d958a80f6..085a0c540e2a3 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts @@ -1,7 +1,7 @@ import { expect, haveResource, haveResourceLike, SynthUtils } from '@aws-cdk/assert'; import * as ec2 from '@aws-cdk/aws-ec2'; import * as ecs from '@aws-cdk/aws-ecs'; -import { ApplicationProtocol } from '@aws-cdk/aws-elasticloadbalancingv2'; +import { ApplicationLoadBalancer, ApplicationProtocol, NetworkLoadBalancer } from '@aws-cdk/aws-elasticloadbalancingv2'; import * as iam from '@aws-cdk/aws-iam'; import * as cdk from '@aws-cdk/core'; import { Test } from 'nodeunit'; @@ -413,4 +413,151 @@ export = { test.done(); }, -}; + 'passing in existing network load balancer to NLB Fargate Service'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'VPC'); + const nlb = new NetworkLoadBalancer(stack, 'NLB', { vpc }); + + // WHEN + new ecsPatterns.NetworkLoadBalancedFargateService(stack, "Service", { + vpc, + loadBalancer: nlb, + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + }, + }); + + // THEN + expect(stack).to(haveResourceLike('AWS::ECS::Service', { + LaunchType: "FARGATE", + })); + test.done(); + }, + + 'passing in imported network load balancer and resources to NLB Fargate service'(test: Test) { + // GIVEN + const stack1 = new cdk.Stack(); + const vpc1 = new ec2.Vpc(stack1, 'VPC'); + const cluster1 = new ecs.Cluster(stack1, 'Cluster', { vpc: vpc1 }); + const nlbArn = "arn:aws:elasticloadbalancing::000000000000::dummyloadbalancer"; + const stack2 = new cdk.Stack(stack1, 'Stack2'); + const cluster2 = ecs.Cluster.fromClusterAttributes(stack2, 'ImportedCluster', { + vpc: vpc1, + securityGroups: cluster1.connections.securityGroups, + clusterName: 'cluster-name' + }); + + // WHEN + const nlb2 = NetworkLoadBalancer.fromNetworkLoadBalancerAttributes(stack2, "ImportedNLB", { + loadBalancerArn: nlbArn, + loadBalancerVpc: vpc1, + }); + const taskDef = new ecs.FargateTaskDefinition(stack2, 'TaskDef', { + cpu: 1024, + memoryLimitMiB: 1024, + }); + const container = taskDef.addContainer('myContainer', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 1024 + }); + container.addPortMappings({ + containerPort: 80, + }); + + new ecsPatterns.NetworkLoadBalancedFargateService(stack2, 'FargateNLBService', { + cluster: cluster2, + loadBalancer: nlb2, + desiredCount: 1, + taskDefinition: taskDef, + }); + + // THEN + expect(stack2).to(haveResourceLike('AWS::ECS::Service', { + LaunchType: "FARGATE", + LoadBalancers: [{ContainerName: 'myContainer', ContainerPort: 80}] + })); + expect(stack2).to(haveResourceLike('AWS::ElasticLoadBalancingV2::TargetGroup')); + expect(stack2).to(haveResourceLike('AWS::ElasticLoadBalancingV2::Listener', { + LoadBalancerArn: nlb2.loadBalancerArn, + Port: 80, + })); + + test.done(); + }, + + 'passing in previously created application load balancer to ALB Fargate Service'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, "Vpc"); + const cluster = new ecs.Cluster(stack, "Cluster", { vpc, clusterName: "MyCluster" }); + const sg = new ec2.SecurityGroup(stack, "SecurityGroup", { vpc }); + cluster.connections.addSecurityGroup(sg); + const alb = new ApplicationLoadBalancer(stack, "ALB", { vpc, securityGroup: sg }); + + // WHEN + new ecsPatterns.ApplicationLoadBalancedFargateService(stack, "Service", { + cluster, + loadBalancer: alb, + taskImageOptions: { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + } + }); + + // THEN + expect(stack).to(haveResourceLike('AWS::ECS::Service', { + LaunchType: 'FARGATE', + })); + test.done(); + }, + + 'passing in imported application load balancer and resources to ALB Fargate Service'(test: Test) { + // GIVEN + const stack1 = new cdk.Stack(); + const albArn = "arn:aws:elasticloadbalancing::000000000000::dummyloadbalancer"; + const vpc = new ec2.Vpc(stack1, "Vpc"); + const cluster = new ecs.Cluster(stack1, "Cluster", { vpc, clusterName: "MyClusterName", }); + const sg = new ec2.SecurityGroup(stack1, "SecurityGroup", { vpc }); + cluster.connections.addSecurityGroup(sg); + const alb = ApplicationLoadBalancer.fromApplicationLoadBalancerAttributes(stack1, "ALB", { + loadBalancerArn: albArn, + vpc, + securityGroupId: sg.securityGroupId, + loadBalancerDnsName: "MyDnsName" + }); + + // WHEN + const taskDef = new ecs.FargateTaskDefinition(stack1, 'TaskDef', { + cpu: 1024, + memoryLimitMiB: 1024, + }); + const container = taskDef.addContainer('Container', { + image: ecs.ContainerImage.fromRegistry('amazon/amazon-ecs-sample'), + memoryLimitMiB: 1024, + }); + container.addPortMappings({ + containerPort: 80, + }); + + new ecsPatterns.ApplicationLoadBalancedFargateService(stack1, 'FargateALBService', { + cluster, + loadBalancer: alb, + desiredCount: 1, + taskDefinition: taskDef, + }); + + // THEN + expect(stack1).to(haveResourceLike('AWS::ECS::Service', { + LaunchType: "FARGATE", + LoadBalancers: [{ContainerName: 'Container', ContainerPort: 80}] + })); + expect(stack1).to(haveResourceLike('AWS::ElasticLoadBalancingV2::TargetGroup')); + expect(stack1).to(haveResourceLike('AWS::ElasticLoadBalancingV2::Listener', { + LoadBalancerArn: alb.loadBalancerArn, + Port: 80, + })); + + test.done(); + }, + +}; \ No newline at end of file diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts index fb16a744e096e..6406ebfbabefa 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-listener.ts @@ -234,7 +234,7 @@ export class ApplicationListener extends BaseListener implements IApplicationLis public addTargets(id: string, props: AddApplicationTargetsProps): ApplicationTargetGroup { if (!this.loadBalancer.vpc) { // tslint:disable-next-line:max-line-length - throw new Error('Can only call addTargets() when using a constructed Load Balancer; construct a new TargetGroup and use addTargetGroup'); + throw new Error('Can only call addTargets() when using a constructed Load Balancer or an imported Load Balancer with specified vpc; construct a new TargetGroup and use addTargetGroup'); } const group = new ApplicationTargetGroup(this, id + 'Group', { diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts index f161a6bd816ca..b1d5e9a018046 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts @@ -525,6 +525,15 @@ export interface ApplicationLoadBalancerAttributes { * @default true */ readonly securityGroupAllowsAllOutbound?: boolean; + + /** + * The VPC this load balancer has been created in, if available + * + * @default - If the Load Balancer was imported and a VPC was not specified, + * the VPC is not available. + */ + readonly vpc?: ec2.IVpc; + } // https://docs.aws.amazon.com/elasticloadbalancing/latest/application/load-balancer-access-logs.html#access-logging-bucket-permissions @@ -571,13 +580,13 @@ class ImportedApplicationLoadBalancer extends Resource implements IApplicationLo /** * VPC of the load balancer * - * Always undefined. + * Undefined if optional vpc is not specified. */ public readonly vpc?: ec2.IVpc; constructor(scope: Construct, id: string, private readonly props: ApplicationLoadBalancerAttributes) { super(scope, id); - + this.vpc = props.vpc; this.loadBalancerArn = props.loadBalancerArn; this.connections = new ec2.Connections({ securityGroups: [ec2.SecurityGroup.fromSecurityGroupId(this, 'SecurityGroup', props.securityGroupId, { diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts index 2aa71dd644749..8f4168ef7ccc5 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-listener.ts @@ -137,7 +137,7 @@ export class NetworkListener extends BaseListener implements INetworkListener { public addTargets(id: string, props: AddNetworkTargetsProps): NetworkTargetGroup { if (!this.loadBalancer.vpc) { // tslint:disable-next-line:max-line-length - throw new Error('Can only call addTargets() when using a constructed Load Balancer; construct a new TargetGroup and use addTargetGroup'); + throw new Error('Can only call addTargets() when using a constructed Load Balancer or imported Load Balancer with specified VPC; construct a new TargetGroup and use addTargetGroup'); } const group = new NetworkTargetGroup(this, id + 'Group', { diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts index 1f4b29ec699b2..9c9266f71411a 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts @@ -38,6 +38,14 @@ export interface NetworkLoadBalancerAttributes { * @default - When not provided, LB cannot be used as Route53 Alias target. */ readonly loadBalancerDnsName?: string; + + /** + * The optional VPC to associate with the imported load balancer. + * + * @default - When not provided, imported load balancers cannot be used + * in ecs-patterns. + */ + readonly loadBalancerVpc?: ec2.IVpc; } /** @@ -49,7 +57,7 @@ export class NetworkLoadBalancer extends BaseLoadBalancer implements INetworkLoa public static fromNetworkLoadBalancerAttributes(scope: Construct, id: string, attrs: NetworkLoadBalancerAttributes): INetworkLoadBalancer { class Import extends Resource implements INetworkLoadBalancer { public readonly loadBalancerArn = attrs.loadBalancerArn; - public readonly vpc?: ec2.IVpc = undefined; + public readonly vpc?: ec2.IVpc = attrs.loadBalancerVpc; public addListener(lid: string, props: BaseNetworkListenerProps): NetworkListener { return new NetworkListener(this, lid, { loadBalancer: this, diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-load-balancer.ts index d05a44bfb7f94..5878534a12a18 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-load-balancer.ts @@ -109,12 +109,9 @@ export abstract class BaseLoadBalancer extends Resource { public readonly loadBalancerSecurityGroups: string[]; /** - * The VPC this load balancer has been created in, if available - * - * If the Load Balancer was imported, the VPC is not available. + * the vpc to create the load balancer inside */ - public readonly vpc?: ec2.IVpc; - + public readonly vpc: ec2.IVpc; /** * Attributes set on this load balancer */ diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/test.load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/test.load-balancer.ts index 0d698c346deaa..fd1629deea74f 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/test.load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/test.load-balancer.ts @@ -268,4 +268,47 @@ export = { })); test.done(); }, + + 'imported load balancer with no vpc throws error when calling addTargets'(test: Test) { + // GIVEN + const stack = new Stack(); + const vpc = new ec2.Vpc(stack, 'Vpc'); + const albArn = 'myArn'; + const sg = new ec2.SecurityGroup(stack, "sg", { + vpc, + securityGroupName: 'mySg', + }); + const alb = elbv2.ApplicationLoadBalancer.fromApplicationLoadBalancerAttributes(stack, 'ALB', { + loadBalancerArn: albArn, + securityGroupId: sg.securityGroupId, + }); + + // WHEN + const listener = alb.addListener('Listener', { port: 80 }); + test.throws(() => listener.addTargets('Targets', {port: 8080})); + + test.done(); + }, + + 'imported load balancer with vpc does not throw error when calling addTargets'(test: Test) { + // GIVEN + const stack = new Stack(); + const vpc = new ec2.Vpc(stack, 'Vpc'); + const albArn = 'MyArn'; + const sg = new ec2.SecurityGroup(stack, 'sg', { + vpc, + securityGroupName: 'mySg', + }); + const alb = elbv2.ApplicationLoadBalancer.fromApplicationLoadBalancerAttributes(stack, 'ALB', { + loadBalancerArn: albArn, + securityGroupId: sg.securityGroupId, + vpc, + }); + + // WHEN + const listener = alb.addListener('Listener', { port: 80 }); + test.doesNotThrow(() => listener.addTargets('Targets', {port: 8080})); + + test.done(); + }, }; diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/nlb/test.load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/nlb/test.load-balancer.ts index 1977dd8425ce5..532459e080195 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/nlb/test.load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/nlb/test.load-balancer.ts @@ -90,6 +90,35 @@ export = { Name: 'myLoadBalancer' })); test.done(); - } + }, + 'imported network load balancer with no vpc specified throws error when calling addTargets'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const nlbArn = "arn:aws:elasticloadbalancing::000000000000::dummyloadbalancer"; + const nlb = elbv2.NetworkLoadBalancer.fromNetworkLoadBalancerAttributes(stack, 'NLB', { + loadBalancerArn: nlbArn, + }); + // WHEN + const listener = nlb.addListener('Listener', {port: 80}); + test.throws(() => listener.addTargets('targetgroup', {port: 8080})); + + test.done(); + }, + + 'imported network load balancer with vpc does not throw error when calling addTargets'(test: Test) { + // GIVEN + const stack = new cdk.Stack(); + const vpc = new ec2.Vpc(stack, 'Vpc'); + const nlbArn = "arn:aws:elasticloadbalancing::000000000000::dummyloadbalancer"; + const nlb = elbv2.NetworkLoadBalancer.fromNetworkLoadBalancerAttributes(stack, 'NLB', { + loadBalancerArn: nlbArn, + loadBalancerVpc: vpc, + }); + // WHEN + const listener = nlb.addListener('Listener', {port: 80}); + test.doesNotThrow(() => listener.addTargets('targetgroup', {port: 8080})); + + test.done(); + } }; From 1aeea917073b36bc2adcae3a89210a9cfef405c8 Mon Sep 17 00:00:00 2001 From: Austin Ely Date: Thu, 19 Dec 2019 16:29:08 -0800 Subject: [PATCH 2/6] fix failing tests --- .../aws-elasticloadbalancingv2/test/alb/test.load-balancer.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/test.load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/test.load-balancer.ts index fd1629deea74f..fb139a0d3fa55 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/test.load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/alb/test.load-balancer.ts @@ -271,7 +271,7 @@ export = { 'imported load balancer with no vpc throws error when calling addTargets'(test: Test) { // GIVEN - const stack = new Stack(); + const stack = new cdk.Stack(); const vpc = new ec2.Vpc(stack, 'Vpc'); const albArn = 'myArn'; const sg = new ec2.SecurityGroup(stack, "sg", { @@ -292,7 +292,7 @@ export = { 'imported load balancer with vpc does not throw error when calling addTargets'(test: Test) { // GIVEN - const stack = new Stack(); + const stack = new cdk.Stack(); const vpc = new ec2.Vpc(stack, 'Vpc'); const albArn = 'MyArn'; const sg = new ec2.SecurityGroup(stack, 'sg', { From 08dcda34586c28e81732b1bdb7997187793ec96a Mon Sep 17 00:00:00 2001 From: Austin Ely Date: Thu, 19 Dec 2019 16:51:24 -0800 Subject: [PATCH 3/6] Check load balancer resources in unit tests involving previously created lbs --- packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts | 6 ++++++ .../test/fargate/test.load-balanced-fargate-service.ts | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts index 9fd21500d3dfd..5f3baa444b9c7 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts @@ -926,6 +926,9 @@ export = { expect(stack).to(haveResourceLike('AWS::ECS::Service', { LaunchType: 'EC2' })); + expect(stack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::LoadBalancer', { + Type: 'network', + })); test.done(); }, @@ -999,6 +1002,9 @@ export = { expect(stack).to(haveResourceLike('AWS::ECS::Service', { LaunchType: 'EC2' })); + expect(stack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::LoadBalancer', { + Type: 'application' + })); test.done(); }, diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts index 085a0c540e2a3..450cfbf998856 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts @@ -432,6 +432,9 @@ export = { expect(stack).to(haveResourceLike('AWS::ECS::Service', { LaunchType: "FARGATE", })); + expect(stack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::LoadBalancer', { + Type: 'network' + })); test.done(); }, @@ -508,6 +511,9 @@ export = { expect(stack).to(haveResourceLike('AWS::ECS::Service', { LaunchType: 'FARGATE', })); + expect(stack).to(haveResourceLike('AWS::ElasticLoadBalancingV2::LoadBalancer', { + Type: 'application' + })); test.done(); }, From 16d8764b86741e98913356b5d07d04db731acec1 Mon Sep 17 00:00:00 2001 From: bvtujo Date: Tue, 28 Jan 2020 14:14:46 -0800 Subject: [PATCH 4/6] Address feedback on comments re: docstrings --- .../lib/base/application-load-balanced-service-base.ts | 2 ++ .../lib/base/network-load-balanced-service-base.ts | 2 ++ .../lib/alb/application-load-balancer.ts | 4 +++- .../lib/nlb/network-load-balancer.ts | 6 +++--- .../lib/shared/base-load-balancer.ts | 2 +- 5 files changed, 11 insertions(+), 5 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts index 2ea9937ec467c..5cf726b2a6f1e 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts @@ -120,6 +120,8 @@ export interface ApplicationLoadBalancedServiceBaseProps { /** * The application load balancer that will serve traffic to the service. + * The VPC attribute of an imported load balancer must be specified in order + * to be used to create a new service with this pattern. * * [disable-awslint:ref-via-interface] * diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts index 58b12368ed8a0..e24f0ae7c0973 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts @@ -97,6 +97,8 @@ export interface NetworkLoadBalancedServiceBaseProps { /** * The network load balancer that will serve traffic to the service. + * If the load balancer has been imported, the vpc attribute must be specified + * in the call to fromNetworkLoadBalancerAttributes(). * * [disable-awslint:ref-via-interface] * diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts index 6d36700bcaf65..41181d05b373a 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts @@ -482,7 +482,9 @@ export interface IApplicationLoadBalancer extends ILoadBalancerV2, ec2.IConnecta readonly loadBalancerArn: string; /** - * The VPC this load balancer has been created in (if available) + * The VPC this load balancer has been created in (if available). + * If this interface is the result of an import call to fromApplicationLoadBalancerAttributes, + * the vpc attribute will be undefined unles specified in the optional properties of that method. */ readonly vpc?: ec2.IVpc; diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts index eabae5fab4b3d..a161bca92490b 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts @@ -40,10 +40,10 @@ export interface NetworkLoadBalancerAttributes { readonly loadBalancerDnsName?: string; /** - * The optional VPC to associate with the imported load balancer. + * The VPC to associate with the imported load balancer. * - * @default - When not provided, imported load balancers cannot be used - * in ecs-patterns. + * @default - When not provided, listeners cannot be created on imported load + * balancers. */ readonly loadBalancerVpc?: ec2.IVpc; } diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-load-balancer.ts index 2a1ac043bd0eb..515bd04f5ba44 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/shared/base-load-balancer.ts @@ -111,7 +111,7 @@ export abstract class BaseLoadBalancer extends Resource { public readonly loadBalancerSecurityGroups: string[]; /** - * the vpc to create the load balancer inside + * The VPC this load balancer has been created in. */ public readonly vpc: ec2.IVpc; /** From 8c6fec5fa59270ecccb5dee85161ee3188f720d6 Mon Sep 17 00:00:00 2001 From: bvtujo Date: Tue, 4 Feb 2020 16:40:24 -0800 Subject: [PATCH 5/6] Address feedback in comments & resolve typo --- .../lib/base/application-load-balanced-service-base.ts | 4 ++-- .../lib/alb/application-load-balancer.ts | 2 +- .../lib/nlb/network-load-balancer.ts | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts index 5cf726b2a6f1e..3ebcc2e995ad6 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts @@ -120,8 +120,8 @@ export interface ApplicationLoadBalancedServiceBaseProps { /** * The application load balancer that will serve traffic to the service. - * The VPC attribute of an imported load balancer must be specified in order - * to be used to create a new service with this pattern. + * The VPC attribute of a load balancer must be specified for it to be used + * to create a new service with this pattern. * * [disable-awslint:ref-via-interface] * diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts index 41181d05b373a..2e61b6246aa62 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/alb/application-load-balancer.ts @@ -484,7 +484,7 @@ export interface IApplicationLoadBalancer extends ILoadBalancerV2, ec2.IConnecta /** * The VPC this load balancer has been created in (if available). * If this interface is the result of an import call to fromApplicationLoadBalancerAttributes, - * the vpc attribute will be undefined unles specified in the optional properties of that method. + * the vpc attribute will be undefined unless specified in the optional properties of that method. */ readonly vpc?: ec2.IVpc; diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts index a161bca92490b..1de0e742e139e 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts @@ -40,7 +40,7 @@ export interface NetworkLoadBalancerAttributes { readonly loadBalancerDnsName?: string; /** - * The VPC to associate with the imported load balancer. + * The VPC to associate with the load balancer. * * @default - When not provided, listeners cannot be created on imported load * balancers. From 57cd88a049898a223f69badf64752d07a80202f5 Mon Sep 17 00:00:00 2001 From: bvtujo Date: Tue, 11 Feb 2020 16:28:23 -0800 Subject: [PATCH 6/6] Refactor .loadBalancer properties to use getter pattern --- .../application-load-balanced-service-base.ts | 25 +++++++++++++------ .../network-load-balanced-service-base.ts | 19 +++++++++++--- .../aws-ecs-patterns/test/ec2/test.l3s.ts | 2 +- .../test.load-balanced-fargate-service.ts | 2 +- .../lib/nlb/network-load-balancer.ts | 4 +-- .../test/nlb/test.load-balancer.ts | 2 +- 6 files changed, 38 insertions(+), 16 deletions(-) diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts index 3ebcc2e995ad6..68365b43be51e 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/base/application-load-balanced-service-base.ts @@ -255,7 +255,12 @@ export abstract class ApplicationLoadBalancedServiceBase extends cdk.Construct { /** * The Application Load Balancer for the service. */ - public readonly loadBalancer: ApplicationLoadBalancer; + public get loadBalancer(): ApplicationLoadBalancer { + if (!this._applicationLoadBalancer) { + throw new Error('.loadBalancer can only be accessed if the class was constructed with an owned, not imported, load balancer'); + } + return this._applicationLoadBalancer; + } /** * The listener for the service. @@ -277,6 +282,8 @@ export abstract class ApplicationLoadBalancedServiceBase extends cdk.Construct { */ public readonly cluster: ICluster; + private readonly _applicationLoadBalancer?: ApplicationLoadBalancer; + /** * Constructs a new instance of the ApplicationLoadBalancedServiceBase class. */ @@ -300,20 +307,20 @@ export abstract class ApplicationLoadBalancedServiceBase extends cdk.Construct { internetFacing }; - this.loadBalancer = props.loadBalancer !== undefined ? props.loadBalancer as ApplicationLoadBalancer + const loadBalancer = props.loadBalancer !== undefined ? props.loadBalancer : new ApplicationLoadBalancer(this, 'LB', lbProps); if (props.certificate !== undefined && props.protocol !== undefined && props.protocol !== ApplicationProtocol.HTTPS) { throw new Error('The HTTPS protocol must be used when a certificate is given'); } const protocol = props.protocol !== undefined ? props.protocol : - (props.certificate ? ApplicationProtocol.HTTPS : ApplicationProtocol.HTTP); + (props.certificate ? ApplicationProtocol.HTTPS : ApplicationProtocol.HTTP); const targetProps = { port: 80 }; - this.listener = this.loadBalancer.addListener('PublicListener', { + this.listener = loadBalancer.addListener('PublicListener', { protocol, port: props.listenerPort, open: true @@ -338,7 +345,7 @@ export abstract class ApplicationLoadBalancedServiceBase extends cdk.Construct { this.listener.addCertificates('Arns', [ListenerCertificate.fromCertificateManager(this.certificate)]); } - let domainName = this.loadBalancer.loadBalancerDnsName; + let domainName = loadBalancer.loadBalancerDnsName; if (typeof props.domainName !== 'undefined') { if (typeof props.domainZone === 'undefined') { throw new Error('A Route53 hosted domain zone name is required to configure the specified domain name'); @@ -347,13 +354,17 @@ export abstract class ApplicationLoadBalancedServiceBase extends cdk.Construct { const record = new ARecord(this, "DNS", { zone: props.domainZone, recordName: props.domainName, - target: RecordTarget.fromAlias(new LoadBalancerTarget(this.loadBalancer)), + target: RecordTarget.fromAlias(new LoadBalancerTarget(loadBalancer)), }); domainName = record.domainName; } - new cdk.CfnOutput(this, 'LoadBalancerDNS', { value: this.loadBalancer.loadBalancerDnsName }); + if (loadBalancer instanceof ApplicationLoadBalancer) { + this._applicationLoadBalancer = loadBalancer; + } + + new cdk.CfnOutput(this, 'LoadBalancerDNS', { value: loadBalancer.loadBalancerDnsName }); new cdk.CfnOutput(this, 'ServiceURL', { value: protocol.toLowerCase() + '://' + domainName }); } diff --git a/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts b/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts index e24f0ae7c0973..6e5e7a07edc61 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/lib/base/network-load-balanced-service-base.ts @@ -230,7 +230,12 @@ export abstract class NetworkLoadBalancedServiceBase extends cdk.Construct { /** * The Network Load Balancer for the service. */ - public readonly loadBalancer: NetworkLoadBalancer; + public get loadBalancer(): NetworkLoadBalancer { + if (!this._networkLoadBalancer) { + throw new Error(".loadBalancer can only be accessed if the class was constructed with an owned, not imported, load balancer"); + } + return this._networkLoadBalancer; + } /** * The listener for the service. @@ -247,6 +252,7 @@ export abstract class NetworkLoadBalancedServiceBase extends cdk.Construct { */ public readonly cluster: ICluster; + private readonly _networkLoadBalancer?: NetworkLoadBalancer; /** * Constructs a new instance of the NetworkLoadBalancedServiceBase class. */ @@ -270,7 +276,8 @@ export abstract class NetworkLoadBalancedServiceBase extends cdk.Construct { internetFacing }; - this.loadBalancer = props.loadBalancer !== undefined ? props.loadBalancer as NetworkLoadBalancer : new NetworkLoadBalancer(this, 'LB', lbProps); + const loadBalancer = props.loadBalancer !== undefined ? props.loadBalancer : + new NetworkLoadBalancer(this, 'LB', lbProps); const listenerPort = props.listenerPort !== undefined ? props.listenerPort : 80; @@ -278,7 +285,7 @@ export abstract class NetworkLoadBalancedServiceBase extends cdk.Construct { port: 80 }; - this.listener = this.loadBalancer.addListener('PublicListener', { port: listenerPort }); + this.listener = loadBalancer.addListener('PublicListener', { port: listenerPort }); this.targetGroup = this.listener.addTargets('ECS', targetProps); if (typeof props.domainName !== 'undefined') { @@ -289,10 +296,14 @@ export abstract class NetworkLoadBalancedServiceBase extends cdk.Construct { new ARecord(this, "DNS", { zone: props.domainZone, recordName: props.domainName, - target: RecordTarget.fromAlias(new LoadBalancerTarget(this.loadBalancer)), + target: RecordTarget.fromAlias(new LoadBalancerTarget(loadBalancer)), }); } + if (loadBalancer instanceof NetworkLoadBalancer) { + this._networkLoadBalancer = loadBalancer; + } + if (props.loadBalancer === undefined) { new cdk.CfnOutput(this, 'LoadBalancerDNS', { value: this.loadBalancer.loadBalancerDnsName }); } diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts index 5f3baa444b9c7..53b5600fc7234 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/test/ec2/test.l3s.ts @@ -941,7 +941,7 @@ export = { cluster.addCapacity("Capacity", {instanceType: new ec2.InstanceType('t2.micro')}); const nlb = NetworkLoadBalancer.fromNetworkLoadBalancerAttributes(stack, "NLB", { loadBalancerArn: nlbArn, - loadBalancerVpc: vpc, + vpc, }); const taskDef = new ecs.Ec2TaskDefinition(stack, 'TaskDef'); const container = taskDef.addContainer('Container', { diff --git a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts index 6f26c50712f30..72353f74ec427 100644 --- a/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts +++ b/packages/@aws-cdk/aws-ecs-patterns/test/fargate/test.load-balanced-fargate-service.ts @@ -511,7 +511,7 @@ export = { // WHEN const nlb2 = NetworkLoadBalancer.fromNetworkLoadBalancerAttributes(stack2, "ImportedNLB", { loadBalancerArn: nlbArn, - loadBalancerVpc: vpc1, + vpc: vpc1, }); const taskDef = new ecs.FargateTaskDefinition(stack2, 'TaskDef', { cpu: 1024, diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts index 1de0e742e139e..15f626989b36a 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/lib/nlb/network-load-balancer.ts @@ -45,7 +45,7 @@ export interface NetworkLoadBalancerAttributes { * @default - When not provided, listeners cannot be created on imported load * balancers. */ - readonly loadBalancerVpc?: ec2.IVpc; + readonly vpc?: ec2.IVpc; } /** @@ -57,7 +57,7 @@ export class NetworkLoadBalancer extends BaseLoadBalancer implements INetworkLoa public static fromNetworkLoadBalancerAttributes(scope: Construct, id: string, attrs: NetworkLoadBalancerAttributes): INetworkLoadBalancer { class Import extends Resource implements INetworkLoadBalancer { public readonly loadBalancerArn = attrs.loadBalancerArn; - public readonly vpc?: ec2.IVpc = attrs.loadBalancerVpc; + public readonly vpc?: ec2.IVpc = attrs.vpc; public addListener(lid: string, props: BaseNetworkListenerProps): NetworkListener { return new NetworkListener(this, lid, { loadBalancer: this, diff --git a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/nlb/test.load-balancer.ts b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/nlb/test.load-balancer.ts index 8da84eb10e0cb..6b53784f4f074 100644 --- a/packages/@aws-cdk/aws-elasticloadbalancingv2/test/nlb/test.load-balancer.ts +++ b/packages/@aws-cdk/aws-elasticloadbalancingv2/test/nlb/test.load-balancer.ts @@ -216,7 +216,7 @@ export = { const nlbArn = "arn:aws:elasticloadbalancing::000000000000::dummyloadbalancer"; const nlb = elbv2.NetworkLoadBalancer.fromNetworkLoadBalancerAttributes(stack, 'NLB', { loadBalancerArn: nlbArn, - loadBalancerVpc: vpc, + vpc, }); // WHEN const listener = nlb.addListener('Listener', {port: 80});