Skip to content
Merged
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
42 changes: 29 additions & 13 deletions cf-custom-resources/lib/custom-domain.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

const aws = require("aws-sdk");

const changeRecordAction = {
Upsert: "UPSERT",
Delete: "DELETE",
}

// These are used for test purposes only
let defaultResponseURL;
let defaultLogGroup;
Expand Down Expand Up @@ -158,17 +163,28 @@ const writeARecord = async function (
hostedZoneCache.set(domain, hostedZoneId);
}
console.log(`${action} A record into Hosted Zone ${hostedZoneId}`);
const changeBatch = await updateRecords(
route53,
hostedZoneId,
action,
alias,
accessDNS,
accessHostedZone
);
await waitForRecordChange(route53, changeBatch.ChangeInfo.Id);
try {
const changeBatch = await updateRecords(
route53,
hostedZoneId,
action,
alias,
accessDNS,
accessHostedZone
);
await waitForRecordChange(route53, changeBatch.ChangeInfo.Id);
} catch (err) {
if (action === changeRecordAction.Delete && isRecordSetNotFoundErr(err)) {
console.log(`${err.message}; Copilot is ignoring this record.`);
Comment thread
paragbhingre marked this conversation as resolved.
return;
}
throw err;
}
};

// Example error message: "InvalidChangeBatch: [Tried to delete resource record set [name='a.domain.com.', type='A'] but it was not found]"
const isRecordSetNotFoundErr = (err) => err.message.includes("Tried to delete resource record set") && err.message.includes("but it was not found")
Comment thread
efekarakus marked this conversation as resolved.

/**
* Custom domain handler, invoked by Lambda.
*/
Expand Down Expand Up @@ -214,7 +230,7 @@ exports.handler = async function (event, context) {
props.PublicAccessDNS,
props.PublicAccessHostedZone,
aliasTypes,
"UPSERT"
changeRecordAction.Upsert,
);
break;
case "Update":
Expand All @@ -225,7 +241,7 @@ exports.handler = async function (event, context) {
props.PublicAccessDNS,
props.PublicAccessHostedZone,
aliasTypes,
"UPSERT"
changeRecordAction.Upsert,
);
// After upserting new aliases, delete unused ones. For example: previously we have ["foo.com", "bar.com"],
// and now the aliases param is updated to just ["foo.com"] then we'll delete "bar.com".
Expand All @@ -242,7 +258,7 @@ exports.handler = async function (event, context) {
props.PublicAccessDNS,
props.PublicAccessHostedZone,
aliasTypes,
"DELETE"
changeRecordAction.Delete,
);
break;
case "Delete":
Expand All @@ -253,7 +269,7 @@ exports.handler = async function (event, context) {
props.PublicAccessDNS,
props.PublicAccessHostedZone,
aliasTypes,
"DELETE"
changeRecordAction.Delete
);
break;
default:
Expand Down
42 changes: 42 additions & 0 deletions cf-custom-resources/test/custom-domain-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -406,4 +406,46 @@ describe("DNS Validated Certificate Handler", () => {
expect(request.isDone()).toBe(true);
});
});

test("Ignore error if trying to delete an A-record that does not exist", () => {
const changeResourceRecordSetsFake = sinon.fake.rejects(new Error("InvalidChangeBatch: [Tried to delete resource record set [name='v1.foobar.com.', type='A'] but it was not found]"));

const listHostedZonesByNameFake = sinon.fake.resolves({
HostedZones: [
{
Id: `/hostedzone/${testHostedZoneId}`,
},
],
});

AWS.mock(
"Route53",
"changeResourceRecordSets",
changeResourceRecordSetsFake
);
AWS.mock("Route53", "listHostedZonesByName", listHostedZonesByNameFake);

const request = nock(ResponseURL)
.put("/", (body) => {
return body.Status === "SUCCESS";
})
.reply(200);
return LambdaTester(handler.handler)
.event({
RequestType: "Delete",
ResourceProperties: {
AppName: testAppName,
EnvName: testEnvName,
DomainName: testDomainName,
Aliases: testAliases,
Region: "us-east-1",
PublicAccessDNS: testAccessDNS,
PublicAccessHostedZone: testLBHostedZone,
AppDNSRole: testRootDNSRole,
},
})
.expectResolve(() => {
expect(request.isDone()).toBe(true);
Comment thread
paragbhingre marked this conversation as resolved.
});
});
});