Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(route53): support CNAME records #1487

Merged
merged 7 commits into from
Jan 8, 2019
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions packages/@aws-cdk/aws-route53/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## AWS Route53 Constuct Library
## AWS Route53 Construct Library

To add a public hosted zone:

Expand Down Expand Up @@ -34,7 +34,7 @@ To add a TXT record to your zone:
```ts
import route53 = require('@aws-cdk/aws-route53');

new route53.TXTRecord(zone, 'TXTRecord', {
new route53.TxtRecord(zone, 'TXTRecord', {
recordName: '_foo', // If the name ends with a ".", it will be used as-is;
// if it ends with a "." followed by the zone name, a trailing "." will be added automatically;
// otherwise, a ".", the zone name, and a trailing "." will be added automatically.
Expand Down
10 changes: 9 additions & 1 deletion packages/@aws-cdk/aws-route53/lib/hosted-zone-ref.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import cdk = require('@aws-cdk/cdk');
*/
export interface IHostedZone extends cdk.IConstruct {
/**
* ID of this hosted zone
* ID of this hosted zone, such as "Z23ABC4XYZL05B"
*/
readonly hostedZoneId: string;

Expand All @@ -14,6 +14,14 @@ export interface IHostedZone extends cdk.IConstruct {
*/
readonly zoneName: string;

/**
* Returns the set of name servers for the specific hosted zone. For example:
* ns1.example.com.
*
* This attribute will be undefined for private hosted zones or hosted zones imported from another stack.
*/
readonly hostedZoneNameServers?: string[];

/**
* Export the hosted zone
*/
Expand Down
159 changes: 74 additions & 85 deletions packages/@aws-cdk/aws-route53/lib/hosted-zone.ts
Original file line number Diff line number Diff line change
@@ -1,89 +1,125 @@
import ec2 = require('@aws-cdk/aws-ec2');
import cdk = require('@aws-cdk/cdk');
import { HostedZoneImportProps, IHostedZone } from './hosted-zone-ref';
import { CfnHostedZone, HostedZoneNameServers } from './route53.generated';
import { CfnHostedZone } from './route53.generated';
import { validateZoneName } from './util';

/**
* Properties of a new hosted zone
*/
export interface PublicHostedZoneProps {
export interface CommonHostedZoneProps {
/**
* The fully qualified domain name for the hosted zone
* The name of the domain. For resource record types that include a domain
* name, specify a fully qualified domain name.
*/
zoneName: string;

/**
* Any comments that you want to include about the hosted zone.
*
* @default no comment
* @default none
*/
comment?: string;

/**
* The Amazon Resource Name (ARN) for the log group that you want Amazon Route 53 to send query logs to.
*
* @default no DNS query logging
* @default disabled
*/
queryLogsLogGroupArn?: string;
}

export abstract class HostedZone extends cdk.Construct implements IHostedZone {
public static import(scope: cdk.Construct, id: string, props: HostedZoneImportProps): IHostedZone {
return new ImportedHostedZone(scope, id, props);
}

public abstract readonly hostedZoneId: string;
public abstract readonly zoneName: string;

public export(): HostedZoneImportProps {
return {
hostedZoneId: new cdk.Output(this, 'HostedZoneId', { value: this.hostedZoneId }).makeImportValue().toString(),
zoneName: this.zoneName,
};
}
}

/**
* Create a Route53 public hosted zone.
* Properties of a new hosted zone
*/
export class PublicHostedZone extends HostedZone {
export interface HostedZoneProps extends CommonHostedZoneProps {
/**
* Identifier of this hosted zone
* A VPC that you want to associate with this hosted zone. When you specify
* this property, a private hosted zone will be created.
*
* You can associate additional VPCs to this private zone using `addVpc(vpc)`.
*
* @default public (no VPCs associated)
*/
public readonly hostedZoneId: string;
vpcs?: ec2.IVpcNetwork[];
}

export class HostedZone extends cdk.Construct implements IHostedZone {
/**
* Fully qualified domain name for the hosted zone
* Imports a hosted zone from another stack.
*/
public static import(scope: cdk.Construct, id: string, props: HostedZoneImportProps): IHostedZone {
return new ImportedHostedZone(scope, id, props);
}

public readonly hostedZoneId: string;
public readonly zoneName: string;
public readonly hostedZoneNameServers?: string[];

/**
* Nameservers for this public hosted zone
* VPCs to which this hosted zone will be added
*/
public readonly nameServers: HostedZoneNameServers;
protected readonly vpcs = new Array<CfnHostedZone.VPCProperty>();

constructor(scope: cdk.Construct, id: string, props: PublicHostedZoneProps) {
constructor(scope: cdk.Construct, id: string, props: HostedZoneProps) {
super(scope, id);

validateZoneName(props.zoneName);

const hostedZone = new CfnHostedZone(this, 'Resource', {
...determineHostedZoneProps(props)
name: props.zoneName + '.',
hostedZoneConfig: props.comment ? { comment: props.comment } : undefined,
queryLoggingConfig: props.queryLogsLogGroupArn ? { cloudWatchLogsLogGroupArn: props.queryLogsLogGroupArn } : undefined,
vpcs: new cdk.Token(() => this.vpcs.length === 0 ? undefined : this.vpcs)
});

this.hostedZoneId = hostedZone.ref;
this.nameServers = hostedZone.hostedZoneNameServers;
this.hostedZoneNameServers = hostedZone.hostedZoneNameServers.toList();
this.zoneName = props.zoneName;

for (const vpc of props.vpcs || []) {
this.addVpc(vpc);
}
}

public export(): HostedZoneImportProps {
return {
hostedZoneId: new cdk.Output(this, 'HostedZoneId', { value: this.hostedZoneId }).makeImportValue(),
zoneName: this.zoneName,
};
}

/**
* Add another VPC to this private hosted zone.
*
* @param vpc the other VPC to add.
*/
public addVpc(vpc: ec2.IVpcNetwork) {
this.vpcs.push({ vpcId: vpc.vpcId, vpcRegion: new cdk.AwsRegion() });
}
}

// tslint:disable-next-line:no-empty-interface
export interface PublicHostedZoneProps extends CommonHostedZoneProps {

}

/**
* Properties for a private hosted zone.
* Create a Route53 public hosted zone.
*/
export interface PrivateHostedZoneProps extends PublicHostedZoneProps {
export class PublicHostedZone extends HostedZone {
constructor(scope: cdk.Construct, id: string, props: PublicHostedZoneProps) {
super(scope, id, props);
}

public addVpc(_vpc: ec2.IVpcNetwork) {
throw new Error('Cannot associate public hosted zones with a VPC');
}
}

export interface PrivateHostedZoneProps extends CommonHostedZoneProps {
/**
* One VPC that you want to associate with this hosted zone.
* A VPC that you want to associate with this hosted zone.
*
* Private hosted zones must be associated with at least one VPC. You can
* associated additional VPCs using `addVpc(vpc)`.
*/
vpc: ec2.IVpcNetwork;
}
Expand All @@ -95,65 +131,18 @@ export interface PrivateHostedZoneProps extends PublicHostedZoneProps {
* for the VPC you're configuring for private hosted zones.
*/
export class PrivateHostedZone extends HostedZone {
/**
* Identifier of this hosted zone
*/
public readonly hostedZoneId: string;

/**
* Fully qualified domain name for the hosted zone
*/
public readonly zoneName: string;

/**
* VPCs to which this hosted zone will be added
*/
private readonly vpcs: CfnHostedZone.VPCProperty[] = [];

constructor(scope: cdk.Construct, id: string, props: PrivateHostedZoneProps) {
super(scope, id);

validateZoneName(props.zoneName);

const hostedZone = new CfnHostedZone(this, 'Resource', {
vpcs: new cdk.Token(() => this.vpcs ? this.vpcs : undefined),
...determineHostedZoneProps(props)
});

this.hostedZoneId = hostedZone.ref;
this.zoneName = props.zoneName;
super(scope, id, props);

this.addVpc(props.vpc);
}

/**
* Add another VPC to this private hosted zone.
*
* @param vpc the other VPC to add.
*/
public addVpc(vpc: ec2.IVpcNetwork) {
this.vpcs.push(toVpcProperty(vpc));
}
}

function toVpcProperty(vpc: ec2.IVpcNetwork): CfnHostedZone.VPCProperty {
return { vpcId: vpc.vpcId, vpcRegion: new cdk.AwsRegion() };
}

function determineHostedZoneProps(props: PublicHostedZoneProps) {
const name = props.zoneName + '.';
const hostedZoneConfig = props.comment ? { comment: props.comment } : undefined;
const queryLoggingConfig = props.queryLogsLogGroupArn ? { cloudWatchLogsLogGroupArn: props.queryLogsLogGroupArn } : undefined;

return { name, hostedZoneConfig, queryLoggingConfig };
}

/**
* Imported hosted zone
*/
class ImportedHostedZone extends cdk.Construct implements IHostedZone {
public readonly hostedZoneId: string;

public readonly zoneName: string;

constructor(scope: cdk.Construct, name: string, private readonly props: HostedZoneImportProps) {
Expand Down
31 changes: 31 additions & 0 deletions packages/@aws-cdk/aws-route53/lib/records/cname.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Construct } from '@aws-cdk/cdk';
import { IHostedZone } from '../hosted-zone-ref';
import { CfnRecordSet } from '../route53.generated';
import { determineFullyQualifiedDomainName } from './_util';

export interface CnameRecordProps {
zone: IHostedZone;
recordName: string;
Copy link
Contributor

Choose a reason for hiding this comment

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

Docstrings

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done. thanks

recordValue: string;
/** @default 1800 seconds */
ttl?: number;
}

/**
* A DNS CNAME record
*/
export class CnameRecord extends Construct {
constructor(scope: Construct, id: string, props: CnameRecordProps) {
super(scope, id);

const ttl = props.ttl === undefined ? 1800 : props.ttl;

new CfnRecordSet(this, 'Resource', {
hostedZoneId: props.zone.hostedZoneId,
name: determineFullyQualifiedDomainName(props.recordName, props.zone),
type: 'CNAME',
resourceRecords: [ props.recordValue ],
eladb marked this conversation as resolved.
Show resolved Hide resolved
ttl: ttl.toString(),
});
}
}
1 change: 1 addition & 0 deletions packages/@aws-cdk/aws-route53/lib/records/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './alias';
export * from './txt';
export * from './cname';
export * from './zone-delegation';
17 changes: 15 additions & 2 deletions packages/@aws-cdk/aws-route53/lib/records/txt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { IHostedZone } from '../hosted-zone-ref';
import { CfnRecordSet } from '../route53.generated';
import { determineFullyQualifiedDomainName } from './_util';

export interface TXTRecordProps {
export interface TxtRecordProps {
zone: IHostedZone;
recordName: string;
recordValue: string;
Expand All @@ -14,7 +14,7 @@ export interface TXTRecordProps {
/**
* A DNS TXT record
*/
export class TXTRecord extends Construct {
export class TxtRecord extends Construct {
constructor(scope: Construct, id: string, props: TXTRecordProps) {
super(scope, id);

Expand All @@ -31,3 +31,16 @@ export class TXTRecord extends Construct {
});
}
}

// backwards compat.

/**
* @deprecated use `TxtRecordProps`.
*/
// tslint:disable-next-line:no-empty-interface
export interface TXTRecordProps extends TxtRecordProps { }

/**
* @deprecated Use `TxtRecord`.
*/
export class TXTRecord extends TxtRecord { }
6 changes: 0 additions & 6 deletions packages/@aws-cdk/aws-route53/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -73,11 +73,5 @@
},
"engines": {
"node": ">= 8.10.0"
},
"awslint": {
"exclude": [
"resource-attribute:@aws-cdk/aws-route53.IHostedZone.hostedZoneNameServers",
"resource-props:@aws-cdk/aws-route53.HostedZoneProps"
]
}
}
Loading