diff --git a/java/google/registry/dns/writer/clouddns/CloudDnsWriter.java b/java/google/registry/dns/writer/clouddns/CloudDnsWriter.java index 766a5df30..3afa3ea92 100644 --- a/java/google/registry/dns/writer/clouddns/CloudDnsWriter.java +++ b/java/google/registry/dns/writer/clouddns/CloudDnsWriter.java @@ -46,6 +46,7 @@ import java.io.IOException; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; @@ -82,8 +83,8 @@ public class CloudDnsWriter extends BaseDnsWriter { private final String projectId; private final String zoneName; private final Dns dnsConnection; - private final ImmutableMap.Builder> - desiredRecordsBuilder = new ImmutableMap.Builder<>(); + private final HashMap> desiredRecords = + new HashMap>(); @Inject CloudDnsWriter( @@ -121,7 +122,7 @@ public class CloudDnsWriter extends BaseDnsWriter { // desiredRecordsBuilder is populated with an empty set to indicate that all existing records // should be deleted. if (!domainResource.isPresent() || !domainResource.get().shouldPublishToDns()) { - desiredRecordsBuilder.put(absoluteDomainName, ImmutableSet.of()); + desiredRecords.put(absoluteDomainName, ImmutableSet.of()); return; } @@ -171,7 +172,7 @@ public class CloudDnsWriter extends BaseDnsWriter { } } - desiredRecordsBuilder.put(absoluteDomainName, domainRecords.build()); + desiredRecords.put(absoluteDomainName, domainRecords.build()); logger.finefmt( "Will write %s records for domain %s", domainRecords.build().size(), absoluteDomainName); } @@ -189,7 +190,7 @@ public class CloudDnsWriter extends BaseDnsWriter { // Return early if the host is deleted. if (!host.isPresent()) { - desiredRecordsBuilder.put(absoluteHostName, ImmutableSet.of()); + desiredRecords.put(absoluteHostName, ImmutableSet.of()); return; } @@ -227,7 +228,7 @@ public class CloudDnsWriter extends BaseDnsWriter { .setRrdatas(ImmutableList.copyOf(aaaaRrData))); } - desiredRecordsBuilder.put(absoluteHostName, domainRecords.build()); + desiredRecords.put(absoluteHostName, domainRecords.build()); } /** @@ -273,7 +274,7 @@ public class CloudDnsWriter extends BaseDnsWriter { @Override protected void commitUnchecked() { retrier.callWithRetry( - getMutateZoneCallback(desiredRecordsBuilder.build()), ZoneStateException.class); + getMutateZoneCallback(ImmutableMap.copyOf(desiredRecords)), ZoneStateException.class); logger.info("Wrote to Cloud DNS"); } diff --git a/javatests/google/registry/dns/writer/clouddns/CloudDnsWriterTest.java b/javatests/google/registry/dns/writer/clouddns/CloudDnsWriterTest.java index 57f1170a1..f1317bbed 100644 --- a/javatests/google/registry/dns/writer/clouddns/CloudDnsWriterTest.java +++ b/javatests/google/registry/dns/writer/clouddns/CloudDnsWriterTest.java @@ -471,4 +471,22 @@ public class CloudDnsWriterTest { verifyZone(ImmutableSet.of()); } + + @Test + public void testDuplicateRecords() throws Exception { + // In publishing DNS records, we can end up publishing information on the same host twice + // (through a domain change and a host change), so this scenario needs to work. + persistResource( + fakeDomain( + "example.tld", + ImmutableSet.of(persistResource(fakeHost("0.ip4.example.tld", IPv4))), + 0)) + .asBuilder() + .addSubordinateHost("ns1.example.tld") + .build(); + writer.publishDomain("example.tld"); + writer.publishHost("0.ip4.example.tld"); + + verifyZone(fakeDomainRecords("example.tld", 1, 0, 0, 0)); + } }