diff --git a/java/google/registry/model/registry/Registry.java b/java/google/registry/model/registry/Registry.java index c4560e686..b58309951 100644 --- a/java/google/registry/model/registry/Registry.java +++ b/java/google/registry/model/registry/Registry.java @@ -603,7 +603,7 @@ public class Registry extends ImmutableObject implements Buildable { /** Returns the EAP fee for the registry at the given time. */ public Fee getEapFeeFor(DateTime now) { - ImmutableSortedMap valueMap = eapFeeSchedule.toValueMap(); + ImmutableSortedMap valueMap = getEapFeeScheduleAsMap(); DateTime periodStart = valueMap.floorKey(now); DateTime periodEnd = valueMap.ceilingKey(now); // NOTE: assuming END_OF_TIME would never be reached... @@ -618,6 +618,11 @@ public class Registry extends ImmutableObject implements Buildable { validPeriod.upperEndpoint()); } + @VisibleForTesting + public ImmutableSortedMap getEapFeeScheduleAsMap() { + return eapFeeSchedule.toValueMap(); + } + public String getLordnUsername() { return lordnUsername; } diff --git a/java/google/registry/tools/SetupOteCommand.java b/java/google/registry/tools/SetupOteCommand.java index f01403a72..bfb19e846 100644 --- a/java/google/registry/tools/SetupOteCommand.java +++ b/java/google/registry/tools/SetupOteCommand.java @@ -21,6 +21,7 @@ import static google.registry.util.X509Utils.loadCertificate; import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSortedMap; import com.google.re2j.Pattern; import google.registry.config.RegistryEnvironment; import google.registry.model.registrar.Registrar; @@ -35,6 +36,9 @@ import java.util.Optional; import java.util.Set; import javax.inject.Inject; import javax.inject.Named; +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; +import org.joda.time.DateTime; import org.joda.time.Duration; /** Composite command to set up OT&E TLDs and accounts. */ @@ -52,6 +56,15 @@ final class SetupOteCommand extends ConfirmingCommand implements RemoteApiComman private static final Duration SHORT_REDEMPTION_GRACE_PERIOD = Duration.standardMinutes(10); private static final Duration SHORT_PENDING_DELETE_LENGTH = Duration.standardMinutes(5); + private static final ImmutableSortedMap EAP_FEE_SCHEDULE = + ImmutableSortedMap.of( + new DateTime(0), + Money.of(CurrencyUnit.USD, 0), + DateTime.parse("2018-03-01T00:00:00Z"), + Money.of(CurrencyUnit.USD, 100), + DateTime.parse("2022-03-01T00:00:00Z"), + Money.of(CurrencyUnit.USD, 0)); + private static final String DEFAULT_PREMIUM_LIST = "default_sandbox_list"; @Inject @@ -92,6 +105,13 @@ final class SetupOteCommand extends ConfirmingCommand implements RemoteApiComman description = "premium list to apply to all TLDs") private String premiumList = DEFAULT_PREMIUM_LIST; + // TODO: (b/74079782) remove this flag once OT&E for .app is complete. + @Parameter( + names = {"--eap_only"}, + description = "whether to only create EAP TLD and registrar" + ) + private boolean eapOnly = false; + @Inject StringGenerator passwordGenerator; @@ -107,7 +127,9 @@ final class SetupOteCommand extends ConfirmingCommand implements RemoteApiComman TldState initialTldState, Duration addGracePeriod, Duration redemptionGracePeriod, - Duration pendingDeleteLength) throws Exception { + Duration pendingDeleteLength, + boolean isEarlyAccess) + throws Exception { CreateTldCommand command = new CreateTldCommand(); command.addGracePeriod = addGracePeriod; command.dnsWriters = dnsWriters; @@ -120,6 +142,9 @@ final class SetupOteCommand extends ConfirmingCommand implements RemoteApiComman command.roidSuffix = String.format( "%S%X", tldName.replaceAll("[^a-z0-9]", "").substring(0, 7), roidSuffixCounter++); command.redemptionGracePeriod = redemptionGracePeriod; + if (isEarlyAccess) { + command.eapFeeSchedule = EAP_FEE_SCHEDULE; + } command.run(); } @@ -177,42 +202,77 @@ final class SetupOteCommand extends ConfirmingCommand implements RemoteApiComman protected String prompt() throws Exception { // Each underlying command will confirm its own operation as well, so just provide // a summary of the steps in this command. - return "Creating TLDs:\n" - + " " + registrar + "-sunrise\n" - + " " + registrar + "-landrush\n" - + " " + registrar + "-ga\n" - + "Creating registrars:\n" - + " " + registrar + "-1 (access to TLD " + registrar + "-sunrise)\n" - + " " + registrar + "-2 (access to TLD " + registrar + "-landrush)\n" - + " " + registrar + "-3 (access to TLD " + registrar + "-ga)\n" - + " " + registrar + "-4 (access to TLD " + registrar + "-ga)"; + if (eapOnly) { + return "Creating TLD:\n" + + " " + registrar + "-eap\n" + + "Creating registrar:\n" + + " " + registrar + "-5 (access to TLD " + registrar + "-eap)"; + } else { + return "Creating TLDs:\n" + + " " + registrar + "-sunrise\n" + + " " + registrar + "-landrush\n" + + " " + registrar + "-ga\n" + + " " + registrar + "-eap\n" + + "Creating registrars:\n" + + " " + registrar + "-1 (access to TLD " + registrar + "-sunrise)\n" + + " " + registrar + "-2 (access to TLD " + registrar + "-landrush)\n" + + " " + registrar + "-3 (access to TLD " + registrar + "-ga)\n" + + " " + registrar + "-4 (access to TLD " + registrar + "-ga)\n" + + " " + registrar + "-5 (access to TLD " + registrar + "-eap)"; + } } @Override public String execute() throws Exception { - createTld(registrar + "-sunrise", TldState.SUNRISE, null, null, null); - createTld(registrar + "-landrush", TldState.LANDRUSH, null, null, null); + if (!eapOnly) { + createTld(registrar + "-sunrise", TldState.START_DATE_SUNRISE, null, null, null, false); + createTld(registrar + "-landrush", TldState.LANDRUSH, null, null, null, false); + createTld( + registrar + "-ga", + TldState.GENERAL_AVAILABILITY, + SHORT_ADD_GRACE_PERIOD, + SHORT_REDEMPTION_GRACE_PERIOD, + SHORT_PENDING_DELETE_LENGTH, + false); + } else { + // Increase ROID suffix counter to not collide with existing TLDs. + roidSuffixCounter = roidSuffixCounter + 3; + } createTld( - registrar + "-ga", + registrar + "-eap", TldState.GENERAL_AVAILABILITY, SHORT_ADD_GRACE_PERIOD, SHORT_REDEMPTION_GRACE_PERIOD, - SHORT_PENDING_DELETE_LENGTH); + SHORT_PENDING_DELETE_LENGTH, + true); // Storing names and credentials in a list of tuples for later play-back. List> registrars = new ArrayList<>(); - registrars.add(ImmutableList.of( - registrar + "-1", passwordGenerator.createString(PASSWORD_LENGTH), - registrar + "-sunrise")); - registrars.add(ImmutableList.of( - registrar + "-2", passwordGenerator.createString(PASSWORD_LENGTH), - registrar + "-landrush")); - registrars.add(ImmutableList.of( - registrar + "-3", passwordGenerator.createString(PASSWORD_LENGTH), - registrar + "-ga")); - registrars.add(ImmutableList.of( - registrar + "-4", passwordGenerator.createString(PASSWORD_LENGTH), - registrar + "-ga")); + if (!eapOnly) { + registrars.add( + ImmutableList.of( + registrar + "-1", + passwordGenerator.createString(PASSWORD_LENGTH), + registrar + "-sunrise")); + registrars.add( + ImmutableList.of( + registrar + "-2", + passwordGenerator.createString(PASSWORD_LENGTH), + registrar + "-landrush")); + registrars.add( + ImmutableList.of( + registrar + "-3", + passwordGenerator.createString(PASSWORD_LENGTH), + registrar + "-ga")); + registrars.add( + ImmutableList.of( + registrar + "-4", + passwordGenerator.createString(PASSWORD_LENGTH), + registrar + "-ga")); + } + registrars.add( + ImmutableList.of( + registrar + "-5", passwordGenerator.createString(PASSWORD_LENGTH), registrar + "-eap")); for (List r : registrars) { createRegistrar(r.get(0), r.get(1), r.get(2)); diff --git a/javatests/google/registry/tools/SetupOteCommandTest.java b/javatests/google/registry/tools/SetupOteCommandTest.java index efc1f13eb..ec760abac 100644 --- a/javatests/google/registry/tools/SetupOteCommandTest.java +++ b/javatests/google/registry/tools/SetupOteCommandTest.java @@ -28,12 +28,15 @@ import static org.joda.time.DateTimeZone.UTC; import com.beust.jcommander.ParameterException; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSortedMap; import google.registry.model.registrar.Registrar; import google.registry.model.registry.Registry; import google.registry.model.registry.Registry.TldState; import google.registry.testing.DeterministicStringGenerator; import google.registry.util.CidrAddressBlock; import java.security.cert.CertificateParsingException; +import org.joda.money.CurrencyUnit; +import org.joda.money.Money; import org.joda.time.DateTime; import org.joda.time.Duration; import org.junit.Before; @@ -42,8 +45,13 @@ import org.junit.Test; /** Unit tests for {@link SetupOteCommand}. */ public class SetupOteCommandTest extends CommandTestCase { - ImmutableList passwords = ImmutableList.of( - "abcdefghijklmnop", "qrstuvwxyzabcdef", "ghijklmnopqrstuv", "wxyzabcdefghijkl"); + ImmutableList passwords = + ImmutableList.of( + "abcdefghijklmnop", + "qrstuvwxyzabcdef", + "ghijklmnopqrstuv", + "wxyzabcdefghijkl", + "mnopqrstuvwxyzab"); DeterministicStringGenerator passwordGenerator = new DeterministicStringGenerator("abcdefghijklmnopqrstuvwxyz"); @@ -64,7 +72,8 @@ public class SetupOteCommandTest extends CommandTestCase { String premiumList, Duration addGracePeriodLength, Duration redemptionGracePeriodLength, - Duration pendingDeleteLength) { + Duration pendingDeleteLength, + boolean isEarlyAccess) { Registry registry = Registry.get(tldName); assertThat(registry).isNotNull(); assertThat(registry.getRoidSuffix()).isEqualTo(roidSuffix); @@ -75,6 +84,21 @@ public class SetupOteCommandTest extends CommandTestCase { assertThat(registry.getAddGracePeriodLength()).isEqualTo(addGracePeriodLength); assertThat(registry.getRedemptionGracePeriodLength()).isEqualTo(redemptionGracePeriodLength); assertThat(registry.getPendingDeleteLength()).isEqualTo(pendingDeleteLength); + ImmutableSortedMap eapFeeSchedule = registry.getEapFeeScheduleAsMap(); + if (!isEarlyAccess) { + assertThat(eapFeeSchedule) + .isEqualTo(ImmutableSortedMap.of(new DateTime(0), Money.of(CurrencyUnit.USD, 0))); + } else { + assertThat(eapFeeSchedule) + .isEqualTo( + ImmutableSortedMap.of( + new DateTime(0), + Money.of(CurrencyUnit.USD, 0), + DateTime.parse("2018-03-01T00:00:00Z"), + Money.of(CurrencyUnit.USD, 100), + DateTime.parse("2022-03-01T00:00:00Z"), + Money.of(CurrencyUnit.USD, 0))); + } } /** Verify TLD creation with registry default durations. */ @@ -88,7 +112,8 @@ public class SetupOteCommandTest extends CommandTestCase { premiumList, Registry.DEFAULT_ADD_GRACE_PERIOD, Registry.DEFAULT_REDEMPTION_GRACE_PERIOD, - Registry.DEFAULT_PENDING_DELETE_LENGTH); + Registry.DEFAULT_PENDING_DELETE_LENGTH, + false); } private void verifyRegistrarCreation( @@ -116,7 +141,11 @@ public class SetupOteCommandTest extends CommandTestCase { "--certfile=" + getCertFilename()); verifyTldCreation( - "blobio-sunrise", "BLOBIOS0", TldState.SUNRISE, "VoidDnsWriter", "default_sandbox_list"); + "blobio-sunrise", + "BLOBIOS0", + TldState.START_DATE_SUNRISE, + "VoidDnsWriter", + "default_sandbox_list"); verifyTldCreation( "blobio-landrush", "BLOBIOL1", TldState.LANDRUSH, "VoidDnsWriter", "default_sandbox_list"); verifyTldCreation( @@ -127,7 +156,18 @@ public class SetupOteCommandTest extends CommandTestCase { "default_sandbox_list", Duration.standardMinutes(60), Duration.standardMinutes(10), - Duration.standardMinutes(5)); + Duration.standardMinutes(5), + false); + verifyTldCreation( + "blobio-eap", + "BLOBIOE3", + TldState.GENERAL_AVAILABILITY, + "VoidDnsWriter", + "default_sandbox_list", + Duration.standardMinutes(60), + Duration.standardMinutes(10), + Duration.standardMinutes(5), + true); ImmutableList ipAddress = ImmutableList.of( CidrAddressBlock.create("1.1.1.1")); @@ -136,6 +176,33 @@ public class SetupOteCommandTest extends CommandTestCase { verifyRegistrarCreation("blobio-2", "blobio-landrush", passwords.get(1), ipAddress); verifyRegistrarCreation("blobio-3", "blobio-ga", passwords.get(2), ipAddress); verifyRegistrarCreation("blobio-4", "blobio-ga", passwords.get(3), ipAddress); + verifyRegistrarCreation("blobio-5", "blobio-eap", passwords.get(4), ipAddress); + } + + @Test + public void testSuccess_eapOnly() throws Exception { + runCommandForced( + "--eap_only", + "--ip_whitelist=1.1.1.1", + "--registrar=blobio", + "--dns_writers=VoidDnsWriter", + "--certfile=" + getCertFilename()); + + verifyTldCreation( + "blobio-eap", + "BLOBIOE3", + TldState.GENERAL_AVAILABILITY, + "VoidDnsWriter", + "default_sandbox_list", + Duration.standardMinutes(60), + Duration.standardMinutes(10), + Duration.standardMinutes(5), + true); + + ImmutableList ipAddress = ImmutableList.of( + CidrAddressBlock.create("1.1.1.1")); + + verifyRegistrarCreation("blobio-5", "blobio-eap", passwords.get(0), ipAddress); } @Test @@ -147,7 +214,11 @@ public class SetupOteCommandTest extends CommandTestCase { "--certfile=" + getCertFilename()); verifyTldCreation( - "blobio-sunrise", "BLOBIOS0", TldState.SUNRISE, "FooDnsWriter", "default_sandbox_list"); + "blobio-sunrise", + "BLOBIOS0", + TldState.START_DATE_SUNRISE, + "FooDnsWriter", + "default_sandbox_list"); verifyTldCreation( "blobio-landrush", "BLOBIOL1", TldState.LANDRUSH, "FooDnsWriter", "default_sandbox_list"); verifyTldCreation( @@ -158,7 +229,18 @@ public class SetupOteCommandTest extends CommandTestCase { "default_sandbox_list", Duration.standardMinutes(60), Duration.standardMinutes(10), - Duration.standardMinutes(5)); + Duration.standardMinutes(5), + false); + verifyTldCreation( + "blobio-eap", + "BLOBIOE3", + TldState.GENERAL_AVAILABILITY, + "FooDnsWriter", + "default_sandbox_list", + Duration.standardMinutes(60), + Duration.standardMinutes(10), + Duration.standardMinutes(5), + true); ImmutableList ipAddresses = ImmutableList.of( CidrAddressBlock.create("1.1.1.1"), @@ -168,6 +250,7 @@ public class SetupOteCommandTest extends CommandTestCase { verifyRegistrarCreation("blobio-2", "blobio-landrush", passwords.get(1), ipAddresses); verifyRegistrarCreation("blobio-3", "blobio-ga", passwords.get(2), ipAddresses); verifyRegistrarCreation("blobio-4", "blobio-ga", passwords.get(3), ipAddresses); + verifyRegistrarCreation("blobio-5", "blobio-eap", passwords.get(4), ipAddresses); } @Test @@ -180,7 +263,11 @@ public class SetupOteCommandTest extends CommandTestCase { "--premium_list=alternate_list"); verifyTldCreation( - "blobio-sunrise", "BLOBIOS0", TldState.SUNRISE, "BarDnsWriter", "alternate_list"); + "blobio-sunrise", + "BLOBIOS0", + TldState.START_DATE_SUNRISE, + "BarDnsWriter", + "alternate_list"); verifyTldCreation( "blobio-landrush", "BLOBIOL1", TldState.LANDRUSH, "BarDnsWriter", "alternate_list"); verifyTldCreation( @@ -191,7 +278,18 @@ public class SetupOteCommandTest extends CommandTestCase { "alternate_list", Duration.standardMinutes(60), Duration.standardMinutes(10), - Duration.standardMinutes(5)); + Duration.standardMinutes(5), + false); + verifyTldCreation( + "blobio-eap", + "BLOBIOE3", + TldState.GENERAL_AVAILABILITY, + "BarDnsWriter", + "alternate_list", + Duration.standardMinutes(60), + Duration.standardMinutes(10), + Duration.standardMinutes(5), + true); ImmutableList ipAddress = ImmutableList.of( CidrAddressBlock.create("1.1.1.1")); @@ -200,6 +298,7 @@ public class SetupOteCommandTest extends CommandTestCase { verifyRegistrarCreation("blobio-2", "blobio-landrush", passwords.get(1), ipAddress); verifyRegistrarCreation("blobio-3", "blobio-ga", passwords.get(2), ipAddress); verifyRegistrarCreation("blobio-4", "blobio-ga", passwords.get(3), ipAddress); + verifyRegistrarCreation("blobio-5", "blobio-eap", passwords.get(4), ipAddress); } @Test