From e1c40e3d038a2ccc053d33695fc60e3867934705 Mon Sep 17 00:00:00 2001 From: Ben McIlwain Date: Tue, 15 Sep 2026 14:40:36 -0400 Subject: [PATCH] Allow test TLDs in drop list export for non-production environments In non-production environments (e.g. sandbox), allow TEST TLDs to be included in the domain drop list export so XAP can be verified with test TLDs. Also remove the isInvoicingEnabled filter globally, as the tld.getExpiryAccessPeriodModeAt(now) check is sufficient. TAG=agy CONV=67020217-639f-40a2-9d7c-54e592c91a53 --- .../registry/export/ExportDropListAction.java | 17 +++-- .../java/google/registry/model/tld/Tlds.java | 5 ++ .../export/ExportDropListActionTest.java | 70 ++++++++++++++++--- .../google/registry/model/tld/TldsTest.java | 2 + 4 files changed, 81 insertions(+), 13 deletions(-) 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"));