Skip to content

Commit

Permalink
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
mergify[bot] authored Jul 8, 2021
2 parents 7d3eacd + 48dd771 commit 665ba2a
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 7 deletions.
5 changes: 5 additions & 0 deletions packages/@aws-cdk/aws-elasticloadbalancingv2/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,11 @@ Routing traffic from a Load Balancer to a Target involves the following steps:
- Create a Target Group, register the Target into the Target Group
- Add an Action to the Listener which forwards traffic to the Target Group.

A new listener can be added to the Load Balancer by calling `addListener()`.
Listeners that have been added to the load balancer can be listed using the
`listeners` property. Note that the `listeners` property will throw an Error
for imported or looked up Load Balancers.

Various methods on the `Listener` take care of this work for you to a greater
or lesser extent:

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export class ApplicationLoadBalancer extends BaseLoadBalancer implements IApplic

public readonly connections: ec2.Connections;
public readonly ipAddressType?: IpAddressType;
public readonly listeners: ApplicationListener[];

constructor(scope: Construct, id: string, props: ApplicationLoadBalancerProps) {
super(scope, id, props, {
Expand All @@ -95,6 +96,7 @@ export class ApplicationLoadBalancer extends BaseLoadBalancer implements IApplic
allowAllOutbound: false,
})];
this.connections = new ec2.Connections({ securityGroups });
this.listeners = [];

if (props.http2Enabled === false) { this.setAttribute('routing.http2.enabled', 'false'); }
if (props.idleTimeout !== undefined) { this.setAttribute('idle_timeout.timeout_seconds', props.idleTimeout.toSeconds().toString()); }
Expand All @@ -104,10 +106,12 @@ export class ApplicationLoadBalancer extends BaseLoadBalancer implements IApplic
* Add a new listener to this load balancer
*/
public addListener(id: string, props: BaseApplicationListenerProps): ApplicationListener {
return new ApplicationListener(this, id, {
const listener = new ApplicationListener(this, id, {
loadBalancer: this,
...props,
});
this.listeners.push(listener);
return listener;
}

/**
Expand Down Expand Up @@ -487,6 +491,12 @@ export interface IApplicationLoadBalancer extends ILoadBalancerV2, ec2.IConnecta
*/
readonly ipAddressType?: IpAddressType;

/**
* A list of listeners that have been added to the load balancer.
* This list is only valid for owned constructs.
*/
readonly listeners: ApplicationListener[];

/**
* Add a new listener to this load balancer
*/
Expand Down Expand Up @@ -554,6 +564,10 @@ class ImportedApplicationLoadBalancer extends Resource implements IApplicationLo
*/
public readonly loadBalancerArn: string;

public get listeners(): ApplicationListener[] {
throw Error('.listeners can only be accessed if the class was constructed as an owned, not imported, load balancer');
}

/**
* VPC of the load balancer
*
Expand Down Expand Up @@ -603,6 +617,10 @@ class LookedUpApplicationLoadBalancer extends Resource implements IApplicationLo
public readonly connections: ec2.Connections;
public readonly vpc?: ec2.IVpc;

public get listeners(): ApplicationListener[] {
throw Error('.listeners can only be accessed if the class was constructed as an owned, not looked up, load balancer');
}

constructor(scope: Construct, id: string, props: cxapi.LoadBalancerContextResponse) {
super(scope, id, {
environmentFromArn: props.loadBalancerArn,
Expand Down Expand Up @@ -685,4 +703,4 @@ export interface ApplicationLoadBalancerRedirectConfig {
*/
readonly open?: boolean;

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,27 @@ describe('tests', () => {
});
});

test('Can add and list listeners for an owned ApplicationLoadBalancer', () => {
// GIVEN
const stack = new cdk.Stack();
const vpc = new ec2.Vpc(stack, 'Stack');

// WHEN
const loadBalancer = new elbv2.ApplicationLoadBalancer(stack, 'LB', {
vpc,
internetFacing: true,
});

const listener = loadBalancer.addListener('listener', {
protocol: elbv2.ApplicationProtocol.HTTP,
defaultAction: elbv2.ListenerAction.fixedResponse(200),
});

// THEN
expect(stack).toHaveResource('AWS::ElasticLoadBalancingV2::Listener');
expect(loadBalancer.listeners).toContain(listener);
});

testFutureBehavior('Access logging', s3GrantWriteCtx, cdk.App, (app) => {
// GIVEN
const stack = new cdk.Stack(app, undefined, { env: { region: 'us-east-1' } });
Expand Down Expand Up @@ -323,6 +344,30 @@ describe('tests', () => {
expect(() => listener.addTargets('Targets', { port: 8080 })).not.toThrow();
});

test('imported load balancer with vpc can add but not list listeners', () => {
// GIVEN
const stack = new cdk.Stack();
const vpc = new ec2.Vpc(stack, 'Vpc');
const albArn = 'arn:aws:elasticloadbalancing:us-west-2:123456789012:loadbalancer/app/my-load-balancer/50dc6c495c0c9188';
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 });
listener.addTargets('Targets', { port: 8080 });

// THEN
expect(stack).toHaveResource('AWS::ElasticLoadBalancingV2::Listener');
expect(() => alb.listeners).toThrow();
});

test('imported load balancer knows its region', () => {
const stack = new cdk.Stack();

Expand Down Expand Up @@ -385,7 +430,7 @@ describe('tests', () => {
expect(loadBalancer.env.region).toEqual('us-west-2');
});

test('Can add listeners to a looked-up ApplicationLoadBalancer', () => {
test('Can add but not list listeners for a looked-up ApplicationLoadBalancer', () => {
// GIVEN
const app = new cdk.App();
const stack = new cdk.Stack(app, 'stack', {
Expand All @@ -409,6 +454,8 @@ describe('tests', () => {

// THEN
expect(stack).toHaveResource('AWS::ElasticLoadBalancingV2::Listener');
expect(() => loadBalancer.listeners).toThrow();
});

});
});
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ export class PublishAssetsAction extends CoreConstruct implements codepipeline.I
}

private getBuildSpecFileName(): string {
return `buildspec-assets-${this.props.actionName}.yaml`;
return `buildspec-assets-${this.node.path.replace(new RegExp('/', 'g'), '-')}.yaml`;
}

private _onSynth(session: ISynthesisSession): void {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1503,7 +1503,7 @@
]
},
"Source": {
"BuildSpec": "buildspec-assets-FileAsset.yaml",
"BuildSpec": "buildspec-assets-PipelineStack-Pipeline-Assets-FileAsset.yaml",
"Type": "CODEPIPELINE"
},
"EncryptionKey": {
Expand Down
31 changes: 29 additions & 2 deletions packages/@aws-cdk/pipelines/test/pipeline-assets.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -506,12 +506,19 @@ describe('pipeline with VPC', () => {
});

describe('pipeline with single asset publisher', () => {
let otherPipelineStack: Stack;
let otherPipeline: cdkp.CdkPipeline;

beforeEach(() => {
app = new TestApp();
pipelineStack = new Stack(app, 'PipelineStack', { env: PIPELINE_ENV });
pipeline = new TestGitHubNpmPipeline(pipelineStack, 'Cdk', {
singlePublisherPerType: true,
});
otherPipelineStack = new Stack(app, 'OtherPipelineStack', { env: PIPELINE_ENV });
otherPipeline = new TestGitHubNpmPipeline(otherPipelineStack, 'Cdk', {
singlePublisherPerType: true,
});
});

behavior('multiple assets are using the same job in singlePublisherMode', (suite) => {
Expand All @@ -534,15 +541,35 @@ describe('pipeline with single asset publisher', () => {
Image: 'aws/codebuild/standard:5.0',
},
Source: {
BuildSpec: 'buildspec-assets-FileAsset.yaml',
BuildSpec: 'buildspec-assets-PipelineStack-Cdk-Assets-FileAsset.yaml',
},
});
const assembly = SynthUtils.synthesize(pipelineStack, { skipValidation: true }).assembly;
const buildSpec = JSON.parse(fs.readFileSync(path.join(assembly.directory, 'buildspec-assets-FileAsset.yaml')).toString());
const buildSpec = JSON.parse(fs.readFileSync(path.join(assembly.directory, 'buildspec-assets-PipelineStack-Cdk-Assets-FileAsset.yaml')).toString());
expect(buildSpec.phases.build.commands).toContain(`cdk-assets --path "assembly-FileAssetApp/FileAssetAppStackEADD68C5.assets.json" --verbose publish "${FILE_ASSET_SOURCE_HASH}:current_account-current_region"`);
expect(buildSpec.phases.build.commands).toContain(`cdk-assets --path "assembly-FileAssetApp/FileAssetAppStackEADD68C5.assets.json" --verbose publish "${FILE_ASSET_SOURCE_HASH2}:current_account-current_region"`);
});
});

behavior('other pipeline writes to separate assets build spec file', (suite) => {
suite.legacy(() => {
// WHEN
pipeline.addApplicationStage(new TwoFileAssetsApp(app, 'FileAssetApp'));
otherPipeline.addApplicationStage(new TwoFileAssetsApp(app, 'OtherFileAssetApp'));

// THEN
expect(pipelineStack).toHaveResourceLike('AWS::CodeBuild::Project', {
Source: {
BuildSpec: 'buildspec-assets-PipelineStack-Cdk-Assets-FileAsset.yaml',
},
});
expect(otherPipelineStack).toHaveResourceLike('AWS::CodeBuild::Project', {
Source: {
BuildSpec: 'buildspec-assets-OtherPipelineStack-Cdk-Assets-FileAsset.yaml',
},
});
});
});
});

describe('pipeline with Docker credentials', () => {
Expand Down

0 comments on commit 665ba2a

Please sign in to comment.