Skip to content

Commit

Permalink
feat(aws-route53-targets): add global accelerator target to route53 a…
Browse files Browse the repository at this point in the history
…lias targets (#13407)

Closes #12839 
----

*By submitting this pull request, I confirm that my contribution is made under the terms of the Apache-2.0 license*
  • Loading branch information
luketn authored Mar 5, 2021
1 parent 42f3740 commit 2672a55
Show file tree
Hide file tree
Showing 7 changed files with 199 additions and 0 deletions.
13 changes: 13 additions & 0 deletions packages/@aws-cdk/aws-route53-targets/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,19 @@ This library contains Route53 Alias Record targets for:

For example, if the Amazon-provided DNS for the load balancer is `ALB-xxxxxxx.us-west-2.elb.amazonaws.com`, CDK will create alias target in Route 53 will be `dualstack.ALB-xxxxxxx.us-west-2.elb.amazonaws.com`.

* GlobalAccelerator

```ts
new route53.ARecord(stack, 'AliasRecord', {
zone,
target: route53.RecordTarget.fromAlias(new targets.GlobalAcceleratorTarget(accelerator)),
// or - route53.RecordTarget.fromAlias(new targets.GlobalAcceleratorDomainTarget('xyz.awsglobalaccelerator.com')),
});
```

**Important:** If you use GlobalAcceleratorDomainTarget, passing a string rather than an instance of IAccelerator, ensure that the string is a valid domain name of an existing Global Accelerator instance.
See [the documentation on DNS addressing](https://docs.aws.amazon.com/global-accelerator/latest/dg/dns-addressing-custom-domains.dns-addressing.html) with Global Accelerator for more info.

* InterfaceVpcEndpoints

**Important:** Based on the CFN docs for VPCEndpoints - [see here](attrDnsEntries) - the attributes returned for DnsEntries in CloudFormation is a combination of the hosted zone ID and the DNS name. The entries are ordered as follows: regional public DNS, zonal public DNS, private DNS, and wildcard DNS. This order is not enforced for AWS Marketplace services, and therefore this CDK construct is ONLY guaranteed to work with non-marketplace services.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import * as globalaccelerator from '@aws-cdk/aws-globalaccelerator';
import * as route53 from '@aws-cdk/aws-route53';


/**
* Use a Global Accelerator domain name as an alias record target.
*/
export class GlobalAcceleratorDomainTarget implements route53.IAliasRecordTarget {
/**
* The hosted zone Id if using an alias record in Route53.
* This value never changes.
* Ref: https://docs.aws.amazon.com/general/latest/gr/global_accelerator.html
*/
public static readonly GLOBAL_ACCELERATOR_ZONE_ID = 'Z2BJ6XQ5FK7U4H';

/**
* Create an Alias Target for a Global Accelerator domain name.
*/
constructor(private readonly acceleratorDomainName: string) {
}

bind(_record: route53.IRecordSet): route53.AliasRecordTargetConfig {
return {
hostedZoneId: GlobalAcceleratorTarget.GLOBAL_ACCELERATOR_ZONE_ID,
dnsName: this.acceleratorDomainName,
};
}
}

/**
* Use a Global Accelerator instance domain name as an alias record target.
*/
export class GlobalAcceleratorTarget extends GlobalAcceleratorDomainTarget {

/**
* Create an Alias Target for a Global Accelerator instance.
*/
constructor(accelerator: globalaccelerator.IAccelerator) {
super(accelerator.dnsName);
}
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-route53-targets/lib/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ export * from './cloudfront-target';
export * from './load-balancer-target';
export * from './interface-vpc-endpoint-target';
export * from './userpool-domain';
export * from './global-accelerator-target';
2 changes: 2 additions & 0 deletions packages/@aws-cdk/aws-route53-targets/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
"@aws-cdk/aws-elasticloadbalancing": "0.0.0",
"@aws-cdk/aws-elasticloadbalancingv2": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-globalaccelerator": "0.0.0",
"@aws-cdk/aws-route53": "0.0.0",
"@aws-cdk/aws-s3": "0.0.0",
"@aws-cdk/core": "0.0.0",
Expand All @@ -96,6 +97,7 @@
"@aws-cdk/aws-elasticloadbalancing": "0.0.0",
"@aws-cdk/aws-elasticloadbalancingv2": "0.0.0",
"@aws-cdk/aws-iam": "0.0.0",
"@aws-cdk/aws-globalaccelerator": "0.0.0",
"@aws-cdk/aws-route53": "0.0.0",
"@aws-cdk/aws-s3": "0.0.0",
"@aws-cdk/core": "0.0.0",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import '@aws-cdk/assert/jest';
import * as globalaccelerator from '@aws-cdk/aws-globalaccelerator';
import * as route53 from '@aws-cdk/aws-route53';
import { Stack } from '@aws-cdk/core';
import * as targets from '../lib';

test('GlobalAcceleratorTarget exposes a public constant of the zone id', () => {
expect(targets.GlobalAcceleratorTarget.GLOBAL_ACCELERATOR_ZONE_ID).toStrictEqual('Z2BJ6XQ5FK7U4H');
expect(targets.GlobalAcceleratorDomainTarget.GLOBAL_ACCELERATOR_ZONE_ID).toStrictEqual('Z2BJ6XQ5FK7U4H');
});

test('GlobalAcceleratorTarget creates an alias resource with a string domain name', () => {
// GIVEN
const stack = new Stack();
const zone = new route53.PublicHostedZone(stack, 'HostedZone', { zoneName: 'test.public' });

// WHEN
new route53.ARecord(stack, 'GlobalAcceleratorAlias', {
target: route53.RecordTarget.fromAlias(new targets.GlobalAcceleratorDomainTarget('xyz.awsglobalaccelerator.com')),
recordName: 'test',
zone,
});

// THEN
expect(stack).toHaveResource('AWS::Route53::RecordSet', {
AliasTarget: {
DNSName: 'xyz.awsglobalaccelerator.com',
HostedZoneId: 'Z2BJ6XQ5FK7U4H',
},
});
});

test('GlobalAcceleratorTarget creates an alias resource with a Global Accelerator reference domain name', () => {
// GIVEN
const stack = new Stack();
const accelerator = new globalaccelerator.Accelerator(stack, 'Accelerator');
const logicalId = stack.getLogicalId(<globalaccelerator.CfnAccelerator>accelerator.node.defaultChild);
const zone = new route53.PublicHostedZone(stack, 'HostedZone', { zoneName: 'test.public' });

// WHEN
new route53.ARecord(stack, 'GlobalAcceleratorAlias', {
target: route53.RecordTarget.fromAlias(new targets.GlobalAcceleratorTarget(accelerator)),
recordName: 'test',
zone,
});

// THEN
expect(stack).toHaveResource('AWS::Route53::RecordSet', {
AliasTarget: {
DNSName: {
'Fn::GetAtt': [
logicalId,
'DnsName',
],
},
HostedZoneId: 'Z2BJ6XQ5FK7U4H',
},
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"Resources": {
"Accelerator8EB0B6B1": {
"Type": "AWS::GlobalAccelerator::Accelerator",
"Properties": {
"Name": "aws-cdk-globalaccelerator-integ",
"Enabled": true
}
},
"HostedZoneDB99F866": {
"Type": "AWS::Route53::HostedZone",
"Properties": {
"Name": "test.public."
}
},
"LocalGlobalAcceleratorAlias18B4A87A": {
"Type": "AWS::Route53::RecordSet",
"Properties": {
"Name": "test-local.test.public.",
"Type": "A",
"AliasTarget": {
"DNSName": {
"Fn::GetAtt": [
"Accelerator8EB0B6B1",
"DnsName"
]
},
"HostedZoneId": "Z2BJ6XQ5FK7U4H"
},
"Comment": "Alias to the locally created Global Accelerator",
"HostedZoneId": {
"Ref": "HostedZoneDB99F866"
}
}
},
"ExistingGlobalAcceleratorAlias7ACF888C": {
"Type": "AWS::Route53::RecordSet",
"Properties": {
"Name": "test-existing.test.public.",
"Type": "A",
"AliasTarget": {
"DNSName": "someexisting.awsglobalaccelerator.com",
"HostedZoneId": "Z2BJ6XQ5FK7U4H"
},
"Comment": "Alias to the an existing Global Accelerator",
"HostedZoneId": {
"Ref": "HostedZoneDB99F866"
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/usr/bin/env node
import * as globalaccelerator from '@aws-cdk/aws-globalaccelerator';
import * as route53 from '@aws-cdk/aws-route53';
import * as cdk from '@aws-cdk/core';
import * as targets from '../lib';

const app = new cdk.App();
const stack = new cdk.Stack(app, 'aws-cdk-globalaccelerator-integ');

let accelerator = new globalaccelerator.Accelerator(stack, 'Accelerator', {
acceleratorName: `${stack.stackName}`,
enabled: true,
});

const zone = new route53.PublicHostedZone(stack, 'HostedZone', { zoneName: 'test.public' });

new route53.ARecord(stack, 'LocalGlobalAcceleratorAlias', {
comment: 'Alias to the locally created Global Accelerator',
target: route53.RecordTarget.fromAlias(new targets.GlobalAcceleratorTarget(accelerator)),
recordName: 'test-local',
zone,
});

new route53.ARecord(stack, 'ExistingGlobalAcceleratorAlias', {
comment: 'Alias to the an existing Global Accelerator',
target: route53.RecordTarget.fromAlias(new targets.GlobalAcceleratorDomainTarget('someexisting.awsglobalaccelerator.com')),
recordName: 'test-existing',
zone,
});

app.synth();

0 comments on commit 2672a55

Please sign in to comment.