1
0
mirror of https://github.com/google/nomulus synced 2026-07-10 01:56:49 +00:00

Compare commits

...

9 Commits

Author SHA1 Message Date
gbrodman 5822f53e14 Allow usage of a read-only Postgres replica (#1470)
* Allow usage of a read-only Postgres replica

This adds the Dagger provider code for both the regular and the BEAM
environments, which are similar but not quite the same.

In addition, this demonstrates usage of the replica DB in the
RdePipeline. I tested this on alpha with a modified version of the
RdePipeline that attempts to write some dummy values to the database and
it failed with the expected message that one cannot write to a replica.
2022-01-07 13:21:22 -05:00
Rachel Guan d04b3299aa Replace all existing vkey string to vkey.stringify() (#1430)
* Resolve ResaveEntityAction related conflicts

* Replace string with existing constants

* Remove solved TODOs related to ofy string to new vkey string

* Add a TODO for clean up

* Fix missing annotation
2022-01-07 12:11:15 -05:00
Lai Jiang ceade7f954 Use the service account credential to delete unused versions (#1484) 2022-01-07 11:06:19 -05:00
Rachel Guan 1fcf63facd Use CloudTasksUtils to enqueue in GenerateEscrowDepositCommand (#1465)
* Use CloudTasksUtils to enqueue in GenerateEscrowDepositCommand

* Add CloudTasksUtil to RegistryToolComponent

* Remove header param
2022-01-06 15:36:22 -05:00
sarahcaseybot f87e7eb6e6 Label classes to be deleted after the database migration - Batch 2 (#1477)
* Add some more annotations

* Add some more classes
2022-01-04 12:26:18 -05:00
Ben McIlwain 7a174e3ffa Make not logged in errors take precedence over extension errors (#1483)
* Make not logged in errors take precedence over extension errors

This is the right order to do the checks in, because if the registrar isn't
logged in (or their login failed) then they will have an empty set of declared
extensions, so any attempt to use an extension will throw a "Service
extension(s) must be declared at login" error. This is potentially misleading
because the actual error in this situation is that the registrar isn't logged
in at all.

This also fixes some flows that weren't declared final (but should be), or
methods declared final on final classes, which is superfluous.
2021-12-30 17:23:14 -05:00
Ben McIlwain 2b38ad8a25 Don't throw errors when existing premium list is empty (#1479)
* Don't throw errors when existing premium list is empty

This state is possible to get into when things go wrong and it shouldn't prevent
saving new revisions of the list. Note that it will continue to throw errors if
you attempt to save a new revision that is blank (which is usually a mistake).

See http://b/211774375
2021-12-30 17:22:43 -05:00
Ben McIlwain eefb4c71aa Make premium list saving run as a single transaction (#1480)
* Make premium list saving run as a single transaction

This fixes the bug where the new revision is saved, but then execution gets
halted for some reason (e.g. request timeout) before the entries finish saving,
which leaves the DB in a bad state with a new top revision containing zero
entries, thus making everything standard.
2021-12-30 12:53:39 -05:00
Ben McIlwain 9d3cbd07fd Add pending action extension to server update poll messages (#1478)
* Add pending action extension to server update poll messages

This is necessary for the poll messages to contain the necessary context
explaining what domain name the relevant statuses were being added/removed
to/from.
2021-12-28 15:45:40 -05:00
124 changed files with 552 additions and 208 deletions
@@ -110,7 +110,7 @@ public final class AsyncTaskEnqueuer {
.method(Method.POST)
.header("Host", backendHostname)
.countdownMillis(etaDuration.getMillis())
.param(PARAM_RESOURCE_KEY, entityKey.getOfyKey().getString())
.param(PARAM_RESOURCE_KEY, entityKey.stringify())
.param(PARAM_REQUESTED_TIME, now.toString());
if (whenToResave.size() > 1) {
task.param(PARAM_RESAVE_TIMES, Joiner.on(',').join(whenToResave.tailSet(firstResave, false)));
@@ -131,7 +131,7 @@ public final class AsyncTaskEnqueuer {
TaskOptions task =
TaskOptions.Builder.withMethod(Method.PULL)
.countdownMillis(asyncDeleteDelay.getMillis())
.param(PARAM_RESOURCE_KEY, resourceToDelete.createVKey().getOfyKey().getString())
.param(PARAM_RESOURCE_KEY, resourceToDelete.createVKey().stringify())
.param(PARAM_REQUESTING_CLIENT_ID, requestingRegistrarId)
.param(PARAM_SERVER_TRANSACTION_ID, trid.getServerTransactionId())
.param(PARAM_IS_SUPERUSER, Boolean.toString(isSuperuser))
@@ -148,7 +148,7 @@ public final class AsyncTaskEnqueuer {
addTaskToQueueWithRetry(
asyncDnsRefreshPullQueue,
TaskOptions.Builder.withMethod(Method.PULL)
.param(PARAM_HOST_KEY, hostKey.getOfyKey().getString())
.param(PARAM_HOST_KEY, hostKey.stringify())
.param(PARAM_REQUESTED_TIME, now.toString()));
}
@@ -23,6 +23,7 @@ import google.registry.config.RegistryConfig.ConfigModule;
import google.registry.persistence.PersistenceModule;
import google.registry.persistence.PersistenceModule.BeamBulkQueryJpaTm;
import google.registry.persistence.PersistenceModule.BeamJpaTm;
import google.registry.persistence.PersistenceModule.BeamReadOnlyReplicaJpaTm;
import google.registry.persistence.PersistenceModule.TransactionIsolationLevel;
import google.registry.persistence.transaction.JpaTransactionManager;
import google.registry.privileges.secretmanager.SecretManagerModule;
@@ -59,6 +60,13 @@ public interface RegistryPipelineComponent {
@BeamBulkQueryJpaTm
Lazy<JpaTransactionManager> getBulkQueryJpaTransactionManager();
/**
* A {@link JpaTransactionManager} that uses the Postgres read-only replica if configured (uses
* the standard DB otherwise).
*/
@BeamReadOnlyReplicaJpaTm
Lazy<JpaTransactionManager> getReadOnlyReplicaJpaTransactionManager();
@Component.Builder
interface Builder {
@@ -56,6 +56,10 @@ public class RegistryPipelineWorkerInitializer implements JvmInitializer {
case BULK_QUERY:
transactionManagerLazy = registryPipelineComponent.getBulkQueryJpaTransactionManager();
break;
case READ_ONLY_REPLICA:
transactionManagerLazy =
registryPipelineComponent.getReadOnlyReplicaJpaTransactionManager();
break;
case REGULAR:
default:
transactionManagerLazy = registryPipelineComponent.getJpaTransactionManager();
@@ -392,19 +392,26 @@ public final class RegistryConfig {
@Provides
@Config("cloudSqlJdbcUrl")
public static String providesCloudSqlJdbcUrl(RegistryConfigSettings config) {
public static String provideCloudSqlJdbcUrl(RegistryConfigSettings config) {
return config.cloudSql.jdbcUrl;
}
@Provides
@Config("cloudSqlInstanceConnectionName")
public static String providesCloudSqlInstanceConnectionName(RegistryConfigSettings config) {
public static String provideCloudSqlInstanceConnectionName(RegistryConfigSettings config) {
return config.cloudSql.instanceConnectionName;
}
@Provides
@Config("cloudSqlReplicaInstanceConnectionName")
public static Optional<String> provideCloudSqlReplicaInstanceConnectionName(
RegistryConfigSettings config) {
return Optional.ofNullable(config.cloudSql.replicaInstanceConnectionName);
}
@Provides
@Config("cloudSqlDbInstanceName")
public static String providesCloudSqlDbInstance(RegistryConfigSettings config) {
public static String provideCloudSqlDbInstance(RegistryConfigSettings config) {
// Format of instanceConnectionName: project-id:region:instance-name
int lastColonIndex = config.cloudSql.instanceConnectionName.lastIndexOf(':');
return config.cloudSql.instanceConnectionName.substring(lastColonIndex + 1);
@@ -128,6 +128,7 @@ public class RegistryConfigSettings {
// TODO(05012021): remove username field after it is removed from all yaml files.
public String username;
public String instanceConnectionName;
public String replicaInstanceConnectionName;
}
/** Configuration for Apache Beam (Cloud Dataflow). */
@@ -231,6 +231,7 @@ cloudSql:
jdbcUrl: jdbc:postgresql://localhost
# This name is used by Cloud SQL when connecting to the database.
instanceConnectionName: project-id:region:instance-id
replicaInstanceConnectionName: null
cloudDns:
# Set both properties to null in Production.
@@ -56,9 +56,9 @@ public final class ContactCheckFlow implements Flow {
@Inject ContactCheckFlow() {}
@Override
public final EppResponse run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
public EppResponse run() throws EppException {
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate(); // There are no legal extensions for this flow.
ImmutableList<String> targetIds = ((Check) resourceCommand).getTargetIds();
verifyTargetIdCount(targetIds, maxChecks);
ImmutableSet<String> existingIds =
@@ -70,10 +70,10 @@ public final class ContactCreateFlow implements TransactionalFlow {
@Inject ContactCreateFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
Create command = (Create) resourceCommand;
DateTime now = tm().getTransactionTime();
verifyResourceDoesNotExist(ContactResource.class, targetId, now, registrarId);
@@ -90,10 +90,10 @@ public final class ContactDeleteFlow implements TransactionalFlow {
ContactDeleteFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
checkLinkedDomains(targetId, now, ContactResource.class, DomainBase::getReferencedContacts);
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
@@ -65,10 +65,10 @@ public final class ContactInfoFlow implements Flow {
ContactInfoFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
DateTime now = clock.nowUtc();
extensionManager.validate(); // There are no legal extensions for this flow.
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate(); // There are no legal extensions for this flow.
ContactResource contact = loadAndVerifyExistence(ContactResource.class, targetId, now);
if (!isSuperuser) {
verifyResourceOwnership(registrarId, contact);
@@ -74,14 +74,14 @@ public final class ContactTransferApproveFlow implements TransactionalFlow {
@Inject ContactTransferApproveFlow() {}
/**
* <p>The logic in this flow, which handles client approvals, very closely parallels the logic in
* The logic in this flow, which handles client approvals, very closely parallels the logic in
* {@link ContactResource#cloneProjectedAtTime} which handles implicit server approvals.
*/
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyOptionalAuthInfo(authInfo, existingContact);
@@ -76,8 +76,8 @@ public final class ContactTransferCancelFlow implements TransactionalFlow {
@Override
public final EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyOptionalAuthInfo(authInfo, existingContact);
@@ -63,9 +63,9 @@ public final class ContactTransferQueryFlow implements Flow {
@Inject ContactTransferQueryFlow() {}
@Override
public final EppResponse run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
public EppResponse run() throws EppException {
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate(); // There are no legal extensions for this flow.
ContactResource contact =
loadAndVerifyExistence(ContactResource.class, targetId, clock.nowUtc());
verifyOptionalAuthInfo(authInfo, contact);
@@ -72,10 +72,10 @@ public final class ContactTransferRejectFlow implements TransactionalFlow {
@Inject ContactTransferRejectFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyOptionalAuthInfo(authInfo, existingContact);
@@ -92,10 +92,10 @@ public final class ContactTransferRequestFlow implements TransactionalFlow {
@Inject ContactTransferRequestFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(gainingClientId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
verifyAuthInfoPresentForResourceTransfer(authInfo);
@@ -89,10 +89,10 @@ public final class ContactUpdateFlow implements TransactionalFlow {
@Inject ContactUpdateFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
Update command = (Update) resourceCommand;
DateTime now = tm().getTransactionTime();
ContactResource existingContact = loadAndVerifyExistence(ContactResource.class, targetId, now);
@@ -135,8 +135,8 @@ public final class DomainCheckFlow implements Flow {
extensionManager.register(
FeeCheckCommandExtension.class, LaunchCheckExtension.class, AllocationTokenExtension.class);
flowCustomLogic.beforeValidation();
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
ImmutableList<String> domainNames = ((Check) resourceCommand).getTargetIds();
verifyTargetIdCount(domainNames, maxChecks);
DateTime now = clock.nowUtc();
@@ -82,8 +82,8 @@ public final class DomainClaimsCheckFlow implements Flow {
@Override
public EppResponse run() throws EppException {
extensionManager.register(LaunchCheckExtension.class, AllocationTokenExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
if (eppInput.getSingleExtension(AllocationTokenExtension.class).isPresent()) {
throw new DomainClaimsCheckNotAllowedWithAllocationTokens();
}
@@ -198,7 +198,7 @@ import org.joda.time.Duration;
* @error {@link DomainPricingLogic.AllocationTokenInvalidForPremiumNameException}
*/
@ReportingSpec(ActivityReportField.DOMAIN_CREATE)
public class DomainCreateFlow implements TransactionalFlow {
public final class DomainCreateFlow implements TransactionalFlow {
/** Anchor tenant creates should always be for 2 years, since they get 2 years free. */
private static final int ANCHOR_TENANT_CREATE_VALID_YEARS = 2;
@@ -219,7 +219,7 @@ public class DomainCreateFlow implements TransactionalFlow {
@Inject DomainCreateFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(
FeeCreateCommandExtension.class,
SecDnsCreateExtension.class,
@@ -227,9 +227,9 @@ public class DomainCreateFlow implements TransactionalFlow {
LaunchCreateExtension.class,
AllocationTokenExtension.class);
flowCustomLogic.beforeValidation();
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
verifyRegistrarIsActive(registrarId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
DomainCommand.Create command = cloneAndLinkReferences((Create) resourceCommand, now);
Period period = command.getPeriod();
@@ -138,12 +138,12 @@ public final class DomainDeleteFlow implements TransactionalFlow {
@Inject DomainDeleteFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(
MetadataExtension.class, SecDnsCreateExtension.class, DomainDeleteSuperuserExtension.class);
flowCustomLogic.beforeValidation();
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
// Loads the target resource if it exists
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
@@ -91,11 +91,11 @@ public final class DomainInfoFlow implements Flow {
DomainInfoFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(FeeInfoCommandExtensionV06.class);
flowCustomLogic.beforeValidation();
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
DateTime now = clock.nowUtc();
DomainBase domain = verifyExistence(
DomainBase.class, targetId, loadByForeignKey(DomainBase.class, targetId, now));
@@ -135,12 +135,12 @@ public final class DomainRenewFlow implements TransactionalFlow {
@Inject DomainRenewFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(FeeRenewCommandExtension.class, MetadataExtension.class);
flowCustomLogic.beforeValidation();
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
verifyRegistrarIsActive(registrarId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
Renew command = (Renew) resourceCommand;
// Loads the target resource if it exists
@@ -128,14 +128,14 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
@Inject DomainRestoreRequestFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(
FeeUpdateCommandExtension.class,
MetadataExtension.class,
RgpUpdateExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
verifyRegistrarIsActive(registrarId);
extensionManager.validate();
Update command = (Update) resourceCommand;
DateTime now = tm().getTransactionTime();
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
@@ -99,14 +99,14 @@ public final class DomainTransferApproveFlow implements TransactionalFlow {
@Inject DomainTransferApproveFlow() {}
/**
* <p>The logic in this flow, which handles client approvals, very closely parallels the logic in
* The logic in this flow, which handles client approvals, very closely parallels the logic in
* {@link DomainBase#cloneProjectedAtTime} which handles implicit server approvals.
*/
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
verifyOptionalAuthInfo(authInfo, existingDomain);
@@ -86,10 +86,10 @@ public final class DomainTransferCancelFlow implements TransactionalFlow {
@Inject DomainTransferCancelFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
verifyOptionalAuthInfo(authInfo, existingDomain);
@@ -67,9 +67,9 @@ public final class DomainTransferQueryFlow implements Flow {
@Inject DomainTransferQueryFlow() {}
@Override
public final EppResponse run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
public EppResponse run() throws EppException {
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate(); // There are no legal extensions for this flow.
DateTime now = clock.nowUtc();
DomainBase domain = loadAndVerifyExistence(DomainBase.class, targetId, now);
verifyOptionalAuthInfo(authInfo, domain);
@@ -88,10 +88,10 @@ public final class DomainTransferRejectFlow implements TransactionalFlow {
@Inject DomainTransferRejectFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
Registry registry = Registry.get(existingDomain.getTld());
@@ -139,14 +139,14 @@ public final class DomainTransferRequestFlow implements TransactionalFlow {
@Inject DomainTransferRequestFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(
DomainTransferRequestSuperuserExtension.class,
FeeTransferCommandExtension.class,
MetadataExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(gainingClientId);
verifyRegistrarIsActive(gainingClientId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
Optional<DomainTransferRequestSuperuserExtension> superuserExtension =
@@ -43,6 +43,7 @@ import static google.registry.flows.domain.DomainFlowUtils.verifyNotInPendingDel
import static google.registry.model.reporting.HistoryEntry.Type.DOMAIN_UPDATE;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Ordering;
@@ -77,9 +78,11 @@ import google.registry.model.domain.secdns.SecDnsUpdateExtension;
import google.registry.model.domain.superuser.DomainUpdateSuperuserExtension;
import google.registry.model.eppcommon.AuthInfo;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.eppcommon.Trid;
import google.registry.model.eppinput.EppInput;
import google.registry.model.eppinput.ResourceCommand;
import google.registry.model.eppoutput.EppResponse;
import google.registry.model.poll.PendingActionNotificationResponse.DomainPendingActionNotificationResponse;
import google.registry.model.poll.PollMessage;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import google.registry.model.tld.Registry;
@@ -149,6 +152,7 @@ public final class DomainUpdateFlow implements TransactionalFlow {
@Inject @RegistrarId String registrarId;
@Inject @TargetId String targetId;
@Inject @Superuser boolean isSuperuser;
@Inject Trid trid;
@Inject DomainHistory.Builder historyBuilder;
@Inject DnsQueue dnsQueue;
@Inject EppResponse.Builder responseBuilder;
@@ -164,8 +168,8 @@ public final class DomainUpdateFlow implements TransactionalFlow {
SecDnsUpdateExtension.class,
DomainUpdateSuperuserExtension.class);
flowCustomLogic.beforeValidation();
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
Update command = cloneAndLinkReferences((Update) resourceCommand, now);
DomainBase existingDomain = loadAndVerifyExistence(DomainBase.class, targetId, now);
@@ -360,6 +364,10 @@ public final class DomainUpdateFlow implements TransactionalFlow {
.setEventTime(now)
.setRegistrarId(existingDomain.getCurrentSponsorRegistrarId())
.setMsg(msg)
.setResponseData(
ImmutableList.of(
DomainPendingActionNotificationResponse.create(
existingDomain.getDomainName(), true, trid, now)))
.build());
}
}
@@ -56,9 +56,9 @@ public final class HostCheckFlow implements Flow {
@Inject HostCheckFlow() {}
@Override
public final EppResponse run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
public EppResponse run() throws EppException {
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate(); // There are no legal extensions for this flow.
ImmutableList<String> hostnames = ((Check) resourceCommand).getTargetIds();
verifyTargetIdCount(hostnames, maxChecks);
ImmutableSet<String> existingIds =
@@ -100,10 +100,10 @@ public final class HostCreateFlow implements TransactionalFlow {
HostCreateFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
Create command = (Create) resourceCommand;
DateTime now = tm().getTransactionTime();
verifyResourceDoesNotExist(HostResource.class, targetId, now, registrarId);
@@ -92,10 +92,10 @@ public final class HostDeleteFlow implements TransactionalFlow {
HostDeleteFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
DateTime now = tm().getTransactionTime();
validateHostName(targetId);
checkLinkedDomains(targetId, now, HostResource.class, DomainBase::getNameservers);
@@ -62,8 +62,8 @@ public final class HostInfoFlow implements Flow {
@Override
public EppResponse run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate(); // There are no legal extensions for this flow.
validateHostName(targetId);
DateTime now = clock.nowUtc();
HostResource host = loadAndVerifyExistence(HostResource.class, targetId, now);
@@ -125,10 +125,10 @@ public final class HostUpdateFlow implements TransactionalFlow {
@Inject HostUpdateFlow() {}
@Override
public final EppResponse run() throws EppException {
public EppResponse run() throws EppException {
extensionManager.register(MetadataExtension.class);
extensionManager.validate();
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate();
Update command = (Update) resourceCommand;
Change change = command.getInnerChange();
String suppliedNewHostName = change.getFullyQualifiedHostName();
@@ -45,17 +45,17 @@ import org.joda.time.DateTime;
/**
* An EPP flow for acknowledging {@link PollMessage}s.
*
* <p>Registrars refer to poll messages using an externally visible id generated by
* {@link PollMessageExternalKeyConverter}. One-time poll messages are deleted from Datastore once
* they are ACKed, whereas autorenew poll messages are simply marked as read, and won't be delivered
* again until the next year of their recurrence.
* <p>Registrars refer to poll messages using an externally visible id generated by {@link
* PollMessageExternalKeyConverter}. One-time poll messages are deleted from Datastore once they are
* ACKed, whereas autorenew poll messages are simply marked as read, and won't be delivered again
* until the next year of their recurrence.
*
* @error {@link PollAckFlow.InvalidMessageIdException}
* @error {@link PollAckFlow.MessageDoesNotExistException}
* @error {@link PollAckFlow.MissingMessageIdException}
* @error {@link PollAckFlow.NotAuthorizedToAckMessageException}
*/
public class PollAckFlow implements TransactionalFlow {
public final class PollAckFlow implements TransactionalFlow {
@Inject ExtensionManager extensionManager;
@Inject @RegistrarId String registrarId;
@@ -65,9 +65,9 @@ public class PollAckFlow implements TransactionalFlow {
@Inject PollAckFlow() {}
@Override
public final EppResponse run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
public EppResponse run() throws EppException {
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate(); // There are no legal extensions for this flow.
if (messageId.isEmpty()) {
throw new MissingMessageIdException();
}
@@ -47,7 +47,7 @@ import org.joda.time.DateTime;
*
* @error {@link PollRequestFlow.UnexpectedMessageIdException}
*/
public class PollRequestFlow implements Flow {
public final class PollRequestFlow implements Flow {
@Inject ExtensionManager extensionManager;
@Inject @RegistrarId String registrarId;
@@ -57,9 +57,9 @@ public class PollRequestFlow implements Flow {
@Inject PollRequestFlow() {}
@Override
public final EppResponse run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
public EppResponse run() throws EppException {
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate(); // There are no legal extensions for this flow.
if (!messageId.isEmpty()) {
throw new UnexpectedMessageIdException();
}
@@ -27,7 +27,7 @@ import javax.inject.Inject;
*
* @error {@link google.registry.flows.FlowUtils.GenericXmlSyntaxErrorException}
*/
public class HelloFlow implements Flow {
public final class HelloFlow implements Flow {
@Inject ExtensionManager extensionManager;
@Inject Clock clock;
@@ -90,7 +90,7 @@ public class LoginFlow implements Flow {
}
/** Run the flow without bothering to log errors. The {@link #run} method will do that for us. */
private final EppResponse runWithoutLogging() throws EppException {
private EppResponse runWithoutLogging() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
Login login = (Login) eppInput.getCommandWrapper().getCommand();
if (!registrarId.isEmpty()) {
@@ -30,7 +30,7 @@ import javax.inject.Inject;
*
* @error {@link google.registry.flows.FlowUtils.NotLoggedInException}
*/
public class LogoutFlow implements Flow {
public final class LogoutFlow implements Flow {
@Inject ExtensionManager extensionManager;
@Inject @RegistrarId String registrarId;
@@ -39,9 +39,9 @@ public class LogoutFlow implements Flow {
@Inject LogoutFlow() {}
@Override
public final EppResponse run() throws EppException {
extensionManager.validate(); // There are no legal extensions for this flow.
public EppResponse run() throws EppException {
validateRegistrarIsLoggedIn(registrarId);
extensionManager.validate(); // There are no legal extensions for this flow.
sessionMetadata.invalidate();
return responseBuilder.setResultFromCode(SUCCESS_AND_CLOSE).build();
}
@@ -15,6 +15,7 @@
package google.registry.model;
import com.google.common.collect.ImmutableSet;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.billing.BillingEvent;
import google.registry.model.common.Cursor;
import google.registry.model.common.EntityGroupRoot;
@@ -45,6 +46,7 @@ import google.registry.model.server.ServerSecret;
import google.registry.model.tld.Registry;
/** Sets of classes of the Objectify-registered entities in use throughout the model. */
@DeleteAfterMigration
public final class EntityClasses {
/** Set of entity classes. */
@@ -20,6 +20,7 @@ import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.common.annotations.VisibleForTesting;
import google.registry.beam.common.RegistryPipelineWorkerInitializer;
import google.registry.config.RegistryEnvironment;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.concurrent.atomic.AtomicLong;
/**
@@ -28,6 +29,7 @@ import java.util.concurrent.atomic.AtomicLong;
* <p>In non-test, non-beam environments the Id is generated by Datastore, otherwise it's from an
* atomic long number that's incremented every time this method is called.
*/
@DeleteAfterMigration
public final class IdService {
/**
@@ -19,12 +19,14 @@ import static com.google.common.base.Predicates.subtypeOf;
import static java.util.stream.Collectors.joining;
import com.google.common.collect.Ordering;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.ArrayDeque;
import java.util.Queue;
import java.util.SortedSet;
import java.util.TreeSet;
/** Utility methods for getting the version of the model schema from the model code. */
@DeleteAfterMigration
public final class SchemaVersion {
/**
@@ -20,11 +20,13 @@ import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Parent;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.InCrossTld;
import javax.persistence.MappedSuperclass;
import javax.persistence.Transient;
/** A singleton entity in Datastore. */
@DeleteAfterMigration
@MappedSuperclass
@InCrossTld
public abstract class CrossTldSingleton extends ImmutableObject {
@@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.flogger.FluentLogger;
import google.registry.config.RegistryEnvironment;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.common.TimedTransitionProperty.TimedTransition;
import google.registry.model.replay.SqlOnlyEntity;
import java.time.Duration;
@@ -39,6 +40,7 @@ import org.joda.time.DateTime;
* <p>The entity is stored in SQL throughout the entire migration so as to have a single point of
* access.
*/
@DeleteAfterMigration
@Entity
public class DatabaseMigrationStateSchedule extends CrossTldSingleton implements SqlOnlyEntity {
@@ -19,6 +19,7 @@ import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import google.registry.model.BackupGroupRoot;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.replay.DatastoreOnlyEntity;
import javax.annotation.Nullable;
@@ -37,6 +38,7 @@ import javax.annotation.Nullable;
* entity group for the single namespace where global data applicable for all TLDs lived.
*/
@Entity
@DeleteAfterMigration
public class EntityGroupRoot extends BackupGroupRoot implements DatastoreOnlyEntity {
@SuppressWarnings("unused")
@@ -24,12 +24,15 @@ import com.googlecode.objectify.annotation.Index;
import com.googlecode.objectify.annotation.Parent;
import google.registry.model.BackupGroupRoot;
import google.registry.model.EppResource;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.ReportedOn;
import google.registry.model.replay.DatastoreOnlyEntity;
import google.registry.persistence.VKey;
/** An index that allows for quick enumeration of all EppResource entities (e.g. via map reduce). */
@ReportedOn
@Entity
@DeleteAfterMigration
public class EppResourceIndex extends BackupGroupRoot implements DatastoreOnlyEntity {
@Id String id;
@@ -64,8 +67,9 @@ public class EppResourceIndex extends BackupGroupRoot implements DatastoreOnlyEn
EppResourceIndex instance = instantiate(EppResourceIndex.class);
instance.reference = resourceKey;
instance.kind = resourceKey.getKind();
// TODO(b/207368050): figure out if this value has ever been used other than test cases
instance.id = resourceKey.getString(); // creates a web-safe key string
// creates a web-safe key string, this value is never used
// TODO(b/211785379): remove unused id
instance.id = VKey.from(resourceKey).stringify();
instance.bucket = bucket;
return instance;
}
@@ -23,12 +23,14 @@ import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import google.registry.model.EppResource;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.VirtualEntity;
import google.registry.model.replay.DatastoreOnlyEntity;
/** A virtual entity to represent buckets to which EppResourceIndex objects are randomly added. */
@Entity
@VirtualEntity
@DeleteAfterMigration
public class EppResourceIndexBucket extends ImmutableObject implements DatastoreOnlyEntity {
@SuppressWarnings("unused")
@@ -43,6 +43,7 @@ import com.googlecode.objectify.annotation.Index;
import google.registry.config.RegistryConfig;
import google.registry.model.BackupGroupRoot;
import google.registry.model.EppResource;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.ReportedOn;
import google.registry.model.contact.ContactResource;
import google.registry.model.domain.DomainBase;
@@ -65,6 +66,7 @@ import org.joda.time.Duration;
* the foreign key string. The instance is never deleted, but it is updated if a newer entity
* becomes the active entity.
*/
@DeleteAfterMigration
public abstract class ForeignKeyIndex<E extends EppResource> extends BackupGroupRoot {
/** The {@link ForeignKeyIndex} type for {@link ContactResource} entities. */
@@ -23,6 +23,7 @@ import com.googlecode.objectify.Key;
import com.googlecode.objectify.Result;
import com.googlecode.objectify.cmd.DeleteType;
import com.googlecode.objectify.cmd.Deleter;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.Arrays;
import java.util.stream.Stream;
@@ -30,6 +31,7 @@ import java.util.stream.Stream;
* A Deleter that forwards to {@code auditedOfy().delete()}, but can be augmented via subclassing to
* do custom processing on the keys to be deleted prior to their deletion.
*/
@DeleteAfterMigration
abstract class AugmentedDeleter implements Deleter {
private final Deleter delegate = ofy().delete();
@@ -21,13 +21,15 @@ import com.google.common.collect.ImmutableList;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Result;
import com.googlecode.objectify.cmd.Saver;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.Arrays;
import java.util.Map;
/**
* A Saver that forwards to {@code ofy().save()}, but can be augmented via subclassing to
* do custom processing on the entities to be saved prior to their saving.
* A Saver that forwards to {@code ofy().save()}, but can be augmented via subclassing to do custom
* processing on the entities to be saved prior to their saving.
*/
@DeleteAfterMigration
abstract class AugmentedSaver implements Saver {
private final Saver delegate = ofy().save();
@@ -31,6 +31,7 @@ import com.googlecode.objectify.annotation.Id;
import google.registry.config.RegistryConfig;
import google.registry.model.Buildable;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.NotBackedUp;
import google.registry.model.annotations.NotBackedUp.Reason;
import google.registry.model.replay.DatastoreOnlyEntity;
@@ -51,6 +52,7 @@ import org.joda.time.DateTime;
*/
@Entity
@NotBackedUp(reason = Reason.COMMIT_LOGS)
@DeleteAfterMigration
public class CommitLogBucket extends ImmutableObject implements Buildable, DatastoreOnlyEntity {
/**
@@ -25,6 +25,7 @@ import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Parent;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.NotBackedUp;
import google.registry.model.annotations.NotBackedUp.Reason;
import google.registry.model.replay.DatastoreOnlyEntity;
@@ -45,6 +46,7 @@ import org.joda.time.DateTime;
*/
@Entity
@NotBackedUp(reason = Reason.COMMIT_LOGS)
@DeleteAfterMigration
public class CommitLogCheckpoint extends ImmutableObject implements DatastoreOnlyEntity {
/** Shared singleton parent entity for commit log checkpoints. */
@@ -21,6 +21,7 @@ import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.NotBackedUp;
import google.registry.model.annotations.NotBackedUp.Reason;
import google.registry.model.replay.DatastoreOnlyEntity;
@@ -29,6 +30,7 @@ import org.joda.time.DateTime;
/** Singleton parent entity for all commit log checkpoints. */
@Entity
@NotBackedUp(reason = Reason.COMMIT_LOGS)
@DeleteAfterMigration
public class CommitLogCheckpointRoot extends ImmutableObject implements DatastoreOnlyEntity {
public static final long SINGLETON_ID = 1; // There is always exactly one of these.
@@ -23,6 +23,7 @@ import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Parent;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.NotBackedUp;
import google.registry.model.annotations.NotBackedUp.Reason;
import google.registry.model.replay.DatastoreOnlyEntity;
@@ -39,6 +40,7 @@ import org.joda.time.DateTime;
*/
@Entity
@NotBackedUp(reason = Reason.COMMIT_LOGS)
@DeleteAfterMigration
public class CommitLogManifest extends ImmutableObject implements DatastoreOnlyEntity {
/** Commit log manifests are parented on a random bucket. */
@@ -27,6 +27,7 @@ import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import com.googlecode.objectify.annotation.Parent;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.NotBackedUp;
import google.registry.model.annotations.NotBackedUp.Reason;
import google.registry.model.replay.DatastoreOnlyEntity;
@@ -34,6 +35,7 @@ import google.registry.model.replay.DatastoreOnlyEntity;
/** Representation of a saved entity in a {@link CommitLogManifest} (not deletes). */
@Entity
@NotBackedUp(reason = Reason.COMMIT_LOGS)
@DeleteAfterMigration
public class CommitLogMutation extends ImmutableObject implements DatastoreOnlyEntity {
/** The manifest this belongs to. */
@@ -30,6 +30,7 @@ import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.model.BackupGroupRoot;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.util.Clock;
import java.util.HashSet;
import java.util.Map;
@@ -39,6 +40,7 @@ import java.util.function.Supplier;
import org.joda.time.DateTime;
/** Wrapper for {@link Supplier} that associates a time with each attempt. */
@DeleteAfterMigration
class CommitLoggedWork<R> implements Runnable {
private final Supplier<R> work;
@@ -33,6 +33,7 @@ import com.googlecode.objectify.Key;
import com.googlecode.objectify.Result;
import com.googlecode.objectify.cmd.Query;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.InCrossTld;
import google.registry.model.contact.ContactHistory;
import google.registry.model.domain.DomainHistory;
@@ -55,6 +56,7 @@ import javax.persistence.NonUniqueResultException;
import org.joda.time.DateTime;
/** Datastore implementation of {@link TransactionManager}. */
@DeleteAfterMigration
public class DatastoreTransactionManager implements TransactionManager {
private Ofy injectedOfy;
@@ -16,6 +16,7 @@ package google.registry.model.ofy;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import google.registry.model.annotations.DeleteAfterMigration;
/**
* Contains the mapping from class names to SQL-replay-write priorities.
@@ -26,6 +27,7 @@ import com.google.common.collect.ImmutableMap;
* values represent an earlier write (and later delete). Higher-valued classes can have foreign keys
* on lower-valued classes, but not vice versa.
*/
@DeleteAfterMigration
public class EntityWritePriorities {
/**
@@ -35,6 +35,7 @@ import google.registry.config.RegistryEnvironment;
import google.registry.model.Buildable;
import google.registry.model.EntityClasses;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.translators.BloomFilterOfStringTranslatorFactory;
import google.registry.model.translators.CidrAddressBlockTranslatorFactory;
import google.registry.model.translators.CommitLogRevisionsTranslatorFactory;
@@ -52,6 +53,7 @@ import google.registry.model.translators.VKeyTranslatorFactory;
* objects. The class contains a static initializer to call factory().register(...) on all
* persistable objects in this package.
*/
@DeleteAfterMigration
public class ObjectifyService {
/** A singleton instance of our Ofy wrapper. */
@@ -37,6 +37,7 @@ import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.cmd.Deleter;
import com.googlecode.objectify.cmd.Loader;
import com.googlecode.objectify.cmd.Saver;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.NotBackedUp;
import google.registry.model.annotations.VirtualEntity;
import google.registry.model.ofy.ReadOnlyWork.KillTransactionException;
@@ -59,6 +60,7 @@ import org.joda.time.Duration;
* simpler to wrap {@link Objectify} rather than extend it because this way we can remove some
* methods that we don't really want exposed and add some shortcuts.
*/
@DeleteAfterMigration
public class Ofy {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@@ -14,6 +14,7 @@
package google.registry.model.ofy;
import google.registry.model.annotations.DeleteAfterMigration;
import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
@@ -23,6 +24,7 @@ import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
/** A filter that statically registers types with Objectify. */
@DeleteAfterMigration
public class OfyFilter implements Filter {
@Override
@@ -14,10 +14,12 @@
package google.registry.model.ofy;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.util.Clock;
import java.util.function.Supplier;
/** Wrapper for {@link Supplier} that disallows mutations and fails the transaction at the end. */
@DeleteAfterMigration
class ReadOnlyWork<R> extends CommitLoggedWork<R> {
ReadOnlyWork(Supplier<R> work, Clock clock) {
@@ -22,6 +22,7 @@ import com.google.common.collect.ImmutableMap;
import com.googlecode.objectify.Key;
import google.registry.config.RegistryEnvironment;
import google.registry.model.UpdateAutoTimestamp;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.replay.DatastoreEntity;
import google.registry.model.replay.ReplaySpecializer;
import google.registry.persistence.VKey;
@@ -34,6 +35,7 @@ import java.util.concurrent.ConcurrentLinkedQueue;
*
* <p>This code is to be removed when the actual replay cron job is implemented.
*/
@DeleteAfterMigration
public class ReplayQueue {
static ConcurrentLinkedQueue<ImmutableMap<Key<?>, Object>> queue =
@@ -28,6 +28,7 @@ import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Transaction;
import com.google.appengine.api.datastore.TransactionOptions;
import com.google.common.collect.ImmutableList;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
@@ -35,6 +36,7 @@ import java.util.Map;
import java.util.concurrent.Future;
/** A proxy for {@link AsyncDatastoreService} that exposes call counts. */
@DeleteAfterMigration
public class RequestCapturingAsyncDatastoreService implements AsyncDatastoreService {
private final AsyncDatastoreService delegate;
@@ -18,8 +18,10 @@ import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.impl.ObjectifyImpl;
import google.registry.model.annotations.DeleteAfterMigration;
/** Registry-specific Objectify subclass that exposes the keys used in the current session. */
@DeleteAfterMigration
public class SessionKeyExposingObjectify extends ObjectifyImpl<SessionKeyExposingObjectify> {
public SessionKeyExposingObjectify(ObjectifyFactory factory) {
@@ -17,6 +17,7 @@ package google.registry.model.ofy;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Objectify;
import google.registry.model.BackupGroupRoot;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.Arrays;
import java.util.Map;
import org.joda.time.DateTime;
@@ -25,6 +26,7 @@ import org.joda.time.DateTime;
* Exception when trying to write to Datastore with a timestamp that is inconsistent with a partial
* ordering on transactions that touch the same entities.
*/
@DeleteAfterMigration
class TimestampInversionException extends RuntimeException {
static String getFileAndLine(StackTraceElement callsite) {
@@ -26,10 +26,12 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.googlecode.objectify.Key;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.Map;
import org.joda.time.DateTime;
/** Metadata for an {@link Ofy} transaction that saves commit logs. */
@DeleteAfterMigration
public class TransactionInfo {
@VisibleForTesting
@@ -14,9 +14,11 @@
package google.registry.model.replay;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.Optional;
/** An entity that has the same Java object representation in SQL and Datastore. */
@DeleteAfterMigration
public interface DatastoreAndSqlEntity extends DatastoreEntity, SqlEntity {
@Override
@@ -14,6 +14,7 @@
package google.registry.model.replay;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.Optional;
/**
@@ -24,6 +25,7 @@ import java.util.Optional;
* transactions and data into the secondary SQL store during the first, Datastore-primary, phase of
* the migration.
*/
@DeleteAfterMigration
public interface DatastoreEntity {
Optional<SqlEntity> toSqlEntity();
@@ -14,9 +14,11 @@
package google.registry.model.replay;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.Optional;
/** An entity that is only stored in Datastore, that should not be replayed to SQL. */
@DeleteAfterMigration
public interface DatastoreOnlyEntity extends DatastoreEntity {
@Override
default Optional<SqlEntity> toSqlEntity() {
@@ -22,9 +22,11 @@ import com.googlecode.objectify.Key;
import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.Id;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration;
/** Datastore entity to keep track of the last SQL transaction imported into the datastore. */
@Entity
@DeleteAfterMigration
public class LastSqlTransaction extends ImmutableObject implements DatastoreOnlyEntity {
/** The key for this singleton. */
@@ -14,6 +14,7 @@
package google.registry.model.replay;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.Optional;
/**
@@ -21,6 +22,7 @@ import java.util.Optional;
*
* <p>We expect that this is a result of the entity being dually-written.
*/
@DeleteAfterMigration
public interface NonReplicatedEntity extends DatastoreEntity, SqlEntity {
@Override
@@ -14,6 +14,7 @@
package google.registry.model.replay;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.persistence.VKey;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -25,6 +26,7 @@ import java.lang.reflect.Method;
* not directly present in the other database. This class allows us to do that by using reflection
* to invoke special class methods if they are present.
*/
@DeleteAfterMigration
public class ReplaySpecializer {
public static void beforeSqlDelete(VKey<?> key) {
@@ -27,6 +27,7 @@ import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
import google.registry.model.UpdateAutoTimestamp;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.common.DatabaseMigrationStateSchedule;
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
import google.registry.model.common.DatabaseMigrationStateSchedule.ReplayDirection;
@@ -53,6 +54,7 @@ import org.joda.time.Duration;
automaticallyPrintOk = true,
auth = Auth.AUTH_INTERNAL_OR_ADMIN)
@VisibleForTesting
@DeleteAfterMigration
public class ReplicateToDatastoreAction implements Runnable {
public static final String PATH = "/_dr/cron/replicateToDatastore";
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@@ -16,6 +16,7 @@ package google.registry.model.replay;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.Optional;
/**
@@ -25,6 +26,7 @@ import java.util.Optional;
* <p>This will be used when replaying SQL transactions into Datastore, during the second,
* SQL-primary, phase of the migration from Datastore to SQL.
*/
@DeleteAfterMigration
public interface SqlEntity {
Optional<DatastoreEntity> toDatastoreEntity();
@@ -14,9 +14,11 @@
package google.registry.model.replay;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.Optional;
/** An entity that is only stored in SQL, that should not be replayed to Datastore. */
@DeleteAfterMigration
public interface SqlOnlyEntity extends SqlEntity {
@Override
default Optional<DatastoreEntity> toDatastoreEntity() {
@@ -17,12 +17,14 @@ package google.registry.model.replay;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.common.CrossTldSingleton;
import javax.persistence.Column;
import javax.persistence.Entity;
import org.joda.time.DateTime;
@Entity
@DeleteAfterMigration
public class SqlReplayCheckpoint extends CrossTldSingleton implements SqlOnlyEntity {
@Column(nullable = false)
@@ -14,11 +14,13 @@
package google.registry.model.tld.label;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static google.registry.config.RegistryConfig.getDomainLabelListCacheDuration;
import static google.registry.config.RegistryConfig.getSingletonCachePersistDuration;
import static google.registry.config.RegistryConfig.getStaticPremiumListMaxCachedEntries;
import static google.registry.persistence.transaction.TransactionManagerFactory.jpaTm;
import static google.registry.util.CollectionUtils.isNullOrEmpty;
import com.google.auto.value.AutoValue;
import com.google.common.annotations.VisibleForTesting;
@@ -153,27 +155,26 @@ public class PremiumListDao {
}
public static PremiumList save(String name, CurrencyUnit currencyUnit, List<String> inputData) {
checkArgument(!inputData.isEmpty(), "New premium list data cannot be empty");
return save(PremiumListUtils.parseToPremiumList(name, currencyUnit, inputData));
}
/** Saves the given premium list (and its premium list entries) to Cloud SQL. */
public static PremiumList save(PremiumList premiumList) {
jpaTm().transact(() -> jpaTm().insert(premiumList));
premiumListCache.invalidate(premiumList.getName());
jpaTm()
.transact(
() -> {
if (premiumList.getLabelsToPrices() != null) {
Optional<PremiumList> savedPremiumList =
PremiumListDao.getLatestRevision(premiumList.getName());
jpaTm().insert(premiumList);
jpaTm().getEntityManager().flush(); // This populates the revisionId.
long revisionId = premiumList.getRevisionId();
if (!isNullOrEmpty(premiumList.getLabelsToPrices())) {
ImmutableSet.Builder<PremiumEntry> entries = new ImmutableSet.Builder<>();
premiumList.getLabelsToPrices().entrySet().stream()
.forEach(
entry ->
entries.add(
PremiumEntry.create(
savedPremiumList.get().getRevisionId(),
entry.getValue(),
entry.getKey())));
PremiumEntry.create(revisionId, entry.getValue(), entry.getKey())));
jpaTm().insertAll(entries.build());
}
});
@@ -14,7 +14,6 @@
package google.registry.model.tld.label;
import static com.google.common.base.Preconditions.checkArgument;
import static org.joda.time.DateTimeZone.UTC;
import com.google.common.collect.ImmutableMap;
@@ -38,7 +37,6 @@ public class PremiumListUtils {
.setCreationTimestamp(DateTime.now(UTC))
.build();
ImmutableMap<String, PremiumEntry> prices = partialPremiumList.parse(inputData);
checkArgument(inputData.size() > 0, "Input cannot be empty");
Map<String, BigDecimal> priceAmounts = Maps.transformValues(prices, PremiumEntry::getValue);
return partialPremiumList.asBuilder().setLabelsToPrices(priceAmounts).build();
}
@@ -23,6 +23,7 @@ import static google.registry.util.DateTimeUtils.START_OF_TIME;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Ordering;
import com.googlecode.objectify.Key;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.ofy.CommitLogManifest;
import google.registry.persistence.transaction.Transaction;
import org.joda.time.DateTime;
@@ -31,11 +32,12 @@ import org.joda.time.DateTime;
* Objectify translator for {@code ImmutableSortedMap<DateTime, Key<CommitLogManifest>>} fields.
*
* <p>This translator is responsible for doing three things:
*
* <ol>
* <li>Translating the data into two lists of {@code Date} and {@code Key} objects, in a manner
* similar to {@code @Mapify}.
* <li>Inserting a key to the transaction's {@link CommitLogManifest} on save.
* <li>Truncating the map to include only the last key per day for the last 30 days.
* <li>Translating the data into two lists of {@code Date} and {@code Key} objects, in a manner
* similar to {@code @Mapify}.
* <li>Inserting a key to the transaction's {@link CommitLogManifest} on save.
* <li>Truncating the map to include only the last key per day for the last 30 days.
* </ol>
*
* <p>This allows you to have a field on your model object that tracks historical revisions of
@@ -46,6 +48,7 @@ import org.joda.time.DateTime;
*
* @see google.registry.model.EppResource
*/
@DeleteAfterMigration
public final class CommitLogRevisionsTranslatorFactory
extends ImmutableSortedMapTranslatorFactory<DateTime, Key<CommitLogManifest>> {
@@ -19,6 +19,7 @@ import google.registry.config.CredentialModule;
import google.registry.config.RegistryConfig.ConfigModule;
import google.registry.keyring.kms.KmsModule;
import google.registry.persistence.PersistenceModule.AppEngineJpaTm;
import google.registry.persistence.PersistenceModule.ReadOnlyReplicaJpaTm;
import google.registry.persistence.transaction.JpaTransactionManager;
import google.registry.privileges.secretmanager.SecretManagerModule;
import google.registry.util.UtilsModule;
@@ -40,4 +41,7 @@ public interface PersistenceComponent {
@AppEngineJpaTm
JpaTransactionManager appEngineJpaTransactionManager();
@ReadOnlyReplicaJpaTm
JpaTransactionManager readOnlyReplicaJpaTransactionManager();
}
@@ -122,8 +122,11 @@ public abstract class PersistenceModule {
@Config("cloudSqlJdbcUrl") String jdbcUrl,
@Config("cloudSqlInstanceConnectionName") String instanceConnectionName,
@DefaultHibernateConfigs ImmutableMap<String, String> defaultConfigs) {
return createPartialSqlConfigs(
jdbcUrl, instanceConnectionName, defaultConfigs, Optional.empty());
HashMap<String, String> overrides = Maps.newHashMap(defaultConfigs);
overrides.put(Environment.URL, jdbcUrl);
overrides.put(HIKARI_DS_SOCKET_FACTORY, "com.google.cloud.sql.postgres.SocketFactory");
overrides.put(HIKARI_DS_CLOUD_SQL_INSTANCE, instanceConnectionName);
return ImmutableMap.copyOf(overrides);
}
/**
@@ -184,22 +187,6 @@ public abstract class PersistenceModule {
return ImmutableMap.copyOf(overrides);
}
@VisibleForTesting
static ImmutableMap<String, String> createPartialSqlConfigs(
String jdbcUrl,
String instanceConnectionName,
ImmutableMap<String, String> defaultConfigs,
Optional<Provider<TransactionIsolationLevel>> isolationOverride) {
HashMap<String, String> overrides = Maps.newHashMap(defaultConfigs);
overrides.put(Environment.URL, jdbcUrl);
overrides.put(HIKARI_DS_SOCKET_FACTORY, "com.google.cloud.sql.postgres.SocketFactory");
overrides.put(HIKARI_DS_CLOUD_SQL_INSTANCE, instanceConnectionName);
isolationOverride
.map(Provider::get)
.ifPresent(override -> overrides.put(Environment.ISOLATION, override.name()));
return ImmutableMap.copyOf(overrides);
}
/**
* Provides a {@link Supplier} of single-use JDBC {@link Connection connections} that can manage
* the database DDL schema.
@@ -280,6 +267,36 @@ public abstract class PersistenceModule {
return new JpaTransactionManagerImpl(create(overrides), clock);
}
@Provides
@Singleton
@ReadOnlyReplicaJpaTm
static JpaTransactionManager provideReadOnlyReplicaJpaTm(
SqlCredentialStore credentialStore,
@PartialCloudSqlConfigs ImmutableMap<String, String> cloudSqlConfigs,
@Config("cloudSqlReplicaInstanceConnectionName")
Optional<String> replicaInstanceConnectionName,
Clock clock) {
HashMap<String, String> overrides = Maps.newHashMap(cloudSqlConfigs);
setSqlCredential(credentialStore, new RobotUser(RobotId.NOMULUS), overrides);
replicaInstanceConnectionName.ifPresent(
name -> overrides.put(HIKARI_DS_CLOUD_SQL_INSTANCE, name));
return new JpaTransactionManagerImpl(create(overrides), clock);
}
@Provides
@Singleton
@BeamReadOnlyReplicaJpaTm
static JpaTransactionManager provideBeamReadOnlyReplicaJpaTm(
@BeamPipelineCloudSqlConfigs ImmutableMap<String, String> beamCloudSqlConfigs,
@Config("cloudSqlReplicaInstanceConnectionName")
Optional<String> replicaInstanceConnectionName,
Clock clock) {
HashMap<String, String> overrides = Maps.newHashMap(beamCloudSqlConfigs);
replicaInstanceConnectionName.ifPresent(
name -> overrides.put(HIKARI_DS_CLOUD_SQL_INSTANCE, name));
return new JpaTransactionManagerImpl(create(overrides), clock);
}
/** Constructs the {@link EntityManagerFactory} instance. */
@VisibleForTesting
static EntityManagerFactory create(
@@ -357,7 +374,12 @@ public abstract class PersistenceModule {
* The {@link JpaTransactionManager} optimized for bulk loading multi-level JPA entities. Please
* see {@link google.registry.model.bulkquery.BulkQueryEntities} for more information.
*/
BULK_QUERY
BULK_QUERY,
/**
* The {@link JpaTransactionManager} that uses the read-only Postgres replica if configured, or
* the standard DB if not.
*/
READ_ONLY_REPLICA
}
/** Dagger qualifier for JDBC {@link Connection} with schema management privilege. */
@@ -383,6 +405,22 @@ public abstract class PersistenceModule {
@Documented
public @interface BeamBulkQueryJpaTm {}
/**
* Dagger qualifier for {@link JpaTransactionManager} used inside BEAM pipelines that uses the
* read-only Postgres replica if one is configured (otherwise it uses the standard DB).
*/
@Qualifier
@Documented
public @interface BeamReadOnlyReplicaJpaTm {}
/**
* Dagger qualifier for {@link JpaTransactionManager} that uses the read-only Postgres replica if
* one is configured (otherwise it uses the standard DB).
*/
@Qualifier
@Documented
public @interface ReadOnlyReplicaJpaTm {}
/** Dagger qualifier for {@link JpaTransactionManager} used for Nomulus tool. */
@Qualifier
@Documented
@@ -144,7 +144,7 @@ public class VKey<T> extends ImmutableObject implements Serializable {
*/
public static <T> VKey<T> create(String keyString) {
if (!keyString.startsWith(CLASS_TYPE + KV_SEPARATOR)) {
// to handle the existing ofy key string
// handle the existing ofy key string
return fromWebsafeKey(keyString);
} else {
ImmutableMap<String, String> kvs =
@@ -307,6 +307,7 @@ public class VKey<T> extends ImmutableObject implements Serializable {
if (maybeGetSqlKey().isPresent()) {
key += DELIMITER + SQL_LOOKUP_KEY + KV_SEPARATOR + SerializeUtils.stringify(getSqlKey());
}
// getString() method returns a Base64 encoded web safe of ofy key
if (maybeGetOfyKey().isPresent()) {
key += DELIMITER + OFY_LOOKUP_KEY + KV_SEPARATOR + getOfyKey().getString();
}
@@ -15,6 +15,7 @@
package google.registry.persistence.converter;
import com.google.common.collect.Maps;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.common.DatabaseMigrationStateSchedule;
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationStateTransition;
@@ -23,6 +24,7 @@ import javax.persistence.Converter;
import org.joda.time.DateTime;
/** JPA converter for {@link DatabaseMigrationStateSchedule} transitions. */
@DeleteAfterMigration
@Converter(autoApply = true)
public class DatabaseMigrationScheduleTransitionConverter
extends TimedTransitionPropertyConverterBase<MigrationState, MigrationStateTransition> {
@@ -16,6 +16,7 @@ package google.registry.persistence.transaction;
import static google.registry.persistence.transaction.TransactionManagerFactory.assertNotReadOnlyMode;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.List;
import java.util.Map;
import javax.persistence.EntityGraph;
@@ -34,6 +35,7 @@ import javax.persistence.criteria.CriteriaUpdate;
import javax.persistence.metamodel.Metamodel;
/** An {@link EntityManager} that throws exceptions on write actions if in read-only mode. */
@DeleteAfterMigration
public class ReadOnlyCheckingEntityManager implements EntityManager {
private final EntityManager delegate;
@@ -16,6 +16,7 @@ package google.registry.persistence.transaction;
import static google.registry.persistence.transaction.TransactionManagerFactory.assertNotReadOnlyMode;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@@ -29,6 +30,7 @@ import javax.persistence.Query;
import javax.persistence.TemporalType;
/** A {@link Query} that throws exceptions on write actions if in read-only mode. */
@DeleteAfterMigration
class ReadOnlyCheckingQuery implements Query {
private final Query delegate;
@@ -16,6 +16,7 @@ package google.registry.persistence.transaction;
import static google.registry.persistence.transaction.TransactionManagerFactory.assertNotReadOnlyMode;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
@@ -29,6 +30,7 @@ import javax.persistence.TemporalType;
import javax.persistence.TypedQuery;
/** A {@link TypedQuery <T>} that throws exceptions on write actions if in read-only mode. */
@DeleteAfterMigration
class ReadOnlyCheckingTypedQuery<T> implements TypedQuery<T> {
private final TypedQuery<T> delegate;
@@ -14,7 +14,6 @@
package google.registry.rde;
import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
import static google.registry.request.RequestParameters.extractBooleanParameter;
import static google.registry.request.RequestParameters.extractOptionalIntParameter;
import static google.registry.request.RequestParameters.extractOptionalParameter;
@@ -22,7 +21,6 @@ import static google.registry.request.RequestParameters.extractRequiredDatetimeP
import static google.registry.request.RequestParameters.extractSetOfDatetimeParameters;
import static google.registry.request.RequestParameters.extractSetOfParameters;
import com.google.appengine.api.taskqueue.Queue;
import com.google.common.collect.ImmutableSet;
import com.jcraft.jsch.SftpProgressMonitor;
import dagger.Binds;
@@ -30,7 +28,6 @@ import dagger.Module;
import dagger.Provides;
import google.registry.request.Parameter;
import java.util.Optional;
import javax.inject.Named;
import javax.servlet.http.HttpServletRequest;
import org.joda.time.DateTime;
@@ -110,12 +107,6 @@ public abstract class RdeModule {
return extractOptionalParameter(req, PARAM_PREFIX);
}
@Provides
@Named("rde-report")
static Queue provideQueueRdeReport() {
return getQueue("rde-report");
}
@Binds
abstract SftpProgressMonitor provideSftpProgressMonitor(
LoggingSftpProgressMonitor loggingSftpProgressMonitor);
@@ -56,6 +56,7 @@ import google.registry.model.host.HostResource;
import google.registry.model.index.EppResourceIndex;
import google.registry.model.rde.RdeMode;
import google.registry.model.registrar.Registrar;
import google.registry.persistence.PersistenceModule.JpaTransactionManagerType;
import google.registry.request.Action;
import google.registry.request.HttpException.BadRequestException;
import google.registry.request.Parameter;
@@ -340,6 +341,9 @@ public final class RdeStagingAction implements Runnable {
.encode(stagingKeyBytes))
.put("registryEnvironment", RegistryEnvironment.get().name())
.put("workerMachineType", machineType)
.put(
"jpaTransactionManagerType",
JpaTransactionManagerType.READ_ONLY_REPLICA.toString())
// TODO (jianglai): Investigate turning off public IPs (for which
// there is a quota) in order to increase the total number of
// workers allowed (also under quota).
@@ -17,6 +17,7 @@ package google.registry.tools;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import google.registry.model.annotations.DeleteAfterMigration;
import java.io.File;
/**
@@ -27,6 +28,7 @@ import java.io.File;
* two-level directory hierarchy with data files in level-db format (output-*) and Datastore
* metadata files (*.export_metadata).
*/
@DeleteAfterMigration
class CompareDbBackups {
private static final String DS_V3_BACKUP_FILE_PREFIX = "output-";
@@ -14,7 +14,6 @@
package google.registry.tools;
import static com.google.appengine.api.taskqueue.TaskOptions.Builder.withUrl;
import static google.registry.model.tld.Registries.assertTldsExist;
import static google.registry.rde.RdeModule.PARAM_BEAM;
import static google.registry.rde.RdeModule.PARAM_DIRECTORY;
@@ -23,23 +22,22 @@ import static google.registry.rde.RdeModule.PARAM_MANUAL;
import static google.registry.rde.RdeModule.PARAM_MODE;
import static google.registry.rde.RdeModule.PARAM_REVISION;
import static google.registry.rde.RdeModule.PARAM_WATERMARKS;
import static google.registry.rde.RdeModule.RDE_REPORT_QUEUE;
import static google.registry.request.RequestParameters.PARAM_TLDS;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import com.beust.jcommander.Parameters;
import com.google.appengine.api.taskqueue.Queue;
import com.google.appengine.api.taskqueue.TaskOptions;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableMultimap;
import google.registry.model.rde.RdeMode;
import google.registry.rde.RdeStagingAction;
import google.registry.request.Action.Service;
import google.registry.tools.params.DateTimeParameter;
import google.registry.util.AppEngineServiceUtils;
import google.registry.util.CloudTasksUtils;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.inject.Named;
import org.joda.time.DateTime;
/**
@@ -94,15 +92,7 @@ final class GenerateEscrowDepositCommand implements CommandWithRemoteApi {
@Inject AppEngineServiceUtils appEngineServiceUtils;
@Inject
@Named("rde-report")
Queue queue;
// ETA is a required property for TaskOptions but we let the service to set it when submitting the
// task to the task queue. However, the local test service doesn't do that for us during the unit
// test, so we add this field here to let the unit test be able to inject the ETA to pass the
// test.
@VisibleForTesting Optional<Long> maybeEtaMillis = Optional.empty();
@Inject CloudTasksUtils cloudTasksUtils;
@Override
public void run() {
@@ -126,27 +116,25 @@ final class GenerateEscrowDepositCommand implements CommandWithRemoteApi {
throw new ParameterException("Output subdirectory must not be empty");
}
// Unlike many tool commands, this command is actually invoking an action on the backend module
// (because it's a mapreduce). So we invoke it in a different way.
String hostname = appEngineServiceUtils.getCurrentVersionHostname("backend");
TaskOptions opts =
withUrl(RdeStagingAction.PATH)
.header("Host", hostname)
.param(PARAM_MANUAL, String.valueOf(true))
.param(PARAM_MODE, mode.toString())
.param(PARAM_DIRECTORY, outdir)
.param(PARAM_LENIENT, Boolean.toString(lenient))
.param(PARAM_BEAM, Boolean.toString(beam))
.param(PARAM_TLDS, tlds.stream().collect(Collectors.joining(",")))
.param(
ImmutableMultimap.Builder<String, String> paramsBuilder =
new ImmutableMultimap.Builder<String, String>()
.put(PARAM_MANUAL, String.valueOf(true))
.put(PARAM_MODE, mode.toString())
.put(PARAM_DIRECTORY, outdir)
.put(PARAM_LENIENT, Boolean.toString(lenient))
.put(PARAM_BEAM, Boolean.toString(beam))
.put(PARAM_TLDS, tlds.stream().collect(Collectors.joining(",")))
.put(
PARAM_WATERMARKS,
watermarks.stream().map(DateTime::toString).collect(Collectors.joining(",")));
if (revision != null) {
opts = opts.param(PARAM_REVISION, String.valueOf(revision));
paramsBuilder.put(PARAM_REVISION, String.valueOf(revision));
}
if (maybeEtaMillis.isPresent()) {
opts = opts.etaMillis(maybeEtaMillis.get());
}
queue.add(opts);
cloudTasksUtils.enqueue(
RDE_REPORT_QUEUE,
CloudTasksUtils.createPostTask(
RdeStagingAction.PATH, Service.BACKEND.toString(), paramsBuilder.build()));
}
}
@@ -15,12 +15,14 @@
package google.registry.tools;
import com.beust.jcommander.Parameters;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.common.DatabaseMigrationStateSchedule;
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationStateTransition;
import google.registry.model.common.TimedTransitionProperty;
/** A command to check the current Registry 3.0 migration state of the database. */
@DeleteAfterMigration
@Parameters(separators = " =", commandDescription = "Check current Registry 3.0 migration state")
public class GetDatabaseMigrationStateCommand implements CommandWithRemoteApi {
@@ -55,7 +55,7 @@ abstract class GetEppResourceCommand implements CommandWithRemoteApi {
? String.format(
"%s\n\nWebsafe key: %s",
expand ? resource.get().toHydratedString() : resource.get(),
resource.get().createVKey().getOfyKey().getString())
resource.get().createVKey().stringify())
: String.format("%s '%s' does not exist or is deleted\n", resourceType, uniqueId));
}
@@ -20,12 +20,12 @@ import static google.registry.model.ofy.ObjectifyService.auditedOfy;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import google.registry.model.EppResource;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.persistence.VKey;
import java.util.List;
/**
* Command to get info on a Datastore resource by websafe key.
*/
/** Command to get info on a Datastore resource by websafe key. */
@DeleteAfterMigration
@Parameters(separators = " =", commandDescription = "Fetch a Datastore resource by websafe key")
final class GetResourceByKeyCommand implements CommandWithRemoteApi {
@@ -19,11 +19,13 @@ import static java.nio.charset.StandardCharsets.UTF_8;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import google.registry.model.SchemaVersion;
import google.registry.model.annotations.DeleteAfterMigration;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
/** Generates the schema file used for model versioning. */
@DeleteAfterMigration
@Parameters(commandDescription = "Generate a model schema file")
final class GetSchemaCommand implements Command {
@@ -29,6 +29,7 @@ import com.googlecode.objectify.annotation.Entity;
import com.googlecode.objectify.annotation.EntitySubclass;
import com.googlecode.objectify.annotation.Parent;
import google.registry.model.BackupGroupRoot;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.annotations.NotBackedUp;
import google.registry.model.annotations.VirtualEntity;
import java.io.Serializable;
@@ -40,6 +41,7 @@ import java.util.Map;
import java.util.Set;
/** Visualizes the schema parentage tree. */
@DeleteAfterMigration
@Parameters(commandDescription = "Generate a model schema file")
final class GetSchemaTreeCommand implements Command {
@@ -22,6 +22,7 @@ import com.google.common.base.Ascii;
import com.google.common.collect.ImmutableList;
import google.registry.export.datastore.DatastoreAdmin;
import google.registry.export.datastore.Operation;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.List;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
@@ -35,6 +36,7 @@ import org.joda.time.Duration;
* href="http://playbooks/domain_registry/procedures/backup-restore-testing.md">the playbook</a> for
* the entire process.
*/
@DeleteAfterMigration
@Parameters(separators = " =", commandDescription = "Imports a backup of the Datastore.")
public class ImportDatastoreCommand extends ConfirmingCommand {
@@ -20,6 +20,7 @@ import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import google.registry.export.datastore.DatastoreAdmin;
import google.registry.export.datastore.DatastoreAdmin.ListOperations;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.util.Clock;
import java.util.Optional;
import javax.annotation.Nullable;
@@ -28,6 +29,7 @@ import org.joda.time.DateTime;
import org.joda.time.Duration;
/** Command that lists Datastore operations. */
@DeleteAfterMigration
@Parameters(separators = " =", commandDescription = "List Datastore operations.")
public class ListDatastoreOperationsCommand implements Command {
@@ -26,12 +26,14 @@ import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
import google.registry.bigquery.BigqueryUtils.SourceFormat;
import google.registry.export.AnnotatedEntities;
import google.registry.model.annotations.DeleteAfterMigration;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/** Command to load Datastore snapshots into Bigquery. */
@DeleteAfterMigration
@Parameters(separators = " =", commandDescription = "Load Datastore snapshot into Bigquery")
final class LoadSnapshotCommand extends BigqueryCommand {
@@ -25,6 +25,7 @@ import com.google.common.io.CharStreams;
import com.google.common.io.Files;
import com.googlecode.objectify.Key;
import google.registry.model.ImmutableObject;
import google.registry.model.annotations.DeleteAfterMigration;
import google.registry.model.domain.DomainBase;
import google.registry.persistence.VKey;
import google.registry.util.NonFinalForTesting;
@@ -40,6 +41,7 @@ import java.util.List;
* <p>The key path is the value of column __key__.path of the entity's BigQuery table. Its value is
* converted from the entity's key.
*/
@DeleteAfterMigration
abstract class ReadEntityFromKeyPathCommand<T> extends MutatingCommand {
@Parameter(

Some files were not shown because too many files have changed in this diff Show More