Add plural DNS writers field to Registry entity

This is the first step in a multi-step data migration to allow multiple
DNS writers per TLD. The overall process looks like this:

1. Add a plural DNS writers field with backfill (this commit).
2. Deploy it.
3. Run the ResaveEnvironmentEntitiesCommand to populate this new field
   on all entities.
4. Update the code to use the new field everywhere.
5. Deploy it.
6. Delete the now-unreferenced, old deprecated singular value field.

This process is rollback-safe.

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=161253436
This commit is contained in:
mcilwain 2017-07-07 15:24:24 -07:00 committed by Ben McIlwain
parent b39f368ea3
commit 4d5b6845b7
4 changed files with 38 additions and 0 deletions

View file

@ -21,6 +21,7 @@ import static com.google.common.base.Predicates.not;
import static google.registry.config.RegistryConfig.getSingletonCacheRefreshDuration; import static google.registry.config.RegistryConfig.getSingletonCacheRefreshDuration;
import static google.registry.model.common.EntityGroupRoot.getCrossTldKey; import static google.registry.model.common.EntityGroupRoot.getCrossTldKey;
import static google.registry.model.ofy.ObjectifyService.ofy; import static google.registry.model.ofy.ObjectifyService.ofy;
import static google.registry.util.CollectionUtils.isNullOrEmpty;
import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy; import static google.registry.util.CollectionUtils.nullToEmptyImmutableCopy;
import static google.registry.util.DateTimeUtils.END_OF_TIME; import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.START_OF_TIME; import static google.registry.util.DateTimeUtils.START_OF_TIME;
@ -49,6 +50,7 @@ import com.googlecode.objectify.annotation.Embed;
import com.googlecode.objectify.annotation.Entity; import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id; import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Mapify; import com.googlecode.objectify.annotation.Mapify;
import com.googlecode.objectify.annotation.OnLoad;
import com.googlecode.objectify.annotation.OnSave; import com.googlecode.objectify.annotation.OnSave;
import com.googlecode.objectify.annotation.Parent; import com.googlecode.objectify.annotation.Parent;
import google.registry.model.Buildable; import google.registry.model.Buildable;
@ -269,9 +271,30 @@ public class Registry extends ImmutableObject implements Buildable {
* *
* <p>This must be a valid key for the map of DnsWriters injected by <code> * <p>This must be a valid key for the map of DnsWriters injected by <code>
* @Inject Map<String, DnsWriter></code> * @Inject Map<String, DnsWriter></code>
*
* @deprecated by dnsWriters
*/ */
// TODO(b/63385623): Delete this field when the data migration is complete.
@Deprecated
String dnsWriter; String dnsWriter;
/**
* The set of name(s) of the {@code DnsWriter} implementations that this TLD uses.
*
* <p>There must be at least one entry in this set.
*
* <p>All entries of this list must be valid keys for the map of {@code DnsWriter}s injected by
* <code>@Inject Map<String, DnsWriter></code>
*/
Set<String> dnsWriters;
@OnLoad
public void migrateDnsWriters() {
if (isNullOrEmpty(dnsWriters)) {
dnsWriters = ImmutableSet.of(dnsWriter);
}
}
/** /**
* The unicode-aware representation of the TLD associated with this {@link Registry}. * The unicode-aware representation of the TLD associated with this {@link Registry}.
* *
@ -588,10 +611,15 @@ public class Registry extends ImmutableObject implements Buildable {
return pricingEngineClassName; return pricingEngineClassName;
} }
@Deprecated
public String getDnsWriter() { public String getDnsWriter() {
return dnsWriter; return dnsWriter;
} }
public ImmutableSet<String> getDnsWriters() {
return ImmutableSet.copyOf(dnsWriters);
}
public ImmutableSet<String> getAllowedRegistrantContactIds() { public ImmutableSet<String> getAllowedRegistrantContactIds() {
return nullToEmptyImmutableCopy(allowedRegistrantContactIds); return nullToEmptyImmutableCopy(allowedRegistrantContactIds);
} }
@ -676,6 +704,7 @@ public class Registry extends ImmutableObject implements Buildable {
public Builder setDnsWriter(String dnsWriter) { public Builder setDnsWriter(String dnsWriter) {
getInstance().dnsWriter = checkArgumentNotNull(dnsWriter); getInstance().dnsWriter = checkArgumentNotNull(dnsWriter);
getInstance().dnsWriters = ImmutableSet.of(dnsWriter);
return this; return this;
} }
@ -946,6 +975,10 @@ public class Registry extends ImmutableObject implements Buildable {
checkArgumentNotNull( checkArgumentNotNull(
instance.dnsWriter, instance.dnsWriter,
"A DNS writer must be specified. VoidDnsWriter can be used if DNS writing isn't wanted"); "A DNS writer must be specified. VoidDnsWriter can be used if DNS writing isn't wanted");
checkArgument(
instance.dnsWriters != null && !instance.dnsWriters.isEmpty(),
"At least one DNS writer must be specified."
+ " VoidDnsWriter can be used if DNS writing isn't desired");
instance.tldStrId = tldName; instance.tldStrId = tldName;
instance.tldUnicode = Idn.toUnicode(tldName); instance.tldUnicode = Idn.toUnicode(tldName);
return super.build(); return super.build();

View file

@ -700,6 +700,7 @@ class google.registry.model.registry.Registry {
java.util.Set<com.googlecode.objectify.Key<google.registry.model.registry.label.ReservedList>> reservedLists; java.util.Set<com.googlecode.objectify.Key<google.registry.model.registry.label.ReservedList>> reservedLists;
java.util.Set<java.lang.String> allowedFullyQualifiedHostNames; java.util.Set<java.lang.String> allowedFullyQualifiedHostNames;
java.util.Set<java.lang.String> allowedRegistrantContactIds; java.util.Set<java.lang.String> allowedRegistrantContactIds;
java.util.Set<java.lang.String> dnsWriters;
org.joda.money.CurrencyUnit currency; org.joda.money.CurrencyUnit currency;
org.joda.money.Money createBillingCost; org.joda.money.Money createBillingCost;
org.joda.money.Money restoreBillingCost; org.joda.money.Money restoreBillingCost;

View file

@ -68,6 +68,7 @@ public class SetupOteCommandTest extends CommandTestCase<SetupOteCommand> {
assertThat(registry.getRoidSuffix()).isEqualTo(roidSuffix); assertThat(registry.getRoidSuffix()).isEqualTo(roidSuffix);
assertThat(registry.getTldState(DateTime.now(UTC))).isEqualTo(tldState); assertThat(registry.getTldState(DateTime.now(UTC))).isEqualTo(tldState);
assertThat(registry.getDnsWriter()).isEqualTo(dnsWriter); assertThat(registry.getDnsWriter()).isEqualTo(dnsWriter);
assertThat(registry.getDnsWriters()).containsExactly(dnsWriter);
assertThat(registry.getPremiumList()).isNotNull(); assertThat(registry.getPremiumList()).isNotNull();
assertThat(registry.getPremiumList().getName()).isEqualTo(premiumList); assertThat(registry.getPremiumList().getName()).isEqualTo(premiumList);
assertThat(registry.getAddGracePeriodLength()).isEqualTo(addGracePeriodLength); assertThat(registry.getAddGracePeriodLength()).isEqualTo(addGracePeriodLength);

View file

@ -177,8 +177,11 @@ public class UpdateTldCommandTest extends CommandTestCase<UpdateTldCommand> {
@Test @Test
public void testSuccess_dnsWriter() throws Exception { public void testSuccess_dnsWriter() throws Exception {
assertThat(Registry.get("xn--q9jyb4c").getDnsWriter()).isEqualTo("VoidDnsWriter"); assertThat(Registry.get("xn--q9jyb4c").getDnsWriter()).isEqualTo("VoidDnsWriter");
assertThat(Registry.get("xn--q9jyb4c").getDnsWriters()).containsExactly("VoidDnsWriter");
runCommandForced("--dns_writer=FooDnsWriter", "xn--q9jyb4c"); runCommandForced("--dns_writer=FooDnsWriter", "xn--q9jyb4c");
assertThat(Registry.get("xn--q9jyb4c").getDnsWriter()).isEqualTo("FooDnsWriter"); assertThat(Registry.get("xn--q9jyb4c").getDnsWriter()).isEqualTo("FooDnsWriter");
assertThat(Registry.get("xn--q9jyb4c").getDnsWriters()).containsExactly("FooDnsWriter");
} }
@Test @Test