diff --git a/core/src/main/java/google/registry/export/ExportDropListAction.java b/core/src/main/java/google/registry/export/ExportDropListAction.java index d33ffb535d2..38eaa7d6023 100644 --- a/core/src/main/java/google/registry/export/ExportDropListAction.java +++ b/core/src/main/java/google/registry/export/ExportDropListAction.java @@ -16,6 +16,7 @@ import static com.google.common.base.Verify.verifyNotNull; import static com.google.common.collect.ImmutableSet.toImmutableSet; +import static google.registry.model.tld.Tlds.getTldEntities; import static google.registry.model.tld.Tlds.getTldEntitiesOfType; import static google.registry.persistence.PersistenceModule.TransactionIsolationLevel.TRANSACTION_REPEATABLE_READ; import static google.registry.persistence.transaction.TransactionManagerFactory.replicaTm; @@ -35,6 +36,7 @@ import google.registry.request.auth.Auth; import google.registry.storage.drive.DriveConnection; import google.registry.util.Clock; +import google.registry.util.RegistryEnvironment; import jakarta.inject.Inject; import java.io.IOException; import java.io.StringWriter; @@ -45,7 +47,10 @@ import org.apache.commons.csv.CSVFormat; import org.apache.commons.csv.CSVPrinter; -/** An action that exports the upcoming domain drop list across all open TLDs to Google Drive. */ +/** + * An action that exports the upcoming domain drop list across TLDs with XAP enabled to Google + * Drive. + */ @Action( service = Action.Service.BACKEND, path = "/_dr/task/exportDropList", @@ -89,15 +94,17 @@ public void run() { Instant now = clock.now(); ImmutableSet xapTlds = - getTldEntitiesOfType(TldType.REAL).stream() - .filter(Tld::isInvoicingEnabled) + (RegistryEnvironment.get() == RegistryEnvironment.PRODUCTION + ? getTldEntitiesOfType(TldType.REAL) + : getTldEntities()) + .stream() .filter(tld -> tld.getExpiryAccessPeriodModeAt(now) == ExpiryAccessPeriodMode.ENABLED) .map(Tld::getTldStr) .collect(toImmutableSet()); - logger.atInfo().log("Exporting domain drop list for open TLDs with XAP enabled: %s", xapTlds); + logger.atInfo().log("Exporting domain drop list for TLDs with XAP enabled: %s", xapTlds); if (xapTlds.isEmpty()) { - logger.atInfo().log("No open TLDs found with XAP enabled."); + logger.atInfo().log("No TLDs found with XAP enabled."); exportToDrive(createCsv(ImmutableList.of())); return; } diff --git a/core/src/main/java/google/registry/model/tld/Tlds.java b/core/src/main/java/google/registry/model/tld/Tlds.java index d80fab7a0e4..acaac7326b0 100644 --- a/core/src/main/java/google/registry/model/tld/Tlds.java +++ b/core/src/main/java/google/registry/model/tld/Tlds.java @@ -85,6 +85,11 @@ public static ImmutableSet getTldsOfType(TldType type) { return ImmutableSet.copyOf(filterValues(cache.get(), equalTo(type)).keySet()); } + /** Returns all TLD entities loaded fresh from the database. */ + public static ImmutableSet getTldEntities() { + return Tld.get(cache.get().keySet()); + } + /** Returns the TLD entities themselves of the given type loaded fresh from the database. */ public static ImmutableSet getTldEntitiesOfType(TldType type) { return Tld.get(filterValues(cache.get(), equalTo(type)).keySet()); diff --git a/core/src/test/java/google/registry/export/ExportDropListActionTest.java b/core/src/test/java/google/registry/export/ExportDropListActionTest.java index 8612e5cfed6..d412a03da88 100644 --- a/core/src/test/java/google/registry/export/ExportDropListActionTest.java +++ b/core/src/test/java/google/registry/export/ExportDropListActionTest.java @@ -39,10 +39,13 @@ import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension; import google.registry.storage.drive.DriveConnection; import google.registry.testing.FakeClock; +import google.registry.testing.SystemPropertyExtension; +import google.registry.util.RegistryEnvironment; import java.io.IOException; import java.time.Instant; import java.util.Optional; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.RegisterExtension; import org.mockito.ArgumentCaptor; @@ -59,6 +62,10 @@ class ExportDropListActionTest { final JpaIntegrationTestExtension jpa = new JpaTestExtensions.Builder().withClock(clock).buildIntegrationTestExtension(); + @RegisterExtension + @Order(Integer.MAX_VALUE) + final SystemPropertyExtension systemPropertyExtension = new SystemPropertyExtension(); + @BeforeEach void beforeEach() { createTld("open1"); @@ -80,11 +87,23 @@ void beforeEach() { .build()); createTld("closed"); - persistResource(Tld.get("closed").asBuilder().setInvoicingEnabled(false).build()); + persistResource( + Tld.get("closed") + .asBuilder() + .setInvoicingEnabled(false) + .setExpiryAccessPeriodTransitions( + ImmutableSortedMap.of(START_INSTANT, ExpiryAccessPeriodMode.ENABLED)) + .build()); createTld("testtld"); persistResource( - Tld.get("testtld").asBuilder().setTldType(TldType.TEST).setInvoicingEnabled(true).build()); + Tld.get("testtld") + .asBuilder() + .setTldType(TldType.TEST) + .setInvoicingEnabled(false) + .setExpiryAccessPeriodTransitions( + ImmutableSortedMap.of(START_INSTANT, ExpiryAccessPeriodMode.ENABLED)) + .build()); action = new ExportDropListAction(); action.clock = clock; @@ -104,7 +123,7 @@ private void verifyExportedToDrive(String expectedCsv) throws Exception { } @Test - void test_exportsDropListAcrossOpenTlds_sortedByDomainName() throws Exception { + void test_exportsDropListAcrossTlds_sortedByDomainName() throws Exception { // Active domain with no drop date (END_INSTANT) on open TLD -> excluded persistActiveDomain("active.open1"); @@ -112,9 +131,12 @@ void test_exportsDropListAcrossOpenTlds_sortedByDomainName() throws Exception { persistDeletedDomain("zebra.open1", Instant.parse("2020-02-07T02:02:02Z")); persistDeletedDomain("alpha.open2", Instant.parse("2020-02-04T02:02:02Z")); - // Pending delete domain on non-invoicing (closed) TLD -> excluded + // Pending delete domain on non-invoicing (closed) TLD with XAP enabled -> included persistDeletedDomain("closed.closed", Instant.parse("2020-02-05T02:02:02Z")); + // Pending delete domain on test TLD with XAP enabled in non-PROD -> included + persistDeletedDomain("test.testtld", Instant.parse("2020-02-06T02:02:02Z")); + // Pending delete domain on open TLD with XAP disabled -> excluded createTld("noxap"); persistResource( @@ -126,9 +148,6 @@ void test_exportsDropListAcrossOpenTlds_sortedByDomainName() throws Exception { .build()); persistDeletedDomain("noxap.noxap", Instant.parse("2020-02-05T02:02:02Z")); - // Pending delete domain on test TLD -> excluded - persistDeletedDomain("test.testtld", Instant.parse("2020-02-06T02:02:02Z")); - // Already deleted domain on open TLD -> excluded persistDeletedDomain("deleted.open1", Instant.parse("2020-02-01T02:02:02Z")); @@ -138,10 +157,33 @@ void test_exportsDropListAcrossOpenTlds_sortedByDomainName() throws Exception { """ domain_name,tld,deletion_time alpha.open2,open2,2020-02-04T02:02:02Z + closed.closed,closed,2020-02-05T02:02:02Z + test.testtld,testtld,2020-02-06T02:02:02Z zebra.open1,open1,2020-02-07T02:02:02Z """); } + @Test + void test_exportsDropList_excludesTestTldsInProduction() throws Exception { + RegistryEnvironment.PRODUCTION.setup(systemPropertyExtension); + + // Pending delete domains on open TLD and non-invoicing TLD with XAP enabled -> included + persistDeletedDomain("alpha.open2", Instant.parse("2020-02-04T02:02:02Z")); + persistDeletedDomain("closed.closed", Instant.parse("2020-02-05T02:02:02Z")); + + // Pending delete domain on test TLD with XAP enabled -> excluded in PROD + persistDeletedDomain("test.testtld", Instant.parse("2020-02-06T02:02:02Z")); + + action.run(); + + verifyExportedToDrive( + """ + domain_name,tld,deletion_time + alpha.open2,open2,2020-02-04T02:02:02Z + closed.closed,closed,2020-02-05T02:02:02Z + """); + } + @Test void test_skipsDriveExport_whenDriveFolderIdIsEmpty() { action.driveFolderId = Optional.empty(); @@ -164,7 +206,7 @@ void test_emptyDropList_outputsHeaderOnly() throws Exception { } @Test - void test_noOpenTldsWithXap_outputsHeaderOnly() throws Exception { + void test_noTldsWithXap_outputsHeaderOnly() throws Exception { persistResource( Tld.get("open1") .asBuilder() @@ -177,6 +219,18 @@ void test_noOpenTldsWithXap_outputsHeaderOnly() throws Exception { .setExpiryAccessPeriodTransitions( ImmutableSortedMap.of(START_INSTANT, ExpiryAccessPeriodMode.DISABLED)) .build()); + persistResource( + Tld.get("closed") + .asBuilder() + .setExpiryAccessPeriodTransitions( + ImmutableSortedMap.of(START_INSTANT, ExpiryAccessPeriodMode.DISABLED)) + .build()); + persistResource( + Tld.get("testtld") + .asBuilder() + .setExpiryAccessPeriodTransitions( + ImmutableSortedMap.of(START_INSTANT, ExpiryAccessPeriodMode.DISABLED)) + .build()); persistDeletedDomain("zebra.open1", Instant.parse("2020-02-07T02:02:02Z")); diff --git a/core/src/test/java/google/registry/model/tld/TldsTest.java b/core/src/test/java/google/registry/model/tld/TldsTest.java index f939e8aa063..f75ca9b9b3e 100644 --- a/core/src/test/java/google/registry/model/tld/TldsTest.java +++ b/core/src/test/java/google/registry/model/tld/TldsTest.java @@ -54,6 +54,8 @@ void testGetTlds() { void test_getTldEntities() { initTestTlds(); persistResource(newTld("testtld", "TESTTLD").asBuilder().setTldType(TldType.TEST).build()); + assertThat(Tlds.getTldEntities()) + .containsExactly(Tld.get("foo"), Tld.get("a.b.c"), Tld.get("testtld")); assertThat(Tlds.getTldEntitiesOfType(TldType.REAL)) .containsExactly(Tld.get("foo"), Tld.get("a.b.c")); assertThat(Tlds.getTldEntitiesOfType(TldType.TEST)).containsExactly(Tld.get("testtld"));