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

Add an option to disable IPv6 (don't create the AAAA record in Route 53). #365

Closed
Show file tree
Hide file tree
Changes from all 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
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ custom:
basePath: api
certificateName: '*.foo.com'
createRoute53Record: true
createRoute53IPv6Record: true
endpointType: 'regional'
securityPolicy: tls_1_2
apiType: rest
Expand All @@ -84,6 +85,7 @@ custom:
basePath: api
certificateName: '*.foo.com'
createRoute53Record: true
createRoute53IPv6Record: true
endpointType: 'regional'
securityPolicy: tls_1_2
http:
Expand All @@ -92,6 +94,7 @@ custom:
basePath: api
certificateName: '*.foo.com'
createRoute53Record: true
createRoute53IPv6Record: true
endpointType: 'regional'
securityPolicy: tls_1_2
websocket:
Expand All @@ -100,6 +103,7 @@ custom:
basePath: api
certificateName: '*.foo.com'
createRoute53Record: true
createRoute53IPv6Record: true
endpointType: 'regional'
securityPolicy: tls_1_2
```
Expand All @@ -111,7 +115,8 @@ custom:
| stage | Value of `--stage`, or `provider.stage` (serverless will default to `dev` if unset) | The stage to create the domain name for. This parameter allows you to specify a different stage for the domain name than the stage specified for the serverless deployment. |
| certificateName | Closest match | The name of a specific certificate from Certificate Manager to use with this API. If not specified, the closest match will be used (i.e. for a given domain name `api.example.com`, a certificate for `api.example.com` will take precedence over a `*.example.com` certificate). <br><br> Note: Edge-optimized endpoints require that the certificate be located in `us-east-1` to be used with the CloudFront distribution. |
| certificateArn | `(none)` | The arn of a specific certificate from Certificate Manager to use with this API. |
| createRoute53Record | `true` | Toggles whether or not the plugin will create an A Alias and AAAA Alias records in Route53 mapping the `domainName` to the generated distribution domain name. If false, does not create a record. |
| createRoute53Record | `true` | Toggles whether or not the plugin will create A Alias and AAAA Alias records in Route53 mapping the `domainName` to the generated distribution domain name. If false, does not create a record. |
| createRoute53IPv6Record | `true` | Toggles whether or not the plugin will create an AAAA Alias record in Route53 mapping the `domainName` to the generated distribution domain name. If false, does not create a record. |
| endpointType | edge | Defines the endpoint type, accepts `regional` or `edge`. |
| apiType | rest | Defines the api type, accepts `rest`, `http` or `websocket`. |
| hostedZoneId | | If hostedZoneId is set the route53 record set will be created in the matching zone, otherwise the hosted zone will be figured out from the domainName (hosted zone with matching domain). |
Expand Down
2 changes: 2 additions & 0 deletions src/DomainConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class DomainConfig {
public certificateName: string | undefined;
public certificateArn: string | undefined;
public createRoute53Record: boolean | undefined;
public createRoute53IPv6Record: boolean | undefined;
public endpointType: string | undefined;
public apiType: string | undefined;
public hostedZoneId: string | undefined;
Expand All @@ -34,6 +35,7 @@ class DomainConfig {
this.certificateArn = config.certificateArn;
this.certificateName = config.certificateName;
this.createRoute53Record = config.createRoute53Record;
this.createRoute53IPv6Record = config.createRoute53IPv6Record;
this.hostedZoneId = config.hostedZoneId;
this.hostedZonePrivate = config.hostedZonePrivate;
this.allowPathMatching = config.allowPathMatching;
Expand Down
10 changes: 9 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -471,9 +471,17 @@ class ServerlessCustomDomain {
this.serverless.cli.log(`Skipping ${action === "DELETE" ? "removal" : "creation"} of Route53 record.`);
return;
}

const recordsToCreate = ["A"];
const createRoute53IPv6Record = domain.createRoute53IPv6Record;

if (createRoute53IPv6Record !== false) {
recordsToCreate.push("AAAA");
}

// Set up parameters
const route53HostedZoneId = await this.getRoute53HostedZoneId(domain);
const Changes = ["A", "AAAA"].map((Type) => ({
const Changes = recordsToCreate.map((Type) => ({
Action: action,
ResourceRecordSet: {
AliasTarget: {
Expand Down
1 change: 1 addition & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export interface ServerlessInstance { // tslint:disable-line
certificateName: string | undefined,
certificateArn: string | undefined,
createRoute53Record: boolean | undefined,
createRoute53IPv6Record: boolean | undefined,
endpointType: string | undefined,
apiType: string | undefined,
hostedZoneId: string | undefined,
Expand Down
56 changes: 55 additions & 1 deletion test/unit-tests/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ const constructPlugin = (customDomainOptions) => {
basePath: customDomainOptions.basePath,
certificateArn: customDomainOptions.certificateArn,
certificateName: customDomainOptions.certificateName,
createRoute53IPv6Record: customDomainOptions.createRoute53IPv6Record,
createRoute53Record: customDomainOptions.createRoute53Record,
domainName: customDomainOptions.domainName,
enabled: customDomainOptions.enabled,
Expand Down Expand Up @@ -604,7 +605,7 @@ describe("Custom Domain Plugin", () => {
expect(dc.domainInfo.securityPolicy).to.equal("TLS_1_2");
});

it("Create a new A Alias Record", async () => {
it("Create new A and AAAA Alias Records", async () => {
AWS.mock("Route53", "listHostedZones", (params, callback) => {
callback(null, { HostedZones: [{ Name: "test_domain", Id: "test_host_id", Config: { PrivateZone: false } }] });
});
Expand Down Expand Up @@ -664,6 +665,59 @@ describe("Custom Domain Plugin", () => {
expect(spy).to.have.been.called.with(expectedParams);
});

it("Create new A Alias Record Only", async () => {
AWS.mock("Route53", "listHostedZones", (params, callback) => {
callback(null, { HostedZones: [{ Name: "test_domain", Id: "test_host_id", Config: { PrivateZone: false } }] });
});

AWS.mock("Route53", "changeResourceRecordSets", (params, callback) => {
callback(null, params);
});

const plugin = constructPlugin({
basePath: "test_basepath",
createRoute53IPv6Record: false,
domainName: "test_domain",
});

plugin.route53 = new aws.Route53();

const dc: DomainConfig = new DomainConfig(plugin.serverless.service.custom.customDomain);

dc.domainInfo = new DomainInfo(
{
distributionDomainName: "test_distribution_name",
distributionHostedZoneId: "test_id",
},
);

const spy = chai.spy.on(plugin.route53, "changeResourceRecordSets");

await plugin.changeResourceRecordSet("UPSERT", dc);

const expectedParams = {
ChangeBatch: {
Changes: [
{
Action: "UPSERT",
ResourceRecordSet: {
AliasTarget: {
DNSName: "test_distribution_name",
EvaluateTargetHealth: false,
HostedZoneId: "test_id",
},
Name: "test_domain",
Type: "A",
},
},
],
Comment: "Record created by serverless-domain-manager",
},
HostedZoneId: "est_host_id", // getRoute53HostedZoneId strips first character
};
expect(spy).to.have.been.called.with(expectedParams);
});

it("Do not create a Route53 record", async () => {
const plugin = constructPlugin({
createRoute53Record: false,
Expand Down