1
0
mirror of https://github.com/google/nomulus synced 2026-07-09 01:27:09 +00:00

Compare commits

...

9 Commits

Author SHA1 Message Date
sarahcaseybot d482754f66 Implement default tokens for the fee extension in domain check flow (#1950)
* Implement default tokens for the fee extension in domain check

* Add test for expired token

* Add test for alloc token and default token

* Fix formatting

* Always check for default tokens

* Change transaction time to passed in DateTime
2023-03-17 15:41:17 -04:00
sarahcaseybot fe086b43f5 Add TTL columns to the Tld table (#1964)
* Add TTL columns to Tld table

* Change A and AAAA records column name
2023-03-17 11:54:14 -04:00
Lai Jiang 95f1bca3fb Remove Nordn pull queue code (#1966)
The SQL-based flow is verified to work on production.
2023-03-16 17:37:48 -04:00
sarahcaseybot 178a2323d9 Add allowedEppActions to AllocationToken Java classes (#1958)
* Add allowedEppActions field to AllocationToken Java class and converter

* Add getter and setter
2023-03-16 15:45:34 -04:00
Lai Jiang a44aa1378f Create a DnsRefreshRequest entity backed by the corresponding table (#1941)
Also adds a DnsUtils class to deal with adding, polling, and removing
DNS refresh requests (only adding is implemented for now). The class
also takes care of choosing which mechanism to use (pull queue vs. SQL)
based on the current time and the database migration schedule map.
2023-03-16 13:02:20 -04:00
Pavlo Tkach d0f625f70e angular version update 15.1.0 -> 15.2.2 (#1967) 2023-03-16 11:56:38 -04:00
gbrodman fb59874234 Allow for multiple service accounts in authentication (#1963)
When submitting tasks to Cloud Tasks, we will use the built-in OIDC
authentication which runs under the default service account (not the
cloud scheduler service account). We want either to work for app-level
auth.
2023-03-15 10:20:58 -04:00
gbrodman b6083e227f Move CloudTasksUtils to core/ project (#1956)
This does nothing for now, but in the future this will allow us to refer
to the RegistryConfig and/or Service objects from the core project. This
will be necessary when changing CloudTasksUtils to not use the AppEngine
built-in connection (it will need to use a standard HTTP request
instead).
2023-03-14 15:15:05 -04:00
Lai Jiang 5805b6859e Rename process_time column in DnsRefreshRequest (#1962)
Make it explicit that this is the last process time, not a scheduled
future process time.
2023-03-14 14:03:12 -04:00
99 changed files with 6737 additions and 5309 deletions
+2165 -1713
View File
File diff suppressed because it is too large Load Diff
+13 -13
View File
@@ -13,24 +13,24 @@
},
"private": true,
"dependencies": {
"@angular/animations": "^15.1.0",
"@angular/cdk": "^15.0.4",
"@angular/common": "^15.1.0",
"@angular/compiler": "^15.1.0",
"@angular/core": "^15.1.0",
"@angular/forms": "^15.1.0",
"@angular/material": "^15.0.4",
"@angular/platform-browser": "^15.1.0",
"@angular/platform-browser-dynamic": "^15.1.0",
"@angular/router": "^15.1.0",
"@angular/animations": "^15.2.2",
"@angular/cdk": "^15.2.2",
"@angular/common": "^15.2.2",
"@angular/compiler": "^15.2.2",
"@angular/core": "^15.2.2",
"@angular/forms": "^15.2.2",
"@angular/material": "^15.2.2",
"@angular/platform-browser": "^15.2.2",
"@angular/platform-browser-dynamic": "^15.2.2",
"@angular/router": "^15.2.2",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "^15.1.0",
"@angular/cli": "~15.1.0",
"@angular/compiler-cli": "^15.1.0",
"@angular-devkit/build-angular": "^15.2.4",
"@angular/cli": "~15.2.4",
"@angular/compiler-cli": "^15.2.2",
"@types/jasmine": "~4.0.0",
"@types/node": "^18.11.18",
"concurrently": "^7.6.0",
@@ -25,7 +25,6 @@ import com.google.common.flogger.FluentLogger;
import google.registry.model.EppResource;
import google.registry.persistence.VKey;
import google.registry.request.Action.Service;
import google.registry.util.CloudTasksUtils;
import javax.inject.Inject;
import org.joda.time.DateTime;
import org.joda.time.Duration;
@@ -86,6 +85,6 @@ public final class AsyncTaskEnqueuer {
cloudTasksUtils.enqueue(
QUEUE_ASYNC_ACTIONS,
cloudTasksUtils.createPostTaskWithDelay(
ResaveEntityAction.PATH, Service.BACKEND.toString(), params, etaDuration));
ResaveEntityAction.PATH, Service.BACKEND, params, etaDuration));
}
}
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.util;
package google.registry.batch;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
@@ -36,12 +36,18 @@ import com.google.common.net.MediaType;
import com.google.common.net.UrlEscapers;
import com.google.protobuf.ByteString;
import com.google.protobuf.util.Timestamps;
import google.registry.config.RegistryConfig.Config;
import google.registry.request.Action.Service;
import google.registry.util.Clock;
import google.registry.util.CollectionUtils;
import google.registry.util.Retrier;
import java.io.Serializable;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Optional;
import java.util.Random;
import java.util.function.Supplier;
import javax.inject.Inject;
import org.joda.time.Duration;
/** Utilities for dealing with Cloud Tasks. */
@@ -57,11 +63,12 @@ public class CloudTasksUtils implements Serializable {
private final String locationId;
private final SerializableCloudTasksClient client;
@Inject
public CloudTasksUtils(
Retrier retrier,
Clock clock,
String projectId,
String locationId,
@Config("projectId") String projectId,
@Config("locationId") String locationId,
SerializableCloudTasksClient client) {
this.retrier = retrier;
this.clock = clock;
@@ -108,7 +115,7 @@ public class CloudTasksUtils implements Serializable {
* the worker service</a>
*/
private Task createTask(
String path, HttpMethod method, String service, Multimap<String, String> params) {
String path, HttpMethod method, Service service, Multimap<String, String> params) {
checkArgument(
path != null && !path.isEmpty() && path.charAt(0) == '/',
"The path must start with a '/'.");
@@ -119,7 +126,8 @@ public class CloudTasksUtils implements Serializable {
AppEngineHttpRequest.Builder requestBuilder =
AppEngineHttpRequest.newBuilder()
.setHttpMethod(method)
.setAppEngineRouting(AppEngineRouting.newBuilder().setService(service).build());
.setAppEngineRouting(
AppEngineRouting.newBuilder().setService(service.toString()).build());
if (!CollectionUtils.isNullOrEmpty(params)) {
Escaper escaper = UrlEscapers.urlPathSegmentEscaper();
@@ -165,7 +173,7 @@ public class CloudTasksUtils implements Serializable {
private Task createTaskWithJitter(
String path,
HttpMethod method,
String service,
Service service,
Multimap<String, String> params,
Optional<Integer> jitterSeconds) {
if (!jitterSeconds.isPresent() || jitterSeconds.get() <= 0) {
@@ -199,7 +207,7 @@ public class CloudTasksUtils implements Serializable {
private Task createTaskWithDelay(
String path,
HttpMethod method,
String service,
Service service,
Multimap<String, String> params,
Duration delay) {
if (delay.isEqual(Duration.ZERO)) {
@@ -211,11 +219,11 @@ public class CloudTasksUtils implements Serializable {
.build();
}
public Task createPostTask(String path, String service, Multimap<String, String> params) {
public Task createPostTask(String path, Service service, Multimap<String, String> params) {
return createTask(path, HttpMethod.POST, service, params);
}
public Task createGetTask(String path, String service, Multimap<String, String> params) {
public Task createGetTask(String path, Service service, Multimap<String, String> params) {
return createTask(path, HttpMethod.GET, service, params);
}
@@ -224,7 +232,7 @@ public class CloudTasksUtils implements Serializable {
*/
public Task createPostTaskWithJitter(
String path,
String service,
Service service,
Multimap<String, String> params,
Optional<Integer> jitterSeconds) {
return createTaskWithJitter(path, HttpMethod.POST, service, params, jitterSeconds);
@@ -235,7 +243,7 @@ public class CloudTasksUtils implements Serializable {
*/
public Task createGetTaskWithJitter(
String path,
String service,
Service service,
Multimap<String, String> params,
Optional<Integer> jitterSeconds) {
return createTaskWithJitter(path, HttpMethod.GET, service, params, jitterSeconds);
@@ -243,13 +251,13 @@ public class CloudTasksUtils implements Serializable {
/** Create a {@link Task} via HTTP.POST that will be delayed for {@code delay}. */
public Task createPostTaskWithDelay(
String path, String service, Multimap<String, String> params, Duration delay) {
String path, Service service, Multimap<String, String> params, Duration delay) {
return createTaskWithDelay(path, HttpMethod.POST, service, params, delay);
}
/** Create a {@link Task} via HTTP.GET that will be delayed for {@code delay}. */
public Task createGetTaskWithDelay(
String path, String service, Multimap<String, String> params, Duration delay) {
String path, Service service, Multimap<String, String> params, Duration delay) {
return createTaskWithDelay(path, HttpMethod.GET, service, params, delay);
}
@@ -32,7 +32,7 @@ import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import google.registry.config.RegistryConfig.Config;
import google.registry.config.RegistryEnvironment;
import google.registry.dns.DnsQueue;
import google.registry.dns.DnsUtils;
import google.registry.model.CreateAutoTimestamp;
import google.registry.model.EppResourceUtils;
import google.registry.model.domain.Domain;
@@ -98,7 +98,7 @@ public class DeleteProberDataAction implements Runnable {
/** Number of domains to retrieve and delete per SQL transaction. */
private static final int BATCH_SIZE = 1000;
@Inject DnsQueue dnsQueue;
@Inject DnsUtils dnsUtils;
@Inject
@Parameter(PARAM_DRY_RUN)
@@ -264,6 +264,6 @@ public class DeleteProberDataAction implements Runnable {
// messages, or auto-renews because those will all be hard-deleted the next time the job runs
// anyway.
tm().putAll(ImmutableList.of(deletedDomain, historyEntry));
dnsQueue.addDomainRefreshTask(deletedDomain.getDomainName());
dnsUtils.requestDomainDnsRefresh(deletedDomain.getDomainName());
}
}
@@ -26,6 +26,7 @@ import com.google.auto.value.AutoValue;
import com.google.cloud.storage.BlobId;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.flogger.FluentLogger;
import google.registry.batch.CloudTasksUtils;
import google.registry.gcs.GcsUtils;
import google.registry.keyring.api.PgpHelper;
import google.registry.model.common.Cursor;
@@ -46,7 +47,6 @@ import google.registry.rde.RdeUtil;
import google.registry.request.Action.Service;
import google.registry.request.RequestParameters;
import google.registry.tldconfig.idn.IdnTableEnum;
import google.registry.util.CloudTasksUtils;
import google.registry.xjc.rdeheader.XjcRdeHeader;
import google.registry.xjc.rdeheader.XjcRdeHeaderElement;
import google.registry.xml.ValidationMode;
@@ -306,7 +306,7 @@ public class RdeIO {
RDE_UPLOAD_QUEUE,
cloudTasksUtils.createPostTaskWithDelay(
RdeUploadAction.PATH,
Service.BACKEND.getServiceId(),
Service.BACKEND,
ImmutableMultimap.of(
RequestParameters.PARAM_TLD,
key.tld(),
@@ -318,7 +318,7 @@ public class RdeIO {
BRDA_QUEUE,
cloudTasksUtils.createPostTaskWithDelay(
BrdaCopyAction.PATH,
Service.BACKEND.getServiceId(),
Service.BACKEND,
ImmutableMultimap.of(
RequestParameters.PARAM_TLD,
key.tld(),
@@ -38,6 +38,7 @@ import com.google.common.flogger.FluentLogger;
import com.google.common.io.BaseEncoding;
import dagger.BindsInstance;
import dagger.Component;
import google.registry.batch.CloudTasksUtils;
import google.registry.beam.common.RegistryJpaIO;
import google.registry.beam.common.RegistryPipelineOptions;
import google.registry.config.CloudTasksUtilsModule;
@@ -62,7 +63,6 @@ import google.registry.rde.DepositFragment;
import google.registry.rde.PendingDeposit;
import google.registry.rde.PendingDeposit.PendingDepositCoder;
import google.registry.rde.RdeMarshaller;
import google.registry.util.CloudTasksUtils;
import google.registry.util.UtilsModule;
import google.registry.xml.ValidationMode;
import java.io.ByteArrayInputStream;
@@ -19,18 +19,15 @@ import com.google.cloud.tasks.v2.CloudTasksClient;
import com.google.cloud.tasks.v2.CloudTasksSettings;
import dagger.Module;
import dagger.Provides;
import google.registry.batch.CloudTasksUtils;
import google.registry.batch.CloudTasksUtils.GcpCloudTasksClient;
import google.registry.batch.CloudTasksUtils.SerializableCloudTasksClient;
import google.registry.config.CredentialModule.DefaultCredential;
import google.registry.config.RegistryConfig.Config;
import google.registry.util.Clock;
import google.registry.util.CloudTasksUtils;
import google.registry.util.CloudTasksUtils.GcpCloudTasksClient;
import google.registry.util.CloudTasksUtils.SerializableCloudTasksClient;
import google.registry.util.GoogleCredentialsBundle;
import google.registry.util.Retrier;
import java.io.IOException;
import java.io.Serializable;
import java.util.function.Supplier;
import javax.inject.Singleton;
/**
* A {@link Module} that provides {@link CloudTasksUtils}.
@@ -41,17 +38,6 @@ import javax.inject.Singleton;
@Module
public abstract class CloudTasksUtilsModule {
@Singleton
@Provides
public static CloudTasksUtils provideCloudTasksUtils(
@Config("projectId") String projectId,
@Config("locationId") String locationId,
SerializableCloudTasksClient client,
Retrier retrier,
Clock clock) {
return new CloudTasksUtils(retrier, clock, projectId, locationId, client);
}
// Provides a supplier instead of using a Dagger @Provider because the latter is not serializable.
@Provides
public static Supplier<CloudTasksClient> provideCloudTasksClientSupplier(
@@ -107,9 +107,9 @@ public final class RegistryConfig {
}
@Provides
@Config("cloudSchedulerServiceAccountEmail")
public static String provideCloudSchedulerServiceAccountEmail(RegistryConfigSettings config) {
return config.gcpProject.cloudSchedulerServiceAccountEmail;
@Config("serviceAccountEmails")
public static ImmutableList<String> provideServiceAccountEmails(RegistryConfigSettings config) {
return ImmutableList.copyOf(config.gcpProject.serviceAccountEmails);
}
@Provides
@@ -930,7 +930,7 @@ public final class RegistryConfig {
* <p>Note that this uses {@code @Named} instead of {@code @Config} so that it can be used from
* the low-level util package, which cannot have a dependency on the config package.
*
* @see google.registry.util.CloudTasksUtils
* @see google.registry.batch.CloudTasksUtils
*/
@Provides
@Named("transientFailureRetries")
@@ -54,7 +54,7 @@ public class RegistryConfigSettings {
public String backendServiceUrl;
public String toolsServiceUrl;
public String pubapiServiceUrl;
public String cloudSchedulerServiceAccountEmail;
public List<String> serviceAccountEmails;
}
/** Configuration options for OAuth settings for authenticating users. */
@@ -22,8 +22,11 @@ gcpProject:
backendServiceUrl: https://localhost
toolsServiceUrl: https://localhost
pubapiServiceUrl: https://localhost
# Service account used by Cloud Scheduler to send authenticated requests.
cloudSchedulerServiceAccountEmail: cloud-scheduler-email@email.com
# Service accounts eligible for authorization (e.g. default service account,
# account used by Cloud Scheduler) to send authenticated requests.
serviceAccountEmails:
- default-service-account-email@email.com
- cloud-scheduler-email@email.com
gSuite:
# Publicly accessible domain name of the running G Suite instance.
@@ -38,6 +38,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Multimap;
import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import google.registry.batch.CloudTasksUtils;
import google.registry.request.Action;
import google.registry.request.Action.Service;
import google.registry.request.Parameter;
@@ -45,7 +46,6 @@ import google.registry.request.ParameterMap;
import google.registry.request.RequestParameters;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.CloudTasksUtils;
import java.util.Optional;
import java.util.stream.Stream;
import javax.inject.Inject;
@@ -158,6 +158,6 @@ public final class TldFanoutAction implements Runnable {
params.put(RequestParameters.PARAM_TLD, tld);
}
return cloudTasksUtils.createPostTaskWithJitter(
endpoint, Service.BACKEND.toString(), params, jitterSeconds);
endpoint, Service.BACKEND, params, jitterSeconds);
}
}
@@ -34,5 +34,8 @@ public class DnsConstants {
public static final String DNS_TARGET_CREATE_TIME_PARAM = "Create-Time";
/** The possible values of the {@code DNS_TARGET_TYPE_PARAM} parameter. */
public enum TargetType { DOMAIN, HOST, ZONE }
public enum TargetType {
DOMAIN,
HOST
}
}
@@ -77,11 +77,15 @@ public class DnsQueue {
private static final RateLimiter rateLimiter = RateLimiter.create(9);
@Inject
public DnsQueue(@Named(DNS_PULL_QUEUE_NAME) Queue queue, Clock clock) {
DnsQueue(@Named(DNS_PULL_QUEUE_NAME) Queue queue, Clock clock) {
this.queue = queue;
this.clock = clock;
}
Clock getClock() {
return clock;
}
@VisibleForTesting
public static DnsQueue createForTesting(Clock clock) {
return new DnsQueue(getQueue(DNS_PULL_QUEUE_NAME), clock);
@@ -108,7 +112,7 @@ public class DnsQueue {
}
/** Adds a task to the queue to refresh the DNS information for the specified subordinate host. */
public TaskHandle addHostRefreshTask(String hostName) {
TaskHandle addHostRefreshTask(String hostName) {
Optional<InternetDomainName> tld = Registries.findTldForName(InternetDomainName.from(hostName));
checkArgument(
tld.isPresent(), String.format("%s is not a subordinate host to a known tld", hostName));
@@ -116,12 +120,12 @@ public class DnsQueue {
}
/** Enqueues a task to refresh DNS for the specified domain now. */
public TaskHandle addDomainRefreshTask(String domainName) {
TaskHandle addDomainRefreshTask(String domainName) {
return addDomainRefreshTask(domainName, Duration.ZERO);
}
/** Enqueues a task to refresh DNS for the specified domain at some point in the future. */
public TaskHandle addDomainRefreshTask(String domainName, Duration countdown) {
TaskHandle addDomainRefreshTask(String domainName, Duration countdown) {
return addToQueue(
TargetType.DOMAIN,
domainName,
@@ -129,11 +133,6 @@ public class DnsQueue {
countdown);
}
/** Adds a task to the queue to refresh the DNS information for the specified zone. */
public TaskHandle addZoneRefreshTask(String zoneName) {
return addToQueue(TargetType.ZONE, zoneName, zoneName, Duration.ZERO);
}
/**
* Returns the maximum number of tasks that can be leased with {@link #leaseTasks}.
*
@@ -0,0 +1,74 @@
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.dns;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.common.net.InternetDomainName;
import google.registry.dns.DnsConstants.TargetType;
import google.registry.model.common.DatabaseMigrationStateSchedule;
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
import google.registry.model.common.DnsRefreshRequest;
import google.registry.model.tld.Registries;
import javax.inject.Inject;
import org.joda.time.Duration;
/** Utility class to handle DNS refresh requests. */
// TODO: Make this a static util function once we are done with the DNS pull queue migration.
public class DnsUtils {
private final DnsQueue dnsQueue;
@Inject
DnsUtils(DnsQueue dnsQueue) {
this.dnsQueue = dnsQueue;
}
private void requestDnsRefresh(String name, TargetType type, Duration delay) {
// Throws an IllegalArgumentException if the name is not under a managed TLD -- we only update
// DNS for names that are under our management.
String tld = Registries.findTldForNameOrThrow(InternetDomainName.from(name)).toString();
if (usePullQueue()) {
if (TargetType.HOST.equals(type)) {
dnsQueue.addHostRefreshTask(name);
} else {
dnsQueue.addDomainRefreshTask(name, delay);
}
} else {
tm().transact(
() ->
tm().insert(
new DnsRefreshRequest(
type, name, tld, tm().getTransactionTime().plus(delay))));
}
}
public void requestDomainDnsRefresh(String domainName, Duration delay) {
requestDnsRefresh(domainName, TargetType.DOMAIN, delay);
}
public void requestDomainDnsRefresh(String domainName) {
requestDomainDnsRefresh(domainName, Duration.ZERO);
}
public void requestHostDnsRefresh(String hostName) {
requestDnsRefresh(hostName, TargetType.HOST, Duration.ZERO);
}
private boolean usePullQueue() {
return !DatabaseMigrationStateSchedule.getValueAtTime(dnsQueue.getClock().nowUtc())
.equals(MigrationState.DNS_SQL);
}
}
@@ -35,6 +35,7 @@ import com.google.common.collect.ImmutableMultimap;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.InternetDomainName;
import dagger.Lazy;
import google.registry.batch.CloudTasksUtils;
import google.registry.config.RegistryConfig.Config;
import google.registry.dns.DnsMetrics.ActionStatus;
import google.registry.dns.DnsMetrics.CommitStatus;
@@ -54,7 +55,6 @@ import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.request.lock.LockHandler;
import google.registry.util.Clock;
import google.registry.util.CloudTasksUtils;
import google.registry.util.DomainNameUtils;
import google.registry.util.EmailMessage;
import google.registry.util.SendEmailService;
@@ -85,7 +85,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final DnsQueue dnsQueue;
private final DnsUtils dnsUtils;
private final DnsWriterProxy dnsWriterProxy;
private final DnsMetrics dnsMetrics;
private final Duration timeout;
@@ -139,7 +139,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
@Config("gSuiteOutgoingEmailAddress") InternetAddress gSuiteOutgoingEmailAddress,
@Header(APP_ENGINE_RETRY_HEADER) Optional<Integer> appEngineRetryCount,
@Header(CLOUD_TASKS_RETRY_HEADER) Optional<Integer> cloudTasksRetryCount,
DnsQueue dnsQueue,
DnsUtils dnsUtils,
DnsWriterProxy dnsWriterProxy,
DnsMetrics dnsMetrics,
LockHandler lockHandler,
@@ -147,7 +147,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
CloudTasksUtils cloudTasksUtils,
SendEmailService sendEmailService,
Response response) {
this.dnsQueue = dnsQueue;
this.dnsUtils = dnsUtils;
this.dnsWriterProxy = dnsWriterProxy;
this.dnsMetrics = dnsMetrics;
this.timeout = timeout;
@@ -339,7 +339,7 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
DNS_PUBLISH_PUSH_QUEUE_NAME,
cloudTasksUtils.createPostTask(
PATH,
Service.BACKEND.toString(),
Service.BACKEND,
ImmutableMultimap.<String, String>builder()
.put(PARAM_TLD, tld)
.put(PARAM_DNS_WRITER, dnsWriter)
@@ -356,10 +356,10 @@ public final class PublishDnsUpdatesAction implements Runnable, Callable<Void> {
private void requeueBatch() {
logger.atInfo().log("Requeueing batch for retry.");
for (String domain : nullToEmpty(domains)) {
dnsQueue.addDomainRefreshTask(domain);
dnsUtils.requestDomainDnsRefresh(domain);
}
for (String host : nullToEmpty(hosts)) {
dnsQueue.addHostRefreshTask(host);
dnsUtils.requestHostDnsRefresh(host);
}
}
@@ -44,6 +44,7 @@ import com.google.common.collect.Ordering;
import com.google.common.flogger.FluentLogger;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
import google.registry.batch.CloudTasksUtils;
import google.registry.config.RegistryConfig.Config;
import google.registry.dns.DnsConstants.TargetType;
import google.registry.model.tld.Registries;
@@ -53,7 +54,6 @@ import google.registry.request.Action.Service;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import google.registry.util.CloudTasksUtils;
import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.Comparator;
@@ -372,7 +372,7 @@ public final class ReadDnsQueueAction implements Runnable {
Task task =
cloudTasksUtils.createPostTaskWithJitter(
PublishDnsUpdatesAction.PATH,
Service.BACKEND.toString(),
Service.BACKEND,
ImmutableMultimap.<String, String>builder()
.put(PARAM_TLD, tld)
.put(PARAM_DNS_WRITER, dnsWriter)
@@ -39,7 +39,7 @@ import javax.inject.Inject;
public final class RefreshDnsAction implements Runnable {
private final Clock clock;
private final DnsQueue dnsQueue;
private final DnsUtils dnsUtils;
private final String domainOrHostName;
private final TargetType type;
@@ -48,11 +48,11 @@ public final class RefreshDnsAction implements Runnable {
@Parameter("domainOrHostName") String domainOrHostName,
@Parameter("type") TargetType type,
Clock clock,
DnsQueue dnsQueue) {
DnsUtils dnsUtils) {
this.domainOrHostName = domainOrHostName;
this.type = type;
this.clock = clock;
this.dnsQueue = dnsQueue;
this.dnsUtils = dnsUtils;
}
@Override
@@ -63,11 +63,11 @@ public final class RefreshDnsAction implements Runnable {
switch (type) {
case DOMAIN:
loadAndVerifyExistence(Domain.class, domainOrHostName);
dnsQueue.addDomainRefreshTask(domainOrHostName);
dnsUtils.requestDomainDnsRefresh(domainOrHostName);
break;
case HOST:
verifyHostIsSubordinate(loadAndVerifyExistence(Host.class, domainOrHostName));
dnsQueue.addHostRefreshTask(domainOrHostName);
dnsUtils.requestHostDnsRefresh(domainOrHostName);
break;
default:
throw new BadRequestException("Unsupported type: " + type);
@@ -45,14 +45,14 @@ public class RefreshDnsOnHostRenameAction implements Runnable {
private final VKey<Host> hostKey;
private final Response response;
private final DnsQueue dnsQueue;
private final DnsUtils dnsUtils;
@Inject
RefreshDnsOnHostRenameAction(
@Parameter(PARAM_HOST_KEY) String hostKey, Response response, DnsQueue dnsQueue) {
@Parameter(PARAM_HOST_KEY) String hostKey, Response response, DnsUtils dnsUtils) {
this.hostKey = VKey.createEppVKeyFromString(hostKey);
this.response = response;
this.dnsQueue = dnsQueue;
this.dnsUtils = dnsUtils;
}
@Override
@@ -76,7 +76,7 @@ public class RefreshDnsOnHostRenameAction implements Runnable {
.stream()
.map(domainKey -> tm().loadByKey(domainKey))
.filter(Domain::shouldPublishToDns)
.forEach(domain -> dnsQueue.addDomainRefreshTask(domain.getDomainName()));
.forEach(domain -> dnsUtils.requestDomainDnsRefresh(domain.getDomainName()));
}
if (!hostValid) {
@@ -6,6 +6,7 @@
<mode>pull</mode>
</queue>
<!-- Queue for publishing DNS updates in batches. -->
<queue>
<name>dns-publish</name>
<rate>100/s</rate>
@@ -18,6 +19,7 @@
</retry-parameters>
</queue>
<!-- Queue for uploading RDE deposits to the escrow provider. -->
<queue>
<name>rde-upload</name>
<rate>10/m</rate>
@@ -28,6 +30,7 @@
</retry-parameters>
</queue>
<!-- Queue for uploading RDE reports to ICANN. -->
<queue>
<name>rde-report</name>
<rate>1/s</rate>
@@ -37,6 +40,7 @@
</retry-parameters>
</queue>
<!-- Queue for copying BRDA deposits to GCS. -->
<queue>
<name>brda</name>
<rate>1/m</rate>
@@ -74,7 +78,7 @@
</retry-parameters>
</queue>
<!-- Queue for tasks to produce LORDN CSV reports, either by the query or queue method. -->
<!-- Queue for tasks to produce LORDN CSV reports, populated by a Cloud Scheduler fanout job. -->
<queue>
<name>nordn</name>
<rate>1/s</rate>
@@ -84,18 +88,6 @@
</retry-parameters>
</queue>
<!-- Queue for LORDN Claims CSV rows to be periodically queried and then uploaded in batches. -->
<queue>
<name>lordn-claims</name>
<mode>pull</mode>
</queue>
<!-- Queue for LORDN Sunrise CSV rows to be periodically queried and then uploaded in batches. -->
<queue>
<name>lordn-sunrise</name>
<mode>pull</mode>
</queue>
<!-- Queue for tasks that sync data to Google Spreadsheets. -->
<queue>
<name>sheet</name>
@@ -173,30 +173,6 @@
<schedule>0 */12 * * *</schedule>
</task>
<task>
<url><![CDATA[/_dr/cron/fanout?queue=nordn&endpoint=/_dr/task/nordnUpload&forEachRealTld&lordnPhase=sunrise&pullQueue]]></url>
<name>nordnUploadSunrisePullQueue</name>
<description>
This job uploads LORDN Sunrise CSV files for each TLD to MarksDB using
pull queue. It should be run at most every three hours, or at absolute
minimum every 26 hours.
</description>
<!-- This may be set anywhere between "every 3 hours" and "every 25 hours". -->
<schedule>0 */12 * * *</schedule>
</task>
<task>
<url><![CDATA[/_dr/cron/fanout?queue=nordn&endpoint=/_dr/task/nordnUpload&forEachRealTld&lordnPhase=claims&pullQueue]]></url>
<name>nordnUploadClaimsPullQueue</name>
<description>
This job uploads LORDN Claims CSV files for each TLD to MarksDB using pull
queue. It should be run at most every three hours, or at absolute minimum
every 26 hours.
</description>
<!-- This may be set anywhere between "every 3 hours" and "every 25 hours". -->
<schedule>0 */12 * * *</schedule>
</task>
<task>
<url><![CDATA[/_dr/cron/fanout?queue=retryable-cron-tasks&endpoint=/_dr/task/deleteProberData&runInEmpty]]></url>
<name>deleteProberData</name>
@@ -38,6 +38,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Maps;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.InternetDomainName;
import google.registry.config.RegistryConfig.Config;
import google.registry.flows.EppException;
@@ -116,6 +117,7 @@ import org.joda.time.DateTime;
@ReportingSpec(ActivityReportField.DOMAIN_CHECK)
public final class DomainCheckFlow implements Flow {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@Inject ResourceCommand resourceCommand;
@Inject ExtensionManager extensionManager;
@Inject EppInput eppInput;
@@ -271,6 +273,12 @@ public final class DomainCheckFlow implements Flow {
for (FeeCheckCommandExtensionItem feeCheckItem : feeCheck.getItems()) {
for (String domainName : getDomainNamesToCheckForFee(feeCheckItem, domainNames.keySet())) {
Optional<AllocationToken> defaultToken =
DomainFlowUtils.checkForDefaultToken(
Registry.get(InternetDomainName.from(domainName).parent().toString()),
domainName,
registrarId,
now);
FeeCheckResponseExtensionItem.Builder<?> builder = feeCheckItem.createResponseBuilder();
Optional<Domain> domain = Optional.ofNullable(domainObjs.get(domainName));
handleFeeRequest(
@@ -281,7 +289,7 @@ public final class DomainCheckFlow implements Flow {
feeCheck.getCurrency(),
now,
pricingLogic,
allocationToken,
allocationToken.isPresent() ? allocationToken : defaultToken,
availableDomains.contains(domainName),
recurrences.getOrDefault(domainName, null));
responseItems.add(builder.setDomainNameIfSupported(domainName).build());
@@ -15,8 +15,6 @@
package google.registry.flows.domain;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static google.registry.flows.FlowUtils.persistEntityChanges;
import static google.registry.flows.FlowUtils.validateRegistrarIsLoggedIn;
@@ -54,7 +52,6 @@ import static google.registry.model.tld.Registry.TldState.QUIET_PERIOD;
import static google.registry.model.tld.Registry.TldState.START_DATE_SUNRISE;
import static google.registry.model.tld.label.ReservationType.NAME_COLLISION;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.util.CollectionUtils.isNullOrEmpty;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.leapSafeAddYears;
@@ -62,9 +59,8 @@ import com.google.auto.value.AutoValue;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.net.InternetDomainName;
import google.registry.dns.DnsQueue;
import google.registry.dns.DnsUtils;
import google.registry.flows.EppException;
import google.registry.flows.EppException.AssociationProhibitsOperationException;
import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.EppException.ParameterValuePolicyErrorException;
import google.registry.flows.ExtensionManager;
@@ -86,8 +82,6 @@ import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.billing.BillingEvent.Recurring;
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
import google.registry.model.common.DatabaseMigrationStateSchedule;
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainCommand;
import google.registry.model.domain.DomainCommand.Create;
@@ -123,10 +117,7 @@ import google.registry.model.tld.Registry.TldType;
import google.registry.model.tld.label.ReservationType;
import google.registry.model.tmch.ClaimsList;
import google.registry.model.tmch.ClaimsListDao;
import google.registry.persistence.VKey;
import google.registry.tmch.LordnTaskUtils;
import google.registry.tmch.LordnTaskUtils.LordnPhase;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nullable;
import javax.inject.Inject;
@@ -235,7 +226,8 @@ public final class DomainCreateFlow implements TransactionalFlow {
@Inject DomainCreateFlowCustomLogic flowCustomLogic;
@Inject DomainFlowTmchUtils tmchUtils;
@Inject DomainPricingLogic pricingLogic;
@Inject DnsQueue dnsQueue;
@Inject DnsUtils dnsUtils;
@Inject DomainCreateFlow() {}
@Override
@@ -282,7 +274,8 @@ public final class DomainCreateFlow implements TransactionalFlow {
eppInput.getSingleExtension(AllocationTokenExtension.class));
boolean defaultTokenUsed = false;
if (!allocationToken.isPresent() && !registry.getDefaultPromoTokens().isEmpty()) {
allocationToken = checkForDefaultToken(registry, command);
allocationToken =
DomainFlowUtils.checkForDefaultToken(registry, command.getDomainName(), registrarId, now);
if (allocationToken.isPresent()) {
defaultTokenUsed = true;
}
@@ -405,12 +398,9 @@ public final class DomainCreateFlow implements TransactionalFlow {
.addGracePeriod(
GracePeriod.forBillingEvent(GracePeriodStatus.ADD, repoId, createBillingEvent))
.setLordnPhase(
!DatabaseMigrationStateSchedule.getValueAtTime(tm().getTransactionTime())
.equals(MigrationState.NORDN_SQL)
? LordnPhase.NONE
: hasSignedMarks
? LordnPhase.SUNRISE
: hasClaimsNotice ? LordnPhase.CLAIMS : LordnPhase.NONE);
hasSignedMarks
? LordnPhase.SUNRISE
: hasClaimsNotice ? LordnPhase.CLAIMS : LordnPhase.NONE);
Domain domain = domainBuilder.build();
if (allocationToken.isPresent()
&& allocationToken.get().getTokenType().equals(TokenType.PACKAGE)) {
@@ -433,8 +423,9 @@ public final class DomainCreateFlow implements TransactionalFlow {
allocationTokenFlowUtils.redeemToken(
allocationToken.get(), domainHistory.getHistoryEntryId()));
}
enqueueTasks(domain, hasSignedMarks, hasClaimsNotice);
if (domain.shouldPublishToDns()) {
dnsUtils.requestDomainDnsRefresh(domain.getDomainName());
}
EntityChanges entityChanges =
flowCustomLogic.beforeSave(
DomainCreateFlowCustomLogic.BeforeSaveParameters.newBuilder()
@@ -458,36 +449,6 @@ public final class DomainCreateFlow implements TransactionalFlow {
.build();
}
private Optional<AllocationToken> checkForDefaultToken(
Registry registry, DomainCommand.Create command) throws EppException {
Map<VKey<AllocationToken>, Optional<AllocationToken>> tokens =
AllocationToken.getAll(registry.getDefaultPromoTokens());
ImmutableList<Optional<AllocationToken>> tokenList =
registry.getDefaultPromoTokens().stream()
.map(tokens::get)
.filter(Optional::isPresent)
.collect(toImmutableList());
checkState(
!isNullOrEmpty(tokenList),
"Failure while loading default TLD promotions from the database");
// Check if any of the tokens are valid for this domain registration
for (Optional<AllocationToken> token : tokenList) {
try {
AllocationTokenFlowUtils.validateToken(
InternetDomainName.from(command.getDomainName()),
token.get(),
registrarId,
tm().getTransactionTime());
} catch (AssociationProhibitsOperationException e) {
// Allocation token was not valid for this registration, continue to check the next token in
// the list
continue;
}
// Only use the first valid token in the list
return token;
}
return Optional.empty();
}
/**
* Verifies that signed marks are only sent during sunrise.
*
@@ -707,17 +668,6 @@ public final class DomainCreateFlow implements TransactionalFlow {
.build();
}
private void enqueueTasks(Domain newDomain, boolean hasSignedMarks, boolean hasClaimsNotice) {
if (newDomain.shouldPublishToDns()) {
dnsQueue.addDomainRefreshTask(newDomain.getDomainName());
}
if (!DatabaseMigrationStateSchedule.getValueAtTime(tm().getTransactionTime())
.equals(MigrationState.NORDN_SQL)
&& (hasClaimsNotice || hasSignedMarks)) {
LordnTaskUtils.enqueueDomainTask(newDomain);
}
}
/**
* Determines the {@link RenewalPriceBehavior} and the renewal price that needs be stored in the
* {@link Recurring} billing events.
@@ -44,7 +44,7 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Sets;
import google.registry.batch.AsyncTaskEnqueuer;
import google.registry.dns.DnsQueue;
import google.registry.dns.DnsUtils;
import google.registry.flows.EppException;
import google.registry.flows.EppException.AssociationProhibitsOperationException;
import google.registry.flows.ExtensionManager;
@@ -129,7 +129,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
@Inject @TargetId String targetId;
@Inject @Superuser boolean isSuperuser;
@Inject DomainHistory.Builder historyBuilder;
@Inject DnsQueue dnsQueue;
@Inject DnsUtils dnsUtils;
@Inject Trid trid;
@Inject AsyncTaskEnqueuer asyncTaskEnqueuer;
@Inject EppResponse.Builder responseBuilder;
@@ -260,7 +260,7 @@ public final class DomainDeleteFlow implements TransactionalFlow {
// If there's a pending transfer, the gaining client's autorenew billing
// event and poll message will already have been deleted in
// ResourceDeleteFlow since it's listed in serverApproveEntities.
dnsQueue.addDomainRefreshTask(existingDomain.getDomainName());
dnsUtils.requestDomainDnsRefresh(existingDomain.getDomainName());
entitiesToSave.add(newDomain, domainHistory);
EntityChanges entityChanges =
@@ -39,6 +39,7 @@ import static google.registry.model.tld.label.ReservationType.RESERVED_FOR_ANCHO
import static google.registry.model.tld.label.ReservationType.RESERVED_FOR_SPECIFIC_USE;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.pricing.PricingEngineProxy.isDomainPremium;
import static google.registry.util.CollectionUtils.isNullOrEmpty;
import static google.registry.util.CollectionUtils.nullToEmpty;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.isAtOrAfter;
@@ -63,6 +64,7 @@ import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import com.google.common.net.InternetDomainName;
import google.registry.flows.EppException;
import google.registry.flows.EppException.AssociationProhibitsOperationException;
import google.registry.flows.EppException.AuthorizationErrorException;
import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.EppException.ObjectDoesNotExistException;
@@ -72,6 +74,7 @@ import google.registry.flows.EppException.ParameterValueSyntaxErrorException;
import google.registry.flows.EppException.RequiredParameterMissingException;
import google.registry.flows.EppException.StatusProhibitsOperationException;
import google.registry.flows.EppException.UnimplementedOptionException;
import google.registry.flows.domain.token.AllocationTokenFlowUtils;
import google.registry.flows.exceptions.ResourceHasClientUpdateProhibitedException;
import google.registry.model.EppResource;
import google.registry.model.billing.BillingEvent;
@@ -1191,6 +1194,44 @@ public class DomainFlowUtils {
.getResultList();
}
/**
* Checks if there is a valid default token to be used for a domain create command.
*
* <p>If there is more than one valid default token for the registration, only the first valid
* token found on the TLD's default token list will be returned.
*/
public static Optional<AllocationToken> checkForDefaultToken(
Registry registry, String domainName, String registrarId, DateTime now) throws EppException {
if (isNullOrEmpty(registry.getDefaultPromoTokens())) {
return Optional.empty();
}
Map<VKey<AllocationToken>, Optional<AllocationToken>> tokens =
AllocationToken.getAll(registry.getDefaultPromoTokens());
ImmutableList<Optional<AllocationToken>> tokenList =
registry.getDefaultPromoTokens().stream()
.map(tokens::get)
.filter(Optional::isPresent)
.collect(toImmutableList());
checkState(
!isNullOrEmpty(tokenList),
"Failure while loading default TLD promotions from the database");
// Check if any of the tokens are valid for this domain registration
for (Optional<AllocationToken> token : tokenList) {
try {
AllocationTokenFlowUtils.validateToken(
InternetDomainName.from(domainName), token.get(), registrarId, now);
} catch (AssociationProhibitsOperationException | StatusProhibitsOperationException e) {
// Allocation token was not valid for this registration, continue to check the next token in
// the list
continue;
}
// Only use the first valid token in the list
return token;
}
// No valid default token found
return Optional.empty();
}
/** Resource linked to this domain does not exist. */
static class LinkedResourcesDoNotExistException extends ObjectDoesNotExistException {
public LinkedResourcesDoNotExistException(Class<?> type, ImmutableSet<String> resourceIds) {
@@ -34,7 +34,7 @@ import static google.registry.util.DateTimeUtils.END_OF_TIME;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.net.InternetDomainName;
import google.registry.dns.DnsQueue;
import google.registry.dns.DnsUtils;
import google.registry.flows.EppException;
import google.registry.flows.EppException.CommandUseErrorException;
import google.registry.flows.EppException.StatusProhibitsOperationException;
@@ -122,7 +122,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
@Inject @TargetId String targetId;
@Inject @Superuser boolean isSuperuser;
@Inject DomainHistory.Builder historyBuilder;
@Inject DnsQueue dnsQueue;
@Inject DnsUtils dnsUtils;
@Inject EppResponse.Builder responseBuilder;
@Inject DomainPricingLogic pricingLogic;
@Inject DomainRestoreRequestFlow() {}
@@ -186,7 +186,7 @@ public final class DomainRestoreRequestFlow implements TransactionalFlow {
entitiesToSave.add(newDomain, domainHistory, autorenewEvent, autorenewPollMessage);
tm().putAll(entitiesToSave.build());
tm().delete(existingDomain.getDeletePollMessage());
dnsQueue.addDomainRefreshTask(existingDomain.getDomainName());
dnsUtils.requestDomainDnsRefresh(existingDomain.getDomainName());
return responseBuilder
.setExtensions(createResponseExtensions(feesAndCredits, feeUpdate, isExpired))
.build();
@@ -49,7 +49,7 @@ import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;
import com.google.common.net.InternetDomainName;
import google.registry.dns.DnsQueue;
import google.registry.dns.DnsUtils;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.FlowModule.RegistrarId;
@@ -156,7 +156,7 @@ public final class DomainUpdateFlow implements TransactionalFlow {
@Inject @Superuser boolean isSuperuser;
@Inject Trid trid;
@Inject DomainHistory.Builder historyBuilder;
@Inject DnsQueue dnsQueue;
@Inject DnsUtils dnsUtils;
@Inject EppResponse.Builder responseBuilder;
@Inject DomainUpdateFlowCustomLogic flowCustomLogic;
@Inject DomainPricingLogic pricingLogic;
@@ -183,7 +183,7 @@ public final class DomainUpdateFlow implements TransactionalFlow {
historyBuilder.setType(DOMAIN_UPDATE).setDomain(newDomain).build();
validateNewState(newDomain);
if (requiresDnsUpdate(existingDomain, newDomain)) {
dnsQueue.addDomainRefreshTask(targetId);
dnsUtils.requestDomainDnsRefresh(targetId);
}
ImmutableSet.Builder<ImmutableObject> entitiesToSave = new ImmutableSet.Builder<>();
entitiesToSave.add(newDomain, domainHistory);
@@ -28,7 +28,7 @@ import static google.registry.util.CollectionUtils.isNullOrEmpty;
import com.google.common.collect.ImmutableSet;
import google.registry.config.RegistryConfig.Config;
import google.registry.dns.DnsQueue;
import google.registry.dns.DnsUtils;
import google.registry.flows.EppException;
import google.registry.flows.EppException.ParameterValueRangeErrorException;
import google.registry.flows.EppException.RequiredParameterMissingException;
@@ -85,7 +85,7 @@ public final class HostCreateFlow implements TransactionalFlow {
@Inject @RegistrarId String registrarId;
@Inject @TargetId String targetId;
@Inject HostHistory.Builder historyBuilder;
@Inject DnsQueue dnsQueue;
@Inject DnsUtils dnsUtils;
@Inject EppResponse.Builder responseBuilder;
@Inject
@@ -138,7 +138,7 @@ public final class HostCreateFlow implements TransactionalFlow {
.build());
// Only update DNS if this is a subordinate host. External hosts have no glue to write, so
// they are only written as NS records from the referencing domain.
dnsQueue.addHostRefreshTask(targetId);
dnsUtils.requestHostDnsRefresh(targetId);
}
tm().insertAll(entitiesToSave);
return responseBuilder.setResData(HostCreateData.create(targetId, now)).build();
@@ -24,7 +24,7 @@ import static google.registry.model.eppoutput.Result.Code.SUCCESS;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.common.collect.ImmutableSet;
import google.registry.dns.DnsQueue;
import google.registry.dns.DnsUtils;
import google.registry.flows.EppException;
import google.registry.flows.ExtensionManager;
import google.registry.flows.FlowModule.RegistrarId;
@@ -71,7 +71,7 @@ public final class HostDeleteFlow implements TransactionalFlow {
StatusValue.PENDING_DELETE,
StatusValue.SERVER_DELETE_PROHIBITED);
@Inject DnsQueue dnsQueue;
@Inject DnsUtils dnsUtils;
@Inject ExtensionManager extensionManager;
@Inject @RegistrarId String registrarId;
@Inject @TargetId String targetId;
@@ -104,7 +104,7 @@ public final class HostDeleteFlow implements TransactionalFlow {
}
Host newHost = existingHost.asBuilder().setStatusValues(null).setDeletionTime(now).build();
if (existingHost.isSubordinate()) {
dnsQueue.addHostRefreshTask(existingHost.getHostName());
dnsUtils.requestHostDnsRefresh(existingHost.getHostName());
tm().update(
tm().loadByKey(existingHost.getSuperordinateDomain())
.asBuilder()
@@ -36,7 +36,8 @@ import com.google.cloud.tasks.v2.Task;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import google.registry.batch.AsyncTaskEnqueuer;
import google.registry.dns.DnsQueue;
import google.registry.batch.CloudTasksUtils;
import google.registry.dns.DnsUtils;
import google.registry.dns.RefreshDnsOnHostRenameAction;
import google.registry.flows.EppException;
import google.registry.flows.EppException.ObjectAlreadyExistsException;
@@ -65,7 +66,6 @@ import google.registry.model.host.HostHistory;
import google.registry.model.reporting.IcannReportingTypes.ActivityReportField;
import google.registry.persistence.VKey;
import google.registry.request.Action.Service;
import google.registry.util.CloudTasksUtils;
import java.util.Objects;
import java.util.Optional;
import javax.inject.Inject;
@@ -124,7 +124,7 @@ public final class HostUpdateFlow implements TransactionalFlow {
@Inject @Superuser boolean isSuperuser;
@Inject HostHistory.Builder historyBuilder;
@Inject AsyncTaskEnqueuer asyncTaskEnqueuer;
@Inject DnsQueue dnsQueue;
@Inject DnsUtils dnsUtils;
@Inject EppResponse.Builder responseBuilder;
@Inject CloudTasksUtils cloudTasksUtils;
@@ -266,21 +266,21 @@ public final class HostUpdateFlow implements TransactionalFlow {
// Only update DNS for subordinate hosts. External hosts have no glue to write, so they
// are only written as NS records from the referencing domain.
if (existingHost.isSubordinate()) {
dnsQueue.addHostRefreshTask(existingHost.getHostName());
dnsUtils.requestHostDnsRefresh(existingHost.getHostName());
}
// In case of a rename, there are many updates we need to queue up.
if (((Update) resourceCommand).getInnerChange().getHostName() != null) {
// If the renamed host is also subordinate, then we must enqueue an update to write the new
// glue.
if (newHost.isSubordinate()) {
dnsQueue.addHostRefreshTask(newHost.getHostName());
dnsUtils.requestHostDnsRefresh(newHost.getHostName());
}
// We must also enqueue updates for all domains that use this host as their nameserver so
// that their NS records can be updated to point at the new name.
Task task =
cloudTasksUtils.createPostTask(
RefreshDnsOnHostRenameAction.PATH,
Service.BACKEND.toString(),
Service.BACKEND,
ImmutableMultimap.of(PARAM_HOST_KEY, existingHost.createVKey().stringify()));
cloudTasksUtils.enqueue(QUEUE_HOST_RENAME, task);
}
@@ -28,13 +28,13 @@ import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Iterators;
import com.google.common.flogger.FluentLogger;
import com.google.protobuf.Timestamp;
import google.registry.batch.CloudTasksUtils;
import google.registry.config.RegistryEnvironment;
import google.registry.request.Action;
import google.registry.request.Action.Service;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.security.XsrfTokenManager;
import google.registry.util.CloudTasksUtils;
import java.time.Instant;
import java.util.Arrays;
import java.util.Iterator;
@@ -337,7 +337,7 @@ public class LoadTestAction implements Runnable {
cloudTasksUtils
.createPostTask(
"/_dr/epptool",
Service.TOOLS.toString(),
Service.TOOLS,
ImmutableMultimap.of(
"clientId",
registrarId,
@@ -90,7 +90,10 @@ public class DatabaseMigrationStateSchedule extends CrossTldSingleton {
SEQUENCE_BASED_ALLOCATE_ID(PrimaryDatabase.CLOUD_SQL, false, ReplayDirection.NO_REPLAY),
/** Use SQL-based Nordn upload flow instead of the pull queue-based one. */
NORDN_SQL(PrimaryDatabase.CLOUD_SQL, false, ReplayDirection.NO_REPLAY);
NORDN_SQL(PrimaryDatabase.CLOUD_SQL, false, ReplayDirection.NO_REPLAY),
/** Use SQL-based DNS update flow instead of the pull queue-based one. */
DNS_SQL(PrimaryDatabase.CLOUD_SQL, false, ReplayDirection.NO_REPLAY);
private final PrimaryDatabase primaryDatabase;
private final boolean isReadOnly;
@@ -171,7 +174,11 @@ public class DatabaseMigrationStateSchedule extends CrossTldSingleton {
MigrationState.SQL_PRIMARY)
.putAll(MigrationState.SQL_ONLY, MigrationState.SEQUENCE_BASED_ALLOCATE_ID)
.putAll(MigrationState.SEQUENCE_BASED_ALLOCATE_ID, MigrationState.NORDN_SQL)
.putAll(MigrationState.NORDN_SQL, MigrationState.SEQUENCE_BASED_ALLOCATE_ID);
.putAll(
MigrationState.NORDN_SQL,
MigrationState.SEQUENCE_BASED_ALLOCATE_ID,
MigrationState.DNS_SQL)
.putAll(MigrationState.DNS_SQL, MigrationState.NORDN_SQL);
// In addition, we can always transition from a state to itself (useful when updating the map).
Arrays.stream(MigrationState.values()).forEach(state -> builder.put(state, state));
@@ -0,0 +1,133 @@
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.common;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import google.registry.dns.DnsConstants.TargetType;
import google.registry.dns.PublishDnsUpdatesAction;
import google.registry.model.ImmutableObject;
import javax.annotation.Nullable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Index;
import javax.persistence.Table;
import org.joda.time.DateTime;
@Entity
@Table(indexes = {@Index(columnList = "requestTime"), @Index(columnList = "lastProcessTime")})
public class DnsRefreshRequest extends ImmutableObject {
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Id
@SuppressWarnings("unused")
protected long id;
@Column(nullable = false)
@Enumerated(EnumType.STRING)
private TargetType type;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String tld;
@Column(nullable = false)
private DateTime requestTime;
@Column(nullable = false)
private DateTime lastProcessTime;
public TargetType getType() {
return type;
}
public String getName() {
return name;
}
public String getTld() {
return tld;
}
public DateTime getRequestTime() {
return requestTime;
}
/**
* The time at which the entity was last processed.
*
* <p>Note that "processed" means that it was read, not necessarily that the DNS request was
* processed successfully. The subsequent steps to bundle requests together and enqueue them in a
* Cloud Tasks queue for {@link PublishDnsUpdatesAction} to process can still fail.
*
* <p>This value allows us to control if a row is just recently read and should be skipped, should
* there are concurrent reads that all attempt to read the rows with oldest {@link #requestTime},
* or another read that comes too early after the previous read.
*/
public DateTime getLastProcessTime() {
return lastProcessTime;
}
protected DnsRefreshRequest() {}
private DnsRefreshRequest(
@Nullable Long id,
TargetType type,
String name,
String tld,
DateTime requestTime,
DateTime lastProcessTime) {
checkNotNull(type, "Target type cannot be null");
checkNotNull(name, "Domain/host name cannot be null");
checkNotNull(tld, "TLD cannot be null");
checkNotNull(requestTime, "Request time cannot be null");
checkNotNull(lastProcessTime, "Last process time cannot be null");
if (id != null) {
this.id = id;
}
this.type = type;
this.name = name;
this.tld = tld;
this.requestTime = requestTime;
this.lastProcessTime = lastProcessTime;
}
public DnsRefreshRequest(TargetType type, String name, String tld, DateTime requestTime) {
this(null, type, name, tld, requestTime, START_OF_TIME);
}
public DnsRefreshRequest updateProcessTime(DateTime processTime) {
checkArgument(
processTime.isAfter(getRequestTime()),
"Process time %s must be later than request time %s",
processTime,
getRequestTime());
checkArgument(
processTime.isAfter(getLastProcessTime()),
"New process time %s must be later than the old one %s",
processTime,
getLastProcessTime());
return new DnsRefreshRequest(id, getType(), getName(), getTld(), getRequestTime(), processTime);
}
}
@@ -45,6 +45,7 @@ import google.registry.model.CreateAutoTimestamp;
import google.registry.model.UpdateAutoTimestampEntity;
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
import google.registry.model.common.TimedTransitionProperty;
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName;
import google.registry.model.reporting.HistoryEntry.HistoryEntryId;
import google.registry.persistence.VKey;
import google.registry.persistence.WithVKey;
@@ -213,6 +214,9 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
TimedTransitionProperty<TokenStatus> tokenStatusTransitions =
TimedTransitionProperty.withInitialValue(NOT_STARTED);
/** Allowed EPP actions for this token, or null if all actions are allowed. */
@Nullable Set<CommandName> allowedEppActions;
public String getToken() {
return token;
}
@@ -263,6 +267,10 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
return tokenStatusTransitions;
}
public ImmutableSet<CommandName> getAllowedEppActions() {
return nullToEmptyImmutableCopy(allowedEppActions);
}
public RenewalPriceBehavior getRenewalPriceBehavior() {
return renewalPriceBehavior;
}
@@ -450,6 +458,11 @@ public class AllocationToken extends UpdateAutoTimestampEntity implements Builda
return this;
}
public Builder setAllowedEppActions(Set<CommandName> allowedEppActions) {
getInstance().allowedEppActions = forceEmptyToNull(allowedEppActions);
return this;
}
public Builder setRenewalPriceBehavior(RenewalPriceBehavior renewalPriceBehavior) {
getInstance().renewalPriceBehavior = renewalPriceBehavior;
return this;
@@ -0,0 +1,34 @@
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.persistence.converter;
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem;
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName;
import javax.persistence.Converter;
@Converter(autoApply = true)
public class CommandNameSetConverter
extends StringSetConverterBase<FeeQueryCommandExtensionItem.CommandName> {
@Override
String toString(CommandName element) {
return element.name();
}
@Override
CommandName fromString(String value) {
return FeeQueryCommandExtensionItem.CommandName.valueOf(value);
}
}
@@ -38,6 +38,7 @@ import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.SftpProgressMonitor;
import dagger.Lazy;
import google.registry.batch.CloudTasksUtils;
import google.registry.config.RegistryConfig.Config;
import google.registry.gcs.GcsUtils;
import google.registry.keyring.api.KeyModule.Key;
@@ -56,7 +57,6 @@ import google.registry.request.RequestParameters;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import google.registry.util.CloudTasksUtils;
import google.registry.util.Retrier;
import google.registry.util.TeeOutputStream;
import java.io.ByteArrayInputStream;
@@ -131,8 +131,7 @@ public final class RdeUploadAction implements Runnable, EscrowTask {
prefix.ifPresent(s -> params.put(RdeModule.PARAM_PREFIX, s));
cloudTasksUtils.enqueue(
RDE_REPORT_QUEUE,
cloudTasksUtils.createPostTask(
RdeReportAction.PATH, Service.BACKEND.getServiceId(), params));
cloudTasksUtils.createPostTask(RdeReportAction.PATH, Service.BACKEND, params));
}
@Override
@@ -27,6 +27,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.batch.CloudTasksUtils;
import google.registry.config.RegistryConfig.Config;
import google.registry.config.RegistryEnvironment;
import google.registry.persistence.PersistenceModule;
@@ -37,7 +38,6 @@ import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import google.registry.util.CloudTasksUtils;
import java.io.IOException;
import javax.inject.Inject;
import org.joda.time.Duration;
@@ -140,7 +140,7 @@ public class GenerateInvoicesAction implements Runnable {
ReportingModule.BEAM_QUEUE,
cloudTasksUtils.createPostTaskWithDelay(
PublishInvoicesAction.PATH,
Service.BACKEND.toString(),
Service.BACKEND,
ImmutableMultimap.of(
ReportingModule.PARAM_JOB_ID,
jobId,
@@ -26,6 +26,7 @@ import com.google.api.services.dataflow.model.Job;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.batch.CloudTasksUtils;
import google.registry.config.RegistryConfig.Config;
import google.registry.reporting.ReportingModule;
import google.registry.request.Action;
@@ -33,7 +34,6 @@ import google.registry.request.Action.Service;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.CloudTasksUtils;
import java.io.IOException;
import javax.inject.Inject;
import org.joda.time.YearMonth;
@@ -127,7 +127,7 @@ public class PublishInvoicesAction implements Runnable {
BillingModule.CRON_QUEUE,
cloudTasksUtils.createPostTask(
CopyDetailReportsAction.PATH,
Service.BACKEND.toString(),
Service.BACKEND,
ImmutableMultimap.of(PARAM_YEAR_MONTH, yearMonth.toString())));
}
}
@@ -26,6 +26,7 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.batch.CloudTasksUtils;
import google.registry.bigquery.BigqueryJobFailureException;
import google.registry.config.RegistryConfig.Config;
import google.registry.reporting.icann.IcannReportingModule.ReportType;
@@ -34,7 +35,6 @@ import google.registry.request.Action.Service;
import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.CloudTasksUtils;
import google.registry.util.EmailMessage;
import google.registry.util.Retrier;
import google.registry.util.SendEmailService;
@@ -123,7 +123,7 @@ public final class IcannReportingStagingAction implements Runnable {
CRON_QUEUE,
cloudTasksUtils.createPostTaskWithDelay(
IcannReportingUploadAction.PATH,
Service.BACKEND.toString(),
Service.BACKEND,
null,
Duration.standardMinutes(2)));
return null;
@@ -27,6 +27,7 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.flogger.FluentLogger;
import com.google.common.net.MediaType;
import google.registry.batch.CloudTasksUtils;
import google.registry.config.RegistryConfig.Config;
import google.registry.config.RegistryEnvironment;
import google.registry.keyring.api.KeyModule.Key;
@@ -37,7 +38,6 @@ import google.registry.request.Parameter;
import google.registry.request.Response;
import google.registry.request.auth.Auth;
import google.registry.util.Clock;
import google.registry.util.CloudTasksUtils;
import java.io.IOException;
import javax.inject.Inject;
import org.joda.time.Duration;
@@ -135,7 +135,7 @@ public class GenerateSpec11ReportAction implements Runnable {
ReportingModule.BEAM_QUEUE,
cloudTasksUtils.createPostTaskWithDelay(
PublishSpec11ReportAction.PATH,
Service.BACKEND.toString(),
Service.BACKEND,
ImmutableMultimap.of(
ReportingModule.PARAM_JOB_ID,
jobId,
@@ -18,6 +18,7 @@ import static com.google.common.net.HttpHeaders.AUTHORIZATION;
import static google.registry.request.auth.AuthLevel.APP;
import com.google.auth.oauth2.TokenVerifier;
import com.google.common.collect.ImmutableList;
import google.registry.config.RegistryConfig.Config;
import google.registry.request.auth.AuthModule.ServiceAccount;
import javax.inject.Inject;
@@ -30,16 +31,16 @@ import javax.servlet.http.HttpServletRequest;
*/
public class ServiceAccountAuthenticationMechanism extends IdTokenAuthenticationBase {
private final String cloudSchedulerEmailPrefix;
private static final String BEARER_PREFIX = "Bearer ";
private final ImmutableList<String> serviceAccountEmails;
@Inject
public ServiceAccountAuthenticationMechanism(
@ServiceAccount TokenVerifier tokenVerifier,
@Config("cloudSchedulerServiceAccountEmail") String cloudSchedulerEmailPrefix) {
@Config("serviceAccountEmails") ImmutableList<String> serviceAccountEmails) {
super(tokenVerifier);
this.cloudSchedulerEmailPrefix = cloudSchedulerEmailPrefix;
this.serviceAccountEmails = serviceAccountEmails;
}
@Override
@@ -53,7 +54,7 @@ public class ServiceAccountAuthenticationMechanism extends IdTokenAuthentication
@Override
AuthResult authResultFromEmail(String emailAddress) {
if (emailAddress.equals(cloudSchedulerEmailPrefix)) {
if (serviceAccountEmails.stream().anyMatch(e -> e.equals(emailAddress))) {
return AuthResult.create(APP);
} else {
return AuthResult.NOT_AUTHENTICATED;
@@ -14,21 +14,15 @@
package google.registry.tmch;
import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
import static com.google.common.base.Preconditions.checkState;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import com.google.appengine.api.taskqueue.TaskOptions;
import com.google.appengine.api.taskqueue.TaskOptions.Method;
import com.google.common.base.Joiner;
import google.registry.model.domain.Domain;
import google.registry.model.registrar.Registrar;
import java.util.Optional;
import org.joda.time.DateTime;
/**
* Helper methods for creating tasks containing CSV line data in the lordn-sunrise and lordn-claims
* queues based on {@link Domain} changes.
* Helper methods for creating tasks containing CSV line data based on {@link Domain#getLordnPhase}.
*
* <p>Note that, per the <a href="https://tools.ietf.org/html/draft-ietf-regext-tmch-func-spec-04">
* TMCH RFC</a>, while the application-datetime data is optional (which we never send because there
@@ -36,65 +30,32 @@ import org.joda.time.DateTime;
*/
public final class LordnTaskUtils {
public static final String QUEUE_SUNRISE = "lordn-sunrise";
public static final String QUEUE_CLAIMS = "lordn-claims";
public static final String COLUMNS_CLAIMS =
"roid,domain-name,notice-id,registrar-id,"
+ "registration-datetime,ack-datetime,application-datetime";
public static final String COLUMNS_SUNRISE =
"roid,domain-name,SMD-id,registrar-id," + "registration-datetime,application-datetime";
/** Enqueues a task in the LORDN queue representing a line of CSV for LORDN export. */
public static void enqueueDomainTask(Domain domain) {
tm().assertInTransaction();
// This method needs to use transactionTime as the Domain's creationTime because CreationTime
// isn't yet populated when this method is called during the resource flow.
String tld = domain.getTld();
if (domain.getLaunchNotice() == null) {
getQueue(QUEUE_SUNRISE)
.add(
TaskOptions.Builder.withTag(tld)
.method(Method.PULL)
.payload(getCsvLineForSunriseDomain(domain, tm().getTransactionTime())));
} else {
getQueue(QUEUE_CLAIMS)
.add(
TaskOptions.Builder.withTag(tld)
.method(Method.PULL)
.payload(getCsvLineForClaimsDomain(domain, tm().getTransactionTime())));
}
}
/** Returns the corresponding CSV LORDN line for a sunrise domain. */
public static String getCsvLineForSunriseDomain(Domain domain) {
return getCsvLineForSunriseDomain(domain, domain.getCreationTime());
}
// TODO: Merge into the function above after pull queue migration.
private static String getCsvLineForSunriseDomain(Domain domain, DateTime transactionTime) {
return Joiner.on(',')
.join(
domain.getRepoId(),
domain.getDomainName(),
domain.getSmdId(),
getIanaIdentifier(domain.getCreationRegistrarId()),
transactionTime); // Used as creation time.
domain.getCreationTime()); // Used as creation time.
}
/** Returns the corresponding CSV LORDN line for a claims domain. */
public static String getCsvLineForClaimsDomain(Domain domain) {
return getCsvLineForClaimsDomain(domain, domain.getCreationTime());
}
// TODO: Merge into the function above after pull queue migration.
private static String getCsvLineForClaimsDomain(Domain domain, DateTime transactionTime) {
return Joiner.on(',')
.join(
domain.getRepoId(),
domain.getDomainName(),
domain.getLaunchNotice().getNoticeId().getTcnId(),
getIanaIdentifier(domain.getCreationRegistrarId()),
transactionTime, // Used as creation time.
domain.getCreationTime(), // Used as creation time.
domain.getLaunchNotice().getAcceptedTime());
}
@@ -14,7 +14,6 @@
package google.registry.tmch;
import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.net.HttpHeaders.LOCATION;
@@ -43,9 +42,9 @@ import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSortedSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
import com.google.common.flogger.FluentLogger;
import google.registry.batch.CloudTasksUtils;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.domain.Domain;
import google.registry.request.Action;
@@ -57,7 +56,6 @@ import google.registry.request.UrlConnectionUtils;
import google.registry.request.auth.Auth;
import google.registry.tmch.LordnTaskUtils.LordnPhase;
import google.registry.util.Clock;
import google.registry.util.CloudTasksUtils;
import google.registry.util.Retrier;
import google.registry.util.UrlConnectionException;
import java.io.IOException;
@@ -66,7 +64,6 @@ import java.net.URL;
import java.security.GeneralSecurityException;
import java.security.SecureRandom;
import java.util.List;
import java.util.Optional;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
@@ -90,8 +87,6 @@ public final class NordnUploadAction implements Runnable {
static final String PATH = "/_dr/task/nordnUpload";
static final String LORDN_PHASE_PARAM = "lordnPhase";
// TODO: Delete after migrating off of pull queue.
static final String PULL_QUEUE_PARAM = "pullQueue";
private static final int BATCH_SIZE = 1000;
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
@@ -122,10 +117,6 @@ public final class NordnUploadAction implements Runnable {
@Parameter(RequestParameters.PARAM_TLD)
String tld;
@Inject
@Parameter(PULL_QUEUE_PARAM)
Optional<Boolean> usePullQueue;
@Inject CloudTasksUtils cloudTasksUtils;
@Inject
@@ -146,67 +137,59 @@ public final class NordnUploadAction implements Runnable {
@Override
public void run() {
if (usePullQueue.orElse(false)) {
try {
processLordnTasks();
} catch (IOException | GeneralSecurityException e) {
throw new RuntimeException(e);
}
} else {
checkArgument(
phase.equals(PARAM_LORDN_PHASE_SUNRISE) || phase.equals(PARAM_LORDN_PHASE_CLAIMS),
"Invalid phase specified to NordnUploadAction: %s.",
phase);
tm().transact(
() -> {
// Note here that we load all domains pending Nordn in one batch, which should not
// be a problem for the rate of domain registration that we see. If we anticipate
// a peak in claims during TLD launch (sunrise is NOT first-come-first-serve, so
// there should be no expectation of a peak during it), we can consider temporarily
// increasing the frequency of Nordn upload to reduce the size of each batch.
//
// We did not further divide the domains into smaller batches because the
// read-upload-write operation per small batch needs to be inside a single
// transaction to prevent race conditions, and running several uploads in rapid
// sucession will likely overwhelm the MarksDB upload server, which recommands a
// maximum upload frequency of every 3 hours.
//
// See:
// https://datatracker.ietf.org/doc/html/draft-ietf-regext-tmch-func-spec-01#section-5.2.3.3
List<Domain> domains =
tm().createQueryComposer(Domain.class)
.where("lordnPhase", EQ, LordnPhase.valueOf(Ascii.toUpperCase(phase)))
.where("tld", EQ, tld)
.orderBy("creationTime")
.list();
if (domains.isEmpty()) {
return;
}
StringBuilder csv = new StringBuilder();
ImmutableList.Builder<Domain> newDomains = new ImmutableList.Builder<>();
checkArgument(
phase.equals(PARAM_LORDN_PHASE_SUNRISE) || phase.equals(PARAM_LORDN_PHASE_CLAIMS),
"Invalid phase specified to NordnUploadAction: %s.",
phase);
tm().transact(
() -> {
// Note here that we load all domains pending Nordn in one batch, which should not
// be a problem for the rate of domain registration that we see. If we anticipate
// a peak in claims during TLD launch (sunrise is NOT first-come-first-serve, so
// there should be no expectation of a peak during it), we can consider temporarily
// increasing the frequency of Nordn upload to reduce the size of each batch.
//
// We did not further divide the domains into smaller batches because the
// read-upload-write operation per small batch needs to be inside a single
// transaction to prevent race conditions, and running several uploads in rapid
// sucession will likely overwhelm the MarksDB upload server, which recommands a
// maximum upload frequency of every 3 hours.
//
// See:
// https://datatracker.ietf.org/doc/html/draft-ietf-regext-tmch-func-spec-01#section-5.2.3.3
List<Domain> domains =
tm().createQueryComposer(Domain.class)
.where("lordnPhase", EQ, LordnPhase.valueOf(Ascii.toUpperCase(phase)))
.where("tld", EQ, tld)
.orderBy("creationTime")
.list();
if (domains.isEmpty()) {
return;
}
StringBuilder csv = new StringBuilder();
ImmutableList.Builder<Domain> newDomains = new ImmutableList.Builder<>();
domains.forEach(
domain -> {
if (phase.equals(PARAM_LORDN_PHASE_SUNRISE)) {
csv.append(getCsvLineForSunriseDomain(domain)).append('\n');
} else {
csv.append(getCsvLineForClaimsDomain(domain)).append('\n');
}
Domain newDomain = domain.asBuilder().setLordnPhase(LordnPhase.NONE).build();
newDomains.add(newDomain);
});
String columns =
phase.equals(PARAM_LORDN_PHASE_SUNRISE) ? COLUMNS_SUNRISE : COLUMNS_CLAIMS;
String header =
String.format("1,%s,%d\n%s\n", clock.nowUtc(), domains.size(), columns);
try {
uploadCsvToLordn(String.format("/LORDN/%s/%s", tld, phase), header + csv);
} catch (IOException | GeneralSecurityException e) {
throw new RuntimeException(e);
}
tm().updateAll(newDomains.build());
});
}
domains.forEach(
domain -> {
if (phase.equals(PARAM_LORDN_PHASE_SUNRISE)) {
csv.append(getCsvLineForSunriseDomain(domain)).append('\n');
} else {
csv.append(getCsvLineForClaimsDomain(domain)).append('\n');
}
Domain newDomain = domain.asBuilder().setLordnPhase(LordnPhase.NONE).build();
newDomains.add(newDomain);
});
String columns =
phase.equals(PARAM_LORDN_PHASE_SUNRISE) ? COLUMNS_SUNRISE : COLUMNS_CLAIMS;
String header =
String.format("1,%s,%d\n%s\n", clock.nowUtc(), domains.size(), columns);
try {
uploadCsvToLordn(String.format("/LORDN/%s/%s", tld, phase), header + csv);
} catch (IOException | GeneralSecurityException e) {
throw new RuntimeException(e);
}
tm().updateAll(newDomains.build());
});
}
/**
@@ -249,35 +232,6 @@ public final class NordnUploadAction implements Runnable {
}
}
private void processLordnTasks() throws IOException, GeneralSecurityException {
checkArgument(
phase.equals(PARAM_LORDN_PHASE_SUNRISE) || phase.equals(PARAM_LORDN_PHASE_CLAIMS),
"Invalid phase specified to NordnUploadAction: %s.",
phase);
DateTime now = clock.nowUtc();
Queue queue =
getQueue(
phase.equals(PARAM_LORDN_PHASE_SUNRISE)
? LordnTaskUtils.QUEUE_SUNRISE
: LordnTaskUtils.QUEUE_CLAIMS);
String columns = phase.equals(PARAM_LORDN_PHASE_SUNRISE) ? COLUMNS_SUNRISE : COLUMNS_CLAIMS;
List<TaskHandle> tasks = loadAllTasks(queue, tld);
// Note: This upload/task deletion isn't done atomically (it's not clear how one would do so
// anyway). As a result, it is possible that the upload might succeed yet the deletion of
// enqueued tasks might fail. If so, this would result in the same lines being uploaded to NORDN
// across multiple uploads. This is probably OK; all that we really cannot have is a missing
// line.
if (!tasks.isEmpty()) {
String csvData = convertTasksToCsv(tasks, now, columns);
uploadCsvToLordn(String.format("/LORDN/%s/%s", tld, phase), csvData);
Lists.partition(tasks, BATCH_SIZE)
.forEach(
batch ->
retrier.callWithRetry(
() -> queue.deleteTask(batch), TransientFailureException.class));
}
}
/**
* Upload LORDN file to MarksDB.
*
@@ -333,7 +287,7 @@ public final class NordnUploadAction implements Runnable {
// The actionLogId is used to uniquely associate the verify task back to the upload task.
return cloudTasksUtils.createPostTaskWithDelay(
NordnVerifyAction.PATH,
Service.BACKEND.toString(),
Service.BACKEND,
ImmutableMultimap.<String, String>builder()
.put(NordnVerifyAction.NORDN_URL_PARAM, url.toString())
.put(NordnVerifyAction.NORDN_LOG_ID_PARAM, actionLogId)
@@ -16,7 +16,6 @@ package google.registry.tmch;
import static com.google.common.io.Resources.asByteSource;
import static com.google.common.io.Resources.getResource;
import static google.registry.request.RequestParameters.extractOptionalBooleanParameter;
import static google.registry.request.RequestParameters.extractRequiredParameter;
import dagger.Module;
@@ -26,7 +25,6 @@ import google.registry.request.HttpException.BadRequestException;
import google.registry.request.Parameter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Optional;
import javax.servlet.http.HttpServletRequest;
import org.bouncycastle.openpgp.PGPPublicKey;
@@ -66,10 +64,4 @@ public final class TmchModule {
static String provideNordnLogId(HttpServletRequest req) {
return extractRequiredParameter(req, NordnVerifyAction.NORDN_LOG_ID_PARAM);
}
@Provides
@Parameter(NordnUploadAction.PULL_QUEUE_PARAM)
static Optional<Boolean> provideUsePullQueue(HttpServletRequest req) {
return extractOptionalBooleanParameter(req, NordnUploadAction.PULL_QUEUE_PARAM);
}
}
@@ -23,6 +23,7 @@ import static google.registry.tools.LockOrUnlockDomainCommand.REGISTRY_LOCK_STAT
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import google.registry.batch.CloudTasksUtils;
import google.registry.batch.RelockDomainAction;
import google.registry.config.RegistryConfig.Config;
import google.registry.model.billing.BillingEvent;
@@ -34,7 +35,6 @@ import google.registry.model.reporting.HistoryEntry;
import google.registry.model.tld.Registry;
import google.registry.model.tld.RegistryLockDao;
import google.registry.request.Action.Service;
import google.registry.util.CloudTasksUtils;
import google.registry.util.StringGenerator;
import java.util.Optional;
import javax.annotation.Nullable;
@@ -223,7 +223,7 @@ public final class DomainLockUtils {
QUEUE_ASYNC_ACTIONS,
cloudTasksUtils.createPostTaskWithDelay(
RelockDomainAction.PATH,
Service.BACKEND.toString(),
Service.BACKEND,
ImmutableMultimap.of(
RelockDomainAction.OLD_UNLOCK_REVISION_ID_PARAM,
String.valueOf(lockRevisionId),
@@ -28,11 +28,11 @@ import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import com.beust.jcommander.Parameters;
import com.google.common.collect.ImmutableMultimap;
import google.registry.batch.CloudTasksUtils;
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.CloudTasksUtils;
import java.util.List;
import java.util.stream.Collectors;
import javax.inject.Inject;
@@ -122,7 +122,7 @@ final class GenerateEscrowDepositCommand implements Command {
cloudTasksUtils.enqueue(
RDE_REPORT_QUEUE,
cloudTasksUtils.createPostTask(
RdeStagingAction.PATH, Service.BACKEND.toString(), paramsBuilder.build()));
RdeStagingAction.PATH, Service.BACKEND, paramsBuilder.build()));
}
}
@@ -21,7 +21,7 @@ import static google.registry.request.RequestParameters.PARAM_TLDS;
import com.google.common.collect.ImmutableSet;
import com.google.common.flogger.FluentLogger;
import google.registry.dns.DnsQueue;
import google.registry.dns.DnsUtils;
import google.registry.request.Action;
import google.registry.request.Parameter;
import google.registry.request.Response;
@@ -66,7 +66,7 @@ public class RefreshDnsForAllDomainsAction implements Runnable {
@Parameter("smearMinutes")
int smearMinutes;
@Inject DnsQueue dnsQueue;
@Inject DnsUtils dnsUtils;
@Inject Clock clock;
@Inject Random random;
@@ -91,7 +91,7 @@ public class RefreshDnsForAllDomainsAction implements Runnable {
domainName -> {
try {
// Smear the task execution time over the next N minutes.
dnsQueue.addDomainRefreshTask(
dnsUtils.requestDomainDnsRefresh(
domainName, Duration.standardMinutes(random.nextInt(smearMinutes)));
} catch (Throwable t) {
logger.atSevere().withCause(t).log(
@@ -36,6 +36,7 @@ import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import google.registry.batch.CloudTasksUtils;
import google.registry.config.RegistryEnvironment;
import google.registry.export.sheet.SyncRegistrarsSheetAction;
import google.registry.flows.certs.CertificateChecker;
@@ -58,7 +59,6 @@ import google.registry.ui.forms.FormException;
import google.registry.ui.forms.FormFieldException;
import google.registry.ui.server.RegistrarFormFields;
import google.registry.ui.server.SendEmailUtils;
import google.registry.util.CloudTasksUtils;
import google.registry.util.CollectionUtils;
import google.registry.util.DiffUtils;
import java.util.HashSet;
@@ -643,7 +643,7 @@ public class RegistrarSettingsAction implements Runnable, JsonActionRunner.JsonA
cloudTasksUtils.enqueue(
SyncRegistrarsSheetAction.QUEUE,
cloudTasksUtils.createGetTask(
SyncRegistrarsSheetAction.PATH, Service.BACKEND.toString(), ImmutableMultimap.of()));
SyncRegistrarsSheetAction.PATH, Service.BACKEND, ImmutableMultimap.of()));
}
String environment = Ascii.toLowerCase(String.valueOf(RegistryEnvironment.get()));
sendEmailUtils.sendEmail(
@@ -43,6 +43,7 @@
<class>google.registry.model.billing.BillingEvent$Recurring</class>
<class>google.registry.model.common.Cursor</class>
<class>google.registry.model.common.DatabaseMigrationStateSchedule</class>
<class>google.registry.model.common.DnsRefreshRequest</class>
<class>google.registry.model.console.User</class>
<class>google.registry.model.contact.ContactHistory</class>
<class>google.registry.model.contact.Contact</class>
@@ -84,6 +85,7 @@
<class>google.registry.persistence.converter.BillingEventFlagSetConverter</class>
<class>google.registry.persistence.converter.BloomFilterConverter</class>
<class>google.registry.persistence.converter.CidrAddressBlockListConverter</class>
<class>google.registry.persistence.converter.CommandNameSetConverter</class>
<class>google.registry.persistence.converter.CurrencyToBillingConverter</class>
<class>google.registry.persistence.converter.CurrencyUnitConverter</class>
<class>google.registry.persistence.converter.DatabaseMigrationScheduleTransitionConverter</class>
@@ -30,7 +30,6 @@ import google.registry.testing.CloudTasksHelper;
import google.registry.testing.CloudTasksHelper.TaskMatcher;
import google.registry.testing.FakeClock;
import google.registry.util.CapturingLogHandler;
import google.registry.util.CloudTasksUtils;
import google.registry.util.JdkLoggerConfig;
import java.util.logging.Level;
import org.joda.time.DateTime;
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.util;
package google.registry.batch;
import static com.google.common.truth.Truth.assertThat;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -27,9 +27,11 @@ import com.google.cloud.tasks.v2.Task;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.LinkedListMultimap;
import google.registry.batch.CloudTasksUtils.SerializableCloudTasksClient;
import google.registry.request.Action.Service;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeSleeper;
import google.registry.util.CloudTasksUtils.SerializableCloudTasksClient;
import google.registry.util.Retrier;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.util.Optional;
@@ -59,22 +61,22 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createGetTasks() {
Task task = cloudTasksUtils.createGetTask("/the/path", "myservice", params);
Task task = cloudTasksUtils.createGetTask("/the/path", Service.BACKEND, params);
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri())
.isEqualTo("/the/path?key1=val1&key2=val2&key1=val3");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(task.getScheduleTime().getSeconds()).isEqualTo(0);
}
@Test
void testSuccess_createPostTasks() {
Task task = cloudTasksUtils.createPostTask("/the/path", "myservice", params);
Task task = cloudTasksUtils.createPostTask("/the/path", Service.BACKEND, params);
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(task.getAppEngineHttpRequest().getHeadersMap().get("Content-Type"))
.isEqualTo("application/x-www-form-urlencoded");
assertThat(task.getAppEngineHttpRequest().getBody().toString(StandardCharsets.UTF_8))
@@ -84,42 +86,43 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createGetTasks_withNullParams() {
Task task = cloudTasksUtils.createGetTask("/the/path", "myservice", null);
Task task = cloudTasksUtils.createGetTask("/the/path", Service.BACKEND, null);
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(task.getScheduleTime().getSeconds()).isEqualTo(0);
}
@Test
void testSuccess_createPostTasks_withNullParams() {
Task task = cloudTasksUtils.createPostTask("/the/path", "myservice", null);
Task task = cloudTasksUtils.createPostTask("/the/path", Service.BACKEND, null);
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(task.getAppEngineHttpRequest().getBody().toString(StandardCharsets.UTF_8)).isEmpty();
assertThat(task.getScheduleTime().getSeconds()).isEqualTo(0);
}
@Test
void testSuccess_createGetTasks_withEmptyParams() {
Task task = cloudTasksUtils.createGetTask("/the/path", "myservice", ImmutableMultimap.of());
Task task = cloudTasksUtils.createGetTask("/the/path", Service.BACKEND, ImmutableMultimap.of());
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(task.getScheduleTime().getSeconds()).isEqualTo(0);
}
@Test
void testSuccess_createPostTasks_withEmptyParams() {
Task task = cloudTasksUtils.createPostTask("/the/path", "myservice", ImmutableMultimap.of());
Task task =
cloudTasksUtils.createPostTask("/the/path", Service.BACKEND, ImmutableMultimap.of());
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(task.getAppEngineHttpRequest().getBody().toString(StandardCharsets.UTF_8)).isEmpty();
assertThat(task.getScheduleTime().getSeconds()).isEqualTo(0);
}
@@ -128,12 +131,13 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createGetTasks_withJitterSeconds() {
Task task =
cloudTasksUtils.createGetTaskWithJitter("/the/path", "myservice", params, Optional.of(100));
cloudTasksUtils.createGetTaskWithJitter(
"/the/path", Service.BACKEND, params, Optional.of(100));
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri())
.isEqualTo("/the/path?key1=val1&key2=val2&key1=val3");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
Instant scheduleTime = Instant.ofEpochSecond(task.getScheduleTime().getSeconds());
Instant lowerBoundTime = Instant.ofEpochMilli(clock.nowUtc().getMillis());
@@ -147,11 +151,12 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createPostTasks_withJitterSeconds() {
Task task =
cloudTasksUtils.createPostTaskWithJitter("/the/path", "myservice", params, Optional.of(1));
cloudTasksUtils.createPostTaskWithJitter(
"/the/path", Service.BACKEND, params, Optional.of(1));
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(task.getAppEngineHttpRequest().getHeadersMap().get("Content-Type"))
.isEqualTo("application/x-www-form-urlencoded");
assertThat(task.getAppEngineHttpRequest().getBody().toString(StandardCharsets.UTF_8))
@@ -170,11 +175,11 @@ public class CloudTasksUtilsTest {
void testSuccess_createPostTasks_withEmptyJitterSeconds() {
Task task =
cloudTasksUtils.createPostTaskWithJitter(
"/the/path", "myservice", params, Optional.empty());
"/the/path", Service.BACKEND, params, Optional.empty());
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(task.getAppEngineHttpRequest().getHeadersMap().get("Content-Type"))
.isEqualTo("application/x-www-form-urlencoded");
assertThat(task.getAppEngineHttpRequest().getBody().toString(StandardCharsets.UTF_8))
@@ -185,23 +190,25 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createGetTasks_withEmptyJitterSeconds() {
Task task =
cloudTasksUtils.createGetTaskWithJitter("/the/path", "myservice", params, Optional.empty());
cloudTasksUtils.createGetTaskWithJitter(
"/the/path", Service.BACKEND, params, Optional.empty());
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri())
.isEqualTo("/the/path?key1=val1&key2=val2&key1=val3");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(task.getScheduleTime().getSeconds()).isEqualTo(0);
}
@Test
void testSuccess_createPostTasks_withZeroJitterSeconds() {
Task task =
cloudTasksUtils.createPostTaskWithJitter("/the/path", "myservice", params, Optional.of(0));
cloudTasksUtils.createPostTaskWithJitter(
"/the/path", Service.BACKEND, params, Optional.of(0));
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(task.getAppEngineHttpRequest().getHeadersMap().get("Content-Type"))
.isEqualTo("application/x-www-form-urlencoded");
assertThat(task.getAppEngineHttpRequest().getBody().toString(StandardCharsets.UTF_8))
@@ -212,12 +219,13 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createGetTasks_withZeroJitterSeconds() {
Task task =
cloudTasksUtils.createGetTaskWithJitter("/the/path", "myservice", params, Optional.of(0));
cloudTasksUtils.createGetTaskWithJitter(
"/the/path", Service.BACKEND, params, Optional.of(0));
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri())
.isEqualTo("/the/path?key1=val1&key2=val2&key1=val3");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(task.getScheduleTime().getSeconds()).isEqualTo(0);
}
@@ -225,12 +233,12 @@ public class CloudTasksUtilsTest {
void testSuccess_createGetTasks_withDelay() {
Task task =
cloudTasksUtils.createGetTaskWithDelay(
"/the/path", "myservice", params, Duration.standardMinutes(10));
"/the/path", Service.BACKEND, params, Duration.standardMinutes(10));
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri())
.isEqualTo("/the/path?key1=val1&key2=val2&key1=val3");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(Instant.ofEpochSecond(task.getScheduleTime().getSeconds()))
.isEqualTo(Instant.ofEpochMilli(clock.nowUtc().plusMinutes(10).getMillis()));
}
@@ -239,11 +247,11 @@ public class CloudTasksUtilsTest {
void testSuccess_createPostTasks_withDelay() {
Task task =
cloudTasksUtils.createPostTaskWithDelay(
"/the/path", "myservice", params, Duration.standardMinutes(10));
"/the/path", Service.BACKEND, params, Duration.standardMinutes(10));
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(task.getAppEngineHttpRequest().getHeadersMap().get("Content-Type"))
.isEqualTo("application/x-www-form-urlencoded");
assertThat(task.getAppEngineHttpRequest().getBody().toString(StandardCharsets.UTF_8))
@@ -260,7 +268,7 @@ public class CloudTasksUtilsTest {
IllegalArgumentException.class,
() ->
cloudTasksUtils.createGetTaskWithDelay(
"/the/path", "myservice", params, Duration.standardMinutes(-10)));
"/the/path", Service.BACKEND, params, Duration.standardMinutes(-10)));
assertThat(thrown).hasMessageThat().isEqualTo("Negative duration is not supported.");
}
@@ -271,18 +279,19 @@ public class CloudTasksUtilsTest {
IllegalArgumentException.class,
() ->
cloudTasksUtils.createGetTaskWithDelay(
"/the/path", "myservice", params, Duration.standardMinutes(-10)));
"/the/path", Service.BACKEND, params, Duration.standardMinutes(-10)));
assertThat(thrown).hasMessageThat().isEqualTo("Negative duration is not supported.");
}
@Test
void testSuccess_createPostTasks_withZeroDelay() {
Task task =
cloudTasksUtils.createPostTaskWithDelay("/the/path", "myservice", params, Duration.ZERO);
cloudTasksUtils.createPostTaskWithDelay(
"/the/path", Service.BACKEND, params, Duration.ZERO);
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.POST);
assertThat(task.getAppEngineHttpRequest().getRelativeUri()).isEqualTo("/the/path");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(task.getAppEngineHttpRequest().getHeadersMap().get("Content-Type"))
.isEqualTo("application/x-www-form-urlencoded");
assertThat(task.getAppEngineHttpRequest().getBody().toString(StandardCharsets.UTF_8))
@@ -293,12 +302,12 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_createGetTasks_withZeroDelay() {
Task task =
cloudTasksUtils.createGetTaskWithDelay("/the/path", "myservice", params, Duration.ZERO);
cloudTasksUtils.createGetTaskWithDelay("/the/path", Service.BACKEND, params, Duration.ZERO);
assertThat(task.getAppEngineHttpRequest().getHttpMethod()).isEqualTo(HttpMethod.GET);
assertThat(task.getAppEngineHttpRequest().getRelativeUri())
.isEqualTo("/the/path?key1=val1&key2=val2&key1=val3");
assertThat(task.getAppEngineHttpRequest().getAppEngineRouting().getService())
.isEqualTo("myservice");
.isEqualTo(Service.BACKEND.toString());
assertThat(task.getScheduleTime().getSeconds()).isEqualTo(0);
}
@@ -306,26 +315,26 @@ public class CloudTasksUtilsTest {
void testFailure_illegalPath() {
assertThrows(
IllegalArgumentException.class,
() -> cloudTasksUtils.createPostTask("the/path", "myservice", params));
() -> cloudTasksUtils.createPostTask("the/path", Service.BACKEND, params));
assertThrows(
IllegalArgumentException.class,
() -> cloudTasksUtils.createPostTask(null, "myservice", params));
() -> cloudTasksUtils.createPostTask(null, Service.BACKEND, params));
assertThrows(
IllegalArgumentException.class,
() -> cloudTasksUtils.createPostTask("", "myservice", params));
() -> cloudTasksUtils.createPostTask("", Service.BACKEND, params));
}
@Test
void testSuccess_enqueueTask() {
Task task = cloudTasksUtils.createGetTask("/the/path", "myservice", params);
Task task = cloudTasksUtils.createGetTask("/the/path", Service.BACKEND, params);
cloudTasksUtils.enqueue("test-queue", task);
verify(mockClient).enqueue("project", "location", "test-queue", task);
}
@Test
void testSuccess_enqueueTasks_varargs() {
Task task1 = cloudTasksUtils.createGetTask("/the/path", "myservice", params);
Task task2 = cloudTasksUtils.createGetTask("/other/path", "yourservice", params);
Task task1 = cloudTasksUtils.createGetTask("/the/path", Service.BACKEND, params);
Task task2 = cloudTasksUtils.createGetTask("/other/path", Service.TOOLS, params);
cloudTasksUtils.enqueue("test-queue", task1, task2);
verify(mockClient).enqueue("project", "location", "test-queue", task1);
verify(mockClient).enqueue("project", "location", "test-queue", task2);
@@ -333,8 +342,8 @@ public class CloudTasksUtilsTest {
@Test
void testSuccess_enqueueTasks_iterable() {
Task task1 = cloudTasksUtils.createGetTask("/the/path", "myservice", params);
Task task2 = cloudTasksUtils.createGetTask("/other/path", "yourservice", params);
Task task1 = cloudTasksUtils.createGetTask("/the/path", Service.BACKEND, params);
Task task2 = cloudTasksUtils.createGetTask("/other/path", Service.TOOLS, params);
cloudTasksUtils.enqueue("test-queue", ImmutableList.of(task1, task2));
verify(mockClient).enqueue("project", "location", "test-queue", task1);
verify(mockClient).enqueue("project", "location", "test-queue", task2);
@@ -27,14 +27,14 @@ import static google.registry.testing.DatabaseHelper.persistDeletedDomain;
import static google.registry.testing.DatabaseHelper.persistDomainAsDeleted;
import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.DatabaseHelper.persistSimpleResource;
import static google.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static org.joda.time.DateTimeZone.UTC;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import com.google.common.collect.ImmutableSet;
import google.registry.config.RegistryEnvironment;
import google.registry.dns.DnsQueue;
import google.registry.dns.DnsUtils;
import google.registry.model.ImmutableObject;
import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Reason;
@@ -47,9 +47,8 @@ import google.registry.model.tld.Registry.TldType;
import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.FakeClock;
import google.registry.testing.DnsUtilsHelper;
import google.registry.testing.SystemPropertyExtension;
import google.registry.testing.TaskQueueExtension;
import java.util.Optional;
import java.util.Set;
import org.joda.money.Money;
@@ -68,13 +67,14 @@ class DeleteProberDataActionTest {
final JpaIntegrationTestExtension jpa =
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
@RegisterExtension TaskQueueExtension taskQueue = new TaskQueueExtension();
@RegisterExtension
final SystemPropertyExtension systemPropertyExtension = new SystemPropertyExtension();
private DeleteProberDataAction action;
private final DnsUtils dnsUtils = mock(DnsUtils.class);
private final DnsUtilsHelper dnsUtilsHelper = new DnsUtilsHelper(dnsUtils);
@BeforeEach
void beforeEach() {
// Entities in these two should not be touched.
@@ -99,7 +99,7 @@ class DeleteProberDataActionTest {
private void resetAction() {
action = new DeleteProberDataAction();
action.dnsQueue = DnsQueue.createForTesting(new FakeClock());
action.dnsUtils = dnsUtils;
action.isDryRun = false;
action.tlds = ImmutableSet.of();
action.registryAdminRegistrarId = "TheRegistrar";
@@ -201,7 +201,7 @@ class DeleteProberDataActionTest {
DateTime timeAfterDeletion = DateTime.now(UTC);
assertThat(loadByForeignKey(Domain.class, "blah.ib-any.test", timeAfterDeletion)).isEmpty();
assertThat(loadByEntity(domain).getDeletionTime()).isLessThan(timeAfterDeletion);
assertDnsTasksEnqueued("blah.ib-any.test");
dnsUtilsHelper.assertDomainDnsRequests("blah.ib-any.test");
}
@Test
@@ -218,7 +218,7 @@ class DeleteProberDataActionTest {
action.run();
assertThat(loadByForeignKey(Domain.class, "blah.ib-any.test", timeAfterDeletion)).isEmpty();
assertThat(loadByEntity(domain).getDeletionTime()).isLessThan(timeAfterDeletion);
assertDnsTasksEnqueued("blah.ib-any.test");
dnsUtilsHelper.assertDomainDnsRequests("blah.ib-any.test");
}
@Test
@@ -0,0 +1,170 @@
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.dns;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.loadAllOf;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Ordering;
import google.registry.dns.DnsConstants.TargetType;
import google.registry.model.common.DatabaseMigrationStateSchedule;
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
import google.registry.model.common.DnsRefreshRequest;
import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
import google.registry.testing.FakeClock;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DnsUtils}. */
public class DnsUtilsTest {
private static final String tld = "tld";
private static final String domainName = "test.tld";
private static final String hostName = "ns1.test.tld";
private final DnsQueue dnsQueue = mock(DnsQueue.class);
private final DnsUtils dnsUtils = new DnsUtils(dnsQueue);
FakeClock clock = new FakeClock(DateTime.parse("2020-02-02T01:23:45Z"));
@RegisterExtension
JpaIntegrationTestExtension jpa =
new JpaTestExtensions.Builder().withClock(clock).buildIntegrationTestExtension();
@BeforeAll
static void beforeAll() {
DatabaseMigrationStateSchedule.useUncachedForTest();
}
@BeforeEach
void beforeEach() {
createTld(tld);
when(dnsQueue.getClock()).thenReturn(clock);
}
@Test
void testSuccess_hostRefresh_pullQueue() {
dnsUtils.requestHostDnsRefresh(hostName);
verify(dnsQueue).addHostRefreshTask(hostName);
assertThat(loadAllOf(DnsRefreshRequest.class)).isEmpty();
}
@Test
void testSuccess_domainRefresh_pullQueue() {
dnsUtils.requestDomainDnsRefresh(domainName);
verify(dnsQueue).addDomainRefreshTask(domainName, Duration.ZERO);
assertThat(loadAllOf(DnsRefreshRequest.class)).isEmpty();
}
@Test
void testSuccess_domainRefreshWithDelay_pullQueue() {
dnsUtils.requestDomainDnsRefresh(domainName, Duration.standardMinutes(3));
verify(dnsQueue).addDomainRefreshTask(domainName, Duration.standardMinutes(3));
assertThat(loadAllOf(DnsRefreshRequest.class)).isEmpty();
}
@Test
void testFailure_hostRefresh_unmanagedHost() {
String unmanagedHostName = "ns1.another.example";
Assertions.assertThrows(
IllegalArgumentException.class, () -> dnsUtils.requestHostDnsRefresh(unmanagedHostName));
verify(dnsQueue, never()).addHostRefreshTask(anyString());
assertThat(loadAllOf(DnsRefreshRequest.class)).isEmpty();
}
@Test
void testFailure_domainRefresh_unmanagedDomain() {
String unmanagedDomainName = "another.example";
Assertions.assertThrows(
IllegalArgumentException.class,
() -> dnsUtils.requestDomainDnsRefresh(unmanagedDomainName));
verify(dnsQueue, never()).addDomainRefreshTask(anyString(), any(Duration.class));
assertThat(loadAllOf(DnsRefreshRequest.class)).isEmpty();
}
@Test
void testSuccess_hostRefresh() {
useDnsSql();
dnsUtils.requestHostDnsRefresh(hostName);
verify(dnsQueue, never()).addHostRefreshTask(anyString());
DnsRefreshRequest request = Iterables.getOnlyElement(loadAllOf(DnsRefreshRequest.class));
assertRequest(request, TargetType.HOST, hostName, tld, clock.nowUtc());
}
@Test
void testSuccess_domainRefresh() {
useDnsSql();
dnsUtils.requestDomainDnsRefresh(domainName);
verify(dnsQueue, never()).addDomainRefreshTask(anyString(), any(Duration.class));
DnsRefreshRequest request = Iterables.getOnlyElement(loadAllOf(DnsRefreshRequest.class));
assertRequest(request, TargetType.DOMAIN, domainName, tld, clock.nowUtc());
}
@Test
void testSuccess_domainRefreshWithDelay() {
useDnsSql();
dnsUtils.requestDomainDnsRefresh(domainName, Duration.standardMinutes(3));
verify(dnsQueue, never()).addDomainRefreshTask(anyString(), any(Duration.class));
DnsRefreshRequest request = Iterables.getOnlyElement(loadAllOf(DnsRefreshRequest.class));
assertRequest(request, TargetType.DOMAIN, domainName, tld, clock.nowUtc().plusMinutes(3));
}
private static void assertRequest(
DnsRefreshRequest request, TargetType type, String name, String tld, DateTime requestTime) {
assertThat(request.getType()).isEqualTo(type);
assertThat(request.getName()).isEqualTo(name);
assertThat(request.getTld()).isEqualTo(tld);
assertThat(request.getRequestTime()).isEqualTo(requestTime);
}
private void useDnsSql() {
DateTime currentTime = clock.nowUtc();
clock.setTo(START_OF_TIME);
tm().transact(
() ->
DatabaseMigrationStateSchedule.set(
new ImmutableSortedMap.Builder<DateTime, MigrationState>(Ordering.natural())
.put(START_OF_TIME, MigrationState.DATASTORE_ONLY)
.put(START_OF_TIME.plusMillis(1), MigrationState.DATASTORE_PRIMARY)
.put(START_OF_TIME.plusMillis(2), MigrationState.DATASTORE_PRIMARY_NO_ASYNC)
.put(
START_OF_TIME.plusMillis(3), MigrationState.DATASTORE_PRIMARY_READ_ONLY)
.put(START_OF_TIME.plusMillis(4), MigrationState.SQL_PRIMARY_READ_ONLY)
.put(START_OF_TIME.plusMillis(5), MigrationState.SQL_PRIMARY)
.put(START_OF_TIME.plusMillis(6), MigrationState.SQL_ONLY)
.put(START_OF_TIME.plusMillis(7), MigrationState.SEQUENCE_BASED_ALLOCATE_ID)
.put(START_OF_TIME.plusMillis(8), MigrationState.NORDN_SQL)
.put(START_OF_TIME.plusMillis(9), MigrationState.DNS_SQL)
.build()));
clock.setTo(currentTime);
}
}
@@ -54,6 +54,7 @@ import google.registry.request.HttpException.ServiceUnavailableException;
import google.registry.request.lock.LockHandler;
import google.registry.testing.CloudTasksHelper;
import google.registry.testing.CloudTasksHelper.TaskMatcher;
import google.registry.testing.DnsUtilsHelper;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeLockHandler;
import google.registry.testing.FakeResponse;
@@ -82,7 +83,8 @@ public class PublishDnsUpdatesActionTest {
private final FakeLockHandler lockHandler = new FakeLockHandler(true);
private final DnsWriter dnsWriter = mock(DnsWriter.class);
private final DnsMetrics dnsMetrics = mock(DnsMetrics.class);
private final DnsQueue dnsQueue = mock(DnsQueue.class);
private final DnsUtils dnsUtils = mock(DnsUtils.class);
private final DnsUtilsHelper dnsUtilsHelper = new DnsUtilsHelper(dnsUtils);
private final CloudTasksHelper cloudTasksHelper = new CloudTasksHelper();
private PublishDnsUpdatesAction action;
private InternetAddress outgoingRegistry;
@@ -162,7 +164,7 @@ public class PublishDnsUpdatesActionTest {
outgoingRegistry,
Optional.ofNullable(retryCount),
Optional.empty(),
dnsQueue,
dnsUtils,
new DnsWriterProxy(ImmutableMap.of("correctWriter", dnsWriter)),
dnsMetrics,
lockHandler,
@@ -196,7 +198,7 @@ public class PublishDnsUpdatesActionTest {
Duration.standardHours(2),
Duration.standardHours(1));
verifyNoMoreInteractions(dnsMetrics);
verifyNoMoreInteractions(dnsQueue);
dnsUtilsHelper.assertNoMoreDnsRequests();
assertThat(response.getStatus()).isEqualTo(SC_OK);
}
@@ -223,7 +225,7 @@ public class PublishDnsUpdatesActionTest {
Duration.standardHours(2),
Duration.standardHours(1));
verifyNoMoreInteractions(dnsMetrics);
verifyNoMoreInteractions(dnsQueue);
dnsUtilsHelper.assertNoMoreDnsRequests();
assertThat(response.getStatus()).isEqualTo(SC_OK);
}
@@ -276,7 +278,7 @@ public class PublishDnsUpdatesActionTest {
Duration.standardHours(2),
Duration.standardHours(1));
verifyNoMoreInteractions(dnsMetrics);
verifyNoMoreInteractions(dnsQueue);
dnsUtilsHelper.assertNoMoreDnsRequests();
}
@Test
@@ -496,7 +498,7 @@ public class PublishDnsUpdatesActionTest {
Duration.standardHours(2),
Duration.standardHours(1));
verifyNoMoreInteractions(dnsMetrics);
verifyNoMoreInteractions(dnsQueue);
dnsUtilsHelper.assertNoMoreDnsRequests();
}
@Test
@@ -526,7 +528,7 @@ public class PublishDnsUpdatesActionTest {
Duration.standardHours(2),
Duration.standardHours(1));
verifyNoMoreInteractions(dnsMetrics);
verifyNoMoreInteractions(dnsQueue);
dnsUtilsHelper.assertNoMoreDnsRequests();
}
@Test
@@ -554,7 +556,7 @@ public class PublishDnsUpdatesActionTest {
Duration.standardHours(2),
Duration.standardHours(1));
verifyNoMoreInteractions(dnsMetrics);
verifyNoMoreInteractions(dnsQueue);
dnsUtilsHelper.assertNoMoreDnsRequests();
}
@Test
@@ -580,9 +582,9 @@ public class PublishDnsUpdatesActionTest {
Duration.standardHours(2),
Duration.standardHours(1));
verifyNoMoreInteractions(dnsMetrics);
verify(dnsQueue).addDomainRefreshTask("example.com");
verify(dnsQueue).addHostRefreshTask("ns1.example.com");
verifyNoMoreInteractions(dnsQueue);
dnsUtilsHelper.assertDomainDnsRequests("example.com");
dnsUtilsHelper.assertHostDnsRequests("ns1.example.com");
dnsUtilsHelper.assertNoMoreDnsRequests();
}
@Test
@@ -608,9 +610,9 @@ public class PublishDnsUpdatesActionTest {
Duration.standardHours(2),
Duration.standardHours(1));
verifyNoMoreInteractions(dnsMetrics);
verify(dnsQueue).addDomainRefreshTask("example.com");
verify(dnsQueue).addHostRefreshTask("ns1.example.com");
verifyNoMoreInteractions(dnsQueue);
dnsUtilsHelper.assertDomainDnsRequests("example.com");
dnsUtilsHelper.assertHostDnsRequests("ns1.example.com");
dnsUtilsHelper.assertNoMoreDnsRequests();
}
@Test
@@ -632,11 +634,11 @@ public class PublishDnsUpdatesActionTest {
Duration.standardHours(2),
Duration.standardHours(1));
verifyNoMoreInteractions(dnsMetrics);
verify(dnsQueue).addDomainRefreshTask("example.com");
verify(dnsQueue).addDomainRefreshTask("example2.com");
verify(dnsQueue).addHostRefreshTask("ns1.example.com");
verify(dnsQueue).addHostRefreshTask("ns2.example.com");
verify(dnsQueue).addHostRefreshTask("ns1.example2.com");
verifyNoMoreInteractions(dnsQueue);
dnsUtilsHelper.assertDomainDnsRequests("example.com");
dnsUtilsHelper.assertDomainDnsRequests("example2.com");
dnsUtilsHelper.assertHostDnsRequests("ns1.example.com");
dnsUtilsHelper.assertHostDnsRequests("ns2.example.com");
dnsUtilsHelper.assertHostDnsRequests("ns1.example2.com");
dnsUtilsHelper.assertNoMoreDnsRequests();
}
}
@@ -388,21 +388,6 @@ public class ReadDnsQueueActionTest {
ImmutableMultimap.of("com", "comWriter", "example", "exampleWriter"));
}
@RetryingTest(4)
void testSuccess_zone_getsIgnored() {
dnsQueue.addHostRefreshTask("ns1.domain.com");
dnsQueue.addDomainRefreshTask("domain.net");
dnsQueue.addZoneRefreshTask("example");
run();
TaskQueueHelper.assertNoTasksEnqueued(DNS_PULL_QUEUE_NAME);
cloudTasksHelper.assertTasksEnqueued(
DNS_PUBLISH_PUSH_QUEUE_NAME,
new TaskMatcher().url(PublishDnsUpdatesAction.PATH).param("domains", "domain.net"),
new TaskMatcher().url(PublishDnsUpdatesAction.PATH).param("hosts", "ns1.domain.com"));
}
private static String makeCommaSeparatedRange(int from, int to, String format) {
return IntStream.range(from, to)
.mapToObj(i -> String.format(format, i))
@@ -21,8 +21,6 @@ import static google.registry.testing.DatabaseHelper.persistActiveHost;
import static google.registry.testing.DatabaseHelper.persistActiveSubordinateHost;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import google.registry.dns.DnsConstants.TargetType;
import google.registry.model.domain.Domain;
@@ -30,6 +28,7 @@ import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
import google.registry.request.HttpException.BadRequestException;
import google.registry.request.HttpException.NotFoundException;
import google.registry.testing.DnsUtilsHelper;
import google.registry.testing.FakeClock;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -42,11 +41,12 @@ public class RefreshDnsActionTest {
final JpaIntegrationTestExtension jpa =
new JpaTestExtensions.Builder().buildIntegrationTestExtension();
private final DnsQueue dnsQueue = mock(DnsQueue.class);
private final DnsUtils dnsUtils = mock(DnsUtils.class);
private final DnsUtilsHelper dnsUtilsHelper = new DnsUtilsHelper(dnsUtils);
private final FakeClock clock = new FakeClock();
private void run(TargetType type, String name) {
new RefreshDnsAction(name, type, clock, dnsQueue).run();
new RefreshDnsAction(name, type, clock, dnsUtils).run();
}
@BeforeEach
@@ -59,8 +59,8 @@ public class RefreshDnsActionTest {
Domain domain = persistActiveDomain("example.xn--q9jyb4c");
persistActiveSubordinateHost("ns1.example.xn--q9jyb4c", domain);
run(TargetType.HOST, "ns1.example.xn--q9jyb4c");
verify(dnsQueue).addHostRefreshTask("ns1.example.xn--q9jyb4c");
verifyNoMoreInteractions(dnsQueue);
dnsUtilsHelper.assertHostDnsRequests("ns1.example.xn--q9jyb4c");
dnsUtilsHelper.assertNoMoreDnsRequests();
}
@Test
@@ -74,7 +74,7 @@ public class RefreshDnsActionTest {
try {
run(TargetType.HOST, "ns1.example.xn--q9jyb4c");
} finally {
verifyNoMoreInteractions(dnsQueue);
dnsUtilsHelper.assertNoMoreDnsRequests();
}
});
assertThat(thrown)
@@ -86,8 +86,8 @@ public class RefreshDnsActionTest {
void testSuccess_domain() {
persistActiveDomain("example.xn--q9jyb4c");
run(TargetType.DOMAIN, "example.xn--q9jyb4c");
verify(dnsQueue).addDomainRefreshTask("example.xn--q9jyb4c");
verifyNoMoreInteractions(dnsQueue);
dnsUtilsHelper.assertDomainDnsRequests("example.xn--q9jyb4c");
dnsUtilsHelper.assertNoMoreDnsRequests();
}
@Test
@@ -24,14 +24,13 @@ import static google.registry.testing.DatabaseHelper.persistResource;
import static javax.servlet.http.HttpServletResponse.SC_NO_CONTENT;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import com.google.common.collect.ImmutableSet;
import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.Host;
import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
import google.registry.testing.DnsUtilsHelper;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeResponse;
import org.joda.time.DateTime;
@@ -43,7 +42,8 @@ import org.junit.jupiter.api.extension.RegisterExtension;
public class RefreshDnsOnHostRenameActionTest {
private final FakeClock clock = new FakeClock(DateTime.parse("2015-01-15T11:22:33Z"));
private final DnsQueue dnsQueue = mock(DnsQueue.class);
private final DnsUtils dnsUtils = mock(DnsUtils.class);
private final DnsUtilsHelper dnsUtilsHelper = new DnsUtilsHelper(dnsUtils);
private final FakeResponse response = new FakeResponse();
@RegisterExtension
@@ -53,14 +53,7 @@ public class RefreshDnsOnHostRenameActionTest {
private RefreshDnsOnHostRenameAction action;
private void createAction(String hostKey) {
action = new RefreshDnsOnHostRenameAction(hostKey, response, dnsQueue);
}
private void assertDnsTasksEnqueued(String... domains) {
for (String domain : domains) {
verify(dnsQueue).addDomainRefreshTask(domain);
}
verifyNoMoreInteractions(dnsQueue);
action = new RefreshDnsOnHostRenameAction(hostKey, response, dnsUtils);
}
@BeforeEach
@@ -82,7 +75,7 @@ public class RefreshDnsOnHostRenameActionTest {
persistDomainAsDeleted(newDomain("deleted.tld", host), clock.nowUtc().minusDays(1));
createAction(host.createVKey().stringify());
action.run();
assertDnsTasksEnqueued("example.tld", "otherexample.tld");
dnsUtilsHelper.assertDomainDnsRequests("example.tld", "otherexample.tld");
assertThat(response.getStatus()).isEqualTo(SC_OK);
}
@@ -90,7 +83,7 @@ public class RefreshDnsOnHostRenameActionTest {
void testFailure_nonexistentHost() {
createAction("kind:Host@sql:rO0ABXQABGJsYWg");
action.run();
assertDnsTasksEnqueued();
dnsUtilsHelper.assertNoMoreDnsRequests();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload())
.isEqualTo("Host to refresh does not exist: VKey<Host>(sql:blah)");
@@ -102,7 +95,7 @@ public class RefreshDnsOnHostRenameActionTest {
persistResource(newDomain("example.tld", host));
createAction(host.createVKey().stringify());
action.run();
assertDnsTasksEnqueued();
dnsUtilsHelper.assertNoMoreDnsRequests();
assertThat(response.getStatus()).isEqualTo(SC_NO_CONTENT);
assertThat(response.getPayload())
.isEqualTo("Host to refresh is already deleted: ns1.example.tld");
@@ -20,9 +20,11 @@ import dagger.Provides;
import dagger.Subcomponent;
import google.registry.batch.AsyncTaskEnqueuer;
import google.registry.batch.AsyncTaskEnqueuerTest;
import google.registry.batch.CloudTasksUtils;
import google.registry.config.RegistryConfig.ConfigModule;
import google.registry.config.RegistryConfig.ConfigModule.TmchCaMode;
import google.registry.dns.DnsQueue;
import google.registry.dns.DnsUtils;
import google.registry.flows.custom.CustomLogicFactory;
import google.registry.flows.custom.TestCustomLogicFactory;
import google.registry.flows.domain.DomainFlowTmchUtils;
@@ -30,13 +32,13 @@ import google.registry.monitoring.whitebox.EppMetric;
import google.registry.request.RequestScope;
import google.registry.request.lock.LockHandler;
import google.registry.testing.CloudTasksHelper;
import google.registry.testing.DnsUtilsHelper;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeLockHandler;
import google.registry.testing.FakeSleeper;
import google.registry.tmch.TmchCertificateAuthority;
import google.registry.tmch.TmchXmlSignature;
import google.registry.util.Clock;
import google.registry.util.CloudTasksUtils;
import google.registry.util.Sleeper;
import javax.inject.Singleton;
@@ -59,11 +61,16 @@ public interface EppTestComponent {
private FakeLockHandler lockHandler;
private Sleeper sleeper;
private CloudTasksHelper cloudTasksHelper;
private DnsUtilsHelper dnsUtilsHelper;
public CloudTasksHelper getCloudTasksHelper() {
return cloudTasksHelper;
}
public DnsUtilsHelper getDnsUtilsHelper() {
return dnsUtilsHelper;
}
public EppMetric.Builder getMetricBuilder() {
return metricBuilder;
}
@@ -82,6 +89,7 @@ public interface EppTestComponent {
instance.metricBuilder = EppMetric.builderForRequest(clock);
instance.lockHandler = new FakeLockHandler(true);
instance.cloudTasksHelper = cloudTasksHelper;
instance.dnsUtilsHelper = new DnsUtilsHelper();
return instance;
}
@@ -95,6 +103,11 @@ public interface EppTestComponent {
return cloudTasksHelper.getTestCloudTasksUtils();
}
@Provides
DnsUtils provideDnsUtils() {
return dnsUtilsHelper.getDnsUtils();
}
@Provides
Clock provideClock() {
return clock;
@@ -45,6 +45,7 @@ import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
import google.registry.testing.CloudTasksHelper;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.DnsUtilsHelper;
import google.registry.testing.EppLoader;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeHttpSession;
@@ -84,6 +85,7 @@ public abstract class FlowTestCase<F extends Flow> {
protected TransportCredentials credentials = new PasswordOnlyTransportCredentials();
protected EppRequestSource eppRequestSource = EppRequestSource.UNIT_TEST;
protected CloudTasksHelper cloudTasksHelper;
protected DnsUtilsHelper dnsUtilsHelper;
private EppMetric.Builder eppMetricBuilder;
@@ -216,6 +218,7 @@ public abstract class FlowTestCase<F extends Flow> {
FakesAndMocksModule fakesAndMocksModule = FakesAndMocksModule.create(clock);
cloudTasksHelper = fakesAndMocksModule.getCloudTasksHelper();
dnsUtilsHelper = fakesAndMocksModule.getDnsUtilsHelper();
// Run the flow.
return DaggerEppTestComponent.builder()
.fakesAndMocksModule(fakesAndMocksModule)
@@ -17,6 +17,7 @@ package google.registry.flows.domain;
import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.DEFAULT;
import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.NONPREMIUM;
import static google.registry.model.billing.BillingEvent.RenewalPriceBehavior.SPECIFIED;
import static google.registry.model.domain.token.AllocationToken.TokenType.DEFAULT_PROMO;
import static google.registry.model.domain.token.AllocationToken.TokenType.SINGLE_USE;
import static google.registry.model.domain.token.AllocationToken.TokenType.UNLIMITED_USE;
import static google.registry.model.eppoutput.CheckData.DomainCheck.create;
@@ -38,6 +39,7 @@ import static org.joda.money.CurrencyUnit.USD;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
@@ -350,6 +352,28 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
runFlowAssertResponse(loadFile("domain_check_allocationtoken_fee_response.xml"));
}
@Test
void testSuccess_allocationTokenPromotion_doesNotUseValidDefaultToken_singleYear()
throws Exception {
setUpDefaultToken();
createTld("example");
persistResource(
new AllocationToken.Builder()
.setToken("abc123")
.setTokenType(UNLIMITED_USE)
.setDiscountFraction(0.5)
.setDiscountYears(2)
.setTokenStatusTransitions(
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
.put(clock.nowUtc().minusDays(1), TokenStatus.VALID)
.put(clock.nowUtc().plusDays(1), TokenStatus.ENDED)
.build())
.build());
setEppInput("domain_check_allocationtoken_fee.xml");
runFlowAssertResponse(loadFile("domain_check_allocationtoken_fee_response.xml"));
}
@Test
void testSuccess_allocationTokenPromotion_multiYearAndPremiums() throws Exception {
createTld("example");
@@ -760,6 +784,31 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
runFlowAssertResponse(loadFile("domain_check_fee_response_v06.xml"));
}
private void setUpDefaultToken() {
AllocationToken defaultToken =
persistResource(
new AllocationToken.Builder()
.setToken("bbbbb")
.setTokenType(DEFAULT_PROMO)
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
.setAllowedTlds(ImmutableSet.of("tld"))
.setDiscountFraction(0.5)
.build());
persistResource(
Registry.get("tld")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.build());
}
@Test
void testFeeExtension_defaultToken_v06() throws Exception {
setUpDefaultToken();
persistActiveDomain("example1.tld");
setEppInput("domain_check_fee_v06.xml", ImmutableMap.of("CURRENCY", "USD"));
runFlowAssertResponse(loadFile("domain_check_fee_response_default_token_v06.xml"));
}
@Test
void testFeeExtension_multipleReservations() throws Exception {
persistResource(
@@ -780,6 +829,14 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
runFlowAssertResponse(loadFile("domain_check_fee_response_v11.xml"));
}
@Test
void testFeeExtension_defaultToken_v11() throws Exception {
setUpDefaultToken();
persistActiveDomain("example1.tld");
setEppInput("domain_check_fee_v11.xml", ImmutableMap.of("CURRENCY", "USD"));
runFlowAssertResponse(loadFile("domain_check_fee_response_default_token_v11.xml"));
}
@Test
void testFeeExtension_v12() throws Exception {
persistActiveDomain("example1.tld");
@@ -787,6 +844,14 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
runFlowAssertResponse(loadFile("domain_check_fee_response_v12.xml"));
}
@Test
void testFeeExtension_defaultToken_v12() throws Exception {
setUpDefaultToken();
persistActiveDomain("example1.tld");
setEppInput("domain_check_fee_v12.xml", ImmutableMap.of("CURRENCY", "USD"));
runFlowAssertResponse(loadFile("domain_check_fee_response_default_token_v12.xml"));
}
@Test
void testSuccess_thirtyDomains_restoreFees() throws Exception {
// Note that 30 is more than 25, which is the maximum # of entity groups you can enlist in a
@@ -810,6 +875,14 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
runFlowAssertResponse(loadFile("domain_check_fee_multiple_commands_response_v06.xml"));
}
@Test
void testFeeExtension_multipleCommands_defaultTokenOnlyOnCreate_v06() throws Exception {
setUpDefaultToken();
setEppInput("domain_check_fee_multiple_commands_v06.xml");
runFlowAssertResponse(
loadFile("domain_check_fee_multiple_commands_default_token_response_v06.xml"));
}
// Version 11 cannot have multiple commands.
@Test
@@ -818,6 +891,80 @@ class DomainCheckFlowTest extends ResourceCheckFlowTestCase<DomainCheckFlow, Dom
runFlowAssertResponse(loadFile("domain_check_fee_multiple_commands_response_v12.xml"));
}
@Test
void testFeeExtension_multipleCommands_defaultTokenOnlyOnCreate_v12() throws Exception {
setUpDefaultToken();
setEppInput("domain_check_fee_multiple_commands_v12.xml");
runFlowAssertResponse(
loadFile("domain_check_fee_multiple_commands_default_token_response_v12.xml"));
}
void testFeeExtension_defaultToken_notValidForAllLabels_v06() throws Exception {
createTld("example");
AllocationToken defaultToken =
persistResource(
new AllocationToken.Builder()
.setToken("bbbbb")
.setTokenType(DEFAULT_PROMO)
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
.setAllowedTlds(ImmutableSet.of("example"))
.setDiscountPremiums(false)
.setDiscountFraction(0.5)
.build());
persistResource(
Registry.get("example")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.build());
setEppInput("domain_check_fee_default_token_multiple_names_v06.xml");
runFlowAssertResponse(
loadFile("domain_check_fee_default_token_multiple_names_response_v06.xml"));
}
void testFeeExtension_defaultToken_notValidForAllLabels_v11() throws Exception {
createTld("example");
AllocationToken defaultToken =
persistResource(
new AllocationToken.Builder()
.setToken("bbbbb")
.setTokenType(DEFAULT_PROMO)
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
.setAllowedTlds(ImmutableSet.of("example"))
.setDiscountPremiums(false)
.setDiscountFraction(0.5)
.build());
persistResource(
Registry.get("example")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.build());
setEppInput("domain_check_fee_default_token_multiple_names_v11.xml");
runFlowAssertResponse(
loadFile("domain_check_fee_default_token_multiple_names_response_v11.xml"));
}
void testFeeExtension_defaultToken_notValidForAllLabels_v12() throws Exception {
createTld("example");
AllocationToken defaultToken =
persistResource(
new AllocationToken.Builder()
.setToken("bbbbb")
.setTokenType(DEFAULT_PROMO)
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
.setAllowedTlds(ImmutableSet.of("example"))
.setDiscountPremiums(false)
.setDiscountFraction(0.5)
.build());
persistResource(
Registry.get("example")
.asBuilder()
.setDefaultPromoTokens(ImmutableList.of(defaultToken.createVKey()))
.build());
setEppInput("domain_check_fee_default_token_multiple_names_v12.xml");
runFlowAssertResponse(
loadFile("domain_check_fee_default_token_multiple_names_response_v12.xml"));
}
/** Test the same as {@link #testFeeExtension_multipleCommands_v06} with premium labels. */
@Test
void testFeeExtension_premiumLabels_v06() throws Exception {
@@ -54,12 +54,6 @@ import static google.registry.testing.DatabaseHelper.persistReservedList;
import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.DomainSubject.assertAboutDomains;
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
import static google.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
import static google.registry.testing.TaskQueueHelper.assertNoDnsTasksEnqueued;
import static google.registry.testing.TaskQueueHelper.assertNoTasksEnqueued;
import static google.registry.testing.TaskQueueHelper.assertTasksEnqueued;
import static google.registry.tmch.LordnTaskUtils.QUEUE_CLAIMS;
import static google.registry.tmch.LordnTaskUtils.QUEUE_SUNRISE;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static org.joda.money.CurrencyUnit.JPY;
@@ -155,8 +149,6 @@ import google.registry.model.billing.BillingEvent;
import google.registry.model.billing.BillingEvent.Flag;
import google.registry.model.billing.BillingEvent.Reason;
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
import google.registry.model.common.DatabaseMigrationStateSchedule;
import google.registry.model.common.DatabaseMigrationStateSchedule.MigrationState;
import google.registry.model.domain.Domain;
import google.registry.model.domain.DomainHistory;
import google.registry.model.domain.GracePeriod;
@@ -183,7 +175,6 @@ import google.registry.monitoring.whitebox.EppMetric;
import google.registry.persistence.VKey;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.TaskQueueExtension;
import google.registry.testing.TaskQueueHelper.TaskMatcher;
import google.registry.tmch.LordnTaskUtils.LordnPhase;
import google.registry.tmch.SmdrlCsvParser;
import google.registry.tmch.TmchData;
@@ -195,12 +186,9 @@ import javax.annotation.Nullable;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.junitpioneer.jupiter.cartesian.CartesianTest;
import org.junitpioneer.jupiter.cartesian.CartesianTest.Values;
@@ -230,11 +218,6 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
clock.setTo(DateTime.parse("1999-04-03T22:00:00.0Z").minus(Duration.millis(1)));
}
@BeforeAll
static void beforeAll() {
DatabaseMigrationStateSchedule.useUncachedForTest();
}
@BeforeEach
void initCreateTest() throws Exception {
createTld("tld");
@@ -393,7 +376,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
GracePeriod.create(
GracePeriodStatus.ADD, domain.getRepoId(), billingTime, "TheRegistrar", null),
createBillingEvent));
assertDnsTasksEnqueued(getUniqueIdFromCommand());
dnsUtilsHelper.assertDomainDnsRequests(getUniqueIdFromCommand());
}
private void assertNoLordn() throws Exception {
@@ -404,30 +387,16 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
.hasLaunchNotice(null)
.and()
.hasLordnPhase(LordnPhase.NONE);
assertNoTasksEnqueued(QUEUE_CLAIMS, QUEUE_SUNRISE);
assertNoTasksEnqueued(QUEUE_CLAIMS, QUEUE_SUNRISE);
}
private void assertSunriseLordn(String domainName) throws Exception {
private void assertSunriseLordn() throws Exception {
assertAboutDomains()
.that(reloadResourceByForeignKey())
.hasSmdId(SMD_ID)
.and()
.hasLaunchNotice(null);
if (DatabaseMigrationStateSchedule.getValueAtTime(clock.nowUtc())
.equals(MigrationState.NORDN_SQL)) {
assertAboutDomains().that(reloadResourceByForeignKey()).hasLordnPhase(LordnPhase.SUNRISE);
} else {
String expectedPayload =
String.format(
"%s,%s,%s,1,%s",
reloadResourceByForeignKey().getRepoId(),
domainName,
SMD_ID,
SMD_VALID_TIME.plusMillis(17));
assertTasksEnqueued(QUEUE_SUNRISE, new TaskMatcher().payload(expectedPayload));
assertAboutDomains().that(reloadResourceByForeignKey()).hasLordnPhase(LordnPhase.NONE);
}
.hasLaunchNotice(null)
.and()
.hasLordnPhase(LordnPhase.SUNRISE);
}
private void assertClaimsLordn() throws Exception {
@@ -440,20 +409,9 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
"370d0b7c9223372036854775807",
"tmch",
DateTime.parse("2010-08-16T09:00:00.0Z"),
DateTime.parse("2009-08-16T09:00:00.0Z")));
if (DatabaseMigrationStateSchedule.getValueAtTime(clock.nowUtc())
.equals(MigrationState.NORDN_SQL)) {
assertAboutDomains().that(reloadResourceByForeignKey()).hasLordnPhase(LordnPhase.CLAIMS);
} else {
TaskMatcher task =
new TaskMatcher()
.payload(
reloadResourceByForeignKey().getRepoId()
+ ",example-one.tld,370d0b7c9223372036854775807,1,"
+ "2009-08-16T09:00:00.017Z,2009-08-16T09:00:00.000Z");
assertTasksEnqueued(QUEUE_CLAIMS, task);
assertAboutDomains().that(reloadResourceByForeignKey()).hasLordnPhase(LordnPhase.NONE);
}
DateTime.parse("2009-08-16T09:00:00.0Z")))
.and()
.hasLordnPhase(LordnPhase.CLAIMS);
}
private void doSuccessfulTest(
@@ -944,7 +902,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
persistContactsAndHosts("net");
runFlowAssertResponse(loadFile("domain_create_response_idn_minna.xml"));
assertSuccessfulCreate("xn--q9jyb4c", ImmutableSet.of());
assertDnsTasksEnqueued("xn--abc-873b2e7eb1k8a4lpjvv.xn--q9jyb4c");
dnsUtilsHelper.assertDomainDnsRequests("xn--abc-873b2e7eb1k8a4lpjvv.xn--q9jyb4c");
}
@Test
@@ -953,7 +911,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
persistContactsAndHosts();
runFlowAssertResponse(
loadFile("domain_create_response.xml", ImmutableMap.of("DOMAIN", "example.tld")));
assertNoDnsTasksEnqueued();
dnsUtilsHelper.assertNoMoreDnsRequests();
}
@Test
@@ -966,7 +924,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
assertAboutDomains()
.that(reloadResourceByForeignKey())
.hasRegistrationExpirationTime(clock.nowUtc().plusYears(1));
assertDnsTasksEnqueued("example.tld");
dnsUtilsHelper.assertDomainDnsRequests("example.tld");
}
@Test
@@ -977,27 +935,19 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
assertAboutEppExceptions().that(thrown).marshalsToXml();
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
void testSuccess_claimsNotice(boolean usePullQueue) throws Exception {
if (!usePullQueue) {
useNordnSql();
}
@Test
void testSuccess_claimsNotice() throws Exception {
clock.setTo(DateTime.parse("2009-08-16T09:00:00.0Z"));
setEppInput("domain_create_claim_notice.xml");
persistContactsAndHosts();
runFlowAssertResponse(loadFile("domain_create_response_claims.xml"));
assertSuccessfulCreate("tld", ImmutableSet.of());
assertDnsTasksEnqueued("example-one.tld");
dnsUtilsHelper.assertDomainDnsRequests("example-one.tld");
assertClaimsLordn();
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
void testSuccess_claimsNoticeInQuietPeriod(boolean usePullQueue) throws Exception {
if (!usePullQueue) {
useNordnSql();
}
@Test
void testSuccess_claimsNoticeInQuietPeriod() throws Exception {
allocationToken =
persistResource(
new AllocationToken.Builder()
@@ -1021,7 +971,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
persistContactsAndHosts();
runFlowAssertResponse(loadFile("domain_create_response_claims.xml"));
assertSuccessfulCreate("tld", ImmutableSet.of(RESERVED), allocationToken);
assertDnsTasksEnqueued("example-one.tld");
dnsUtilsHelper.assertDomainDnsRequests("example-one.tld");
assertClaimsLordn();
assertAllocationTokenWasRedeemed("abcDEF23456");
}
@@ -1034,7 +984,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
runFlowAssertResponse(
loadFile("domain_create_response.xml", ImmutableMap.of("DOMAIN", "example.tld")));
assertSuccessfulCreate("tld", ImmutableSet.of());
assertDnsTasksEnqueued("example.tld");
dnsUtilsHelper.assertDomainDnsRequests("example.tld");
}
@Test
@@ -1043,7 +993,6 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
persistContactsAndHosts();
EppException thrown = assertThrows(MissingClaimsNoticeException.class, this::runFlow);
assertAboutEppExceptions().that(thrown).marshalsToXml();
assertNoTasksEnqueued(QUEUE_CLAIMS, QUEUE_SUNRISE);
}
@Test
@@ -1419,12 +1368,8 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
assertAllocationTokenWasRedeemed("abcDEF23456");
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
void testSuccess_anchorTenant_withClaims(boolean usePullQueue) throws Exception {
if (!usePullQueue) {
useNordnSql();
}
@Test
void testSuccess_anchorTenant_withClaims() throws Exception {
persistResource(
new AllocationToken.Builder()
.setDomainName("example-one.tld")
@@ -1442,7 +1387,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
persistContactsAndHosts();
runFlowAssertResponse(loadFile("domain_create_response_claims.xml"));
assertSuccessfulCreate("tld", ImmutableSet.of(ANCHOR_TENANT), allocationToken);
assertDnsTasksEnqueued("example-one.tld");
dnsUtilsHelper.assertDomainDnsRequests("example-one.tld");
assertClaimsLordn();
assertAllocationTokenWasRedeemed("abcDEF23456");
}
@@ -1492,12 +1437,8 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
assertSuccessfulCreate("tld", ImmutableSet.of(SUNRISE, ANCHOR_TENANT));
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
void testSuccess_anchorTenantInSunrise_withSignedMark(boolean usePullQueue) throws Exception {
if (!usePullQueue) {
useNordnSql();
}
@Test
void testSuccess_anchorTenantInSunrise_withSignedMark() throws Exception {
allocationToken =
persistResource(
new AllocationToken.Builder()
@@ -1526,8 +1467,8 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
"EXPIRATION_TIME",
SMD_VALID_TIME.plusYears(2).toString())));
assertSuccessfulCreate("tld", ImmutableSet.of(ANCHOR_TENANT, SUNRISE), allocationToken);
assertDnsTasksEnqueued("test-validate.tld");
assertSunriseLordn("test-validate.tld");
dnsUtilsHelper.assertDomainDnsRequests("test-validate.tld");
assertSunriseLordn();
assertAllocationTokenWasRedeemed("abcDEF23456");
}
@@ -2071,6 +2012,41 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
assertThat(billingEvent.getCost()).isEqualTo(Money.of(USD, BigDecimal.valueOf(19.5)));
}
@Test
void testSuccess_skipsOverExpiredDefaultToken() throws Exception {
persistContactsAndHosts();
AllocationToken defaultToken1 =
persistResource(
new AllocationToken.Builder()
.setToken("aaaaa")
.setTokenType(DEFAULT_PROMO)
.setAllowedRegistrarIds(ImmutableSet.of("NewRegistrar"))
.setAllowedTlds(ImmutableSet.of("tld"))
.build());
AllocationToken defaultToken2 =
persistResource(
new AllocationToken.Builder()
.setToken("bbbbb")
.setTokenType(DEFAULT_PROMO)
.setDiscountFraction(0.5)
.setAllowedRegistrarIds(ImmutableSet.of("TheRegistrar"))
.setAllowedTlds(ImmutableSet.of("tld"))
.setTokenStatusTransitions(
ImmutableSortedMap.<DateTime, TokenStatus>naturalOrder()
.put(START_OF_TIME, TokenStatus.NOT_STARTED)
.put(clock.nowUtc().minusDays(2), TokenStatus.VALID)
.put(clock.nowUtc().minusDays(1), TokenStatus.ENDED)
.build())
.build());
persistResource(
Registry.get("tld")
.asBuilder()
.setDefaultPromoTokens(
ImmutableList.of(defaultToken1.createVKey(), defaultToken2.createVKey()))
.build());
doSuccessfulTest();
}
BillingEvent.OneTime runTest_defaultToken(String token) throws Exception {
setEppInput("domain_create.xml", ImmutableMap.of("DOMAIN", "example.tld"));
runFlowAssertResponse(
@@ -2097,13 +2073,9 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
assertSuccessfulCreate("tld", ImmutableSet.of(RESERVED));
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
void testSuccess_reservedNameCollisionDomain_inSunrise_setsServerHoldAndPollMessage(
boolean usePullQueue) throws Exception {
if (!usePullQueue) {
useNordnSql();
}
@Test
void testSuccess_reservedNameCollisionDomain_inSunrise_setsServerHoldAndPollMessage()
throws Exception {
persistResource(
Registry.get("tld")
.asBuilder()
@@ -2125,10 +2097,10 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
"EXPIRATION_TIME",
SMD_VALID_TIME.plusYears(2).toString())));
assertSunriseLordn("test-and-validate.tld");
assertSunriseLordn();
// Check for SERVER_HOLD status, no DNS tasks enqueued, and collision poll message.
assertNoDnsTasksEnqueued();
dnsUtilsHelper.assertNoMoreDnsRequests();
Domain domain = reloadResourceByForeignKey();
assertThat(domain.getStatusValues()).contains(SERVER_HOLD);
assertPollMessagesWithCollisionOneTime(domain);
@@ -2145,7 +2117,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
loadFile("domain_create_response.xml", ImmutableMap.of("DOMAIN", "badcrash.tld")));
// Check for SERVER_HOLD status, no DNS tasks enqueued, and collision poll message.
assertNoDnsTasksEnqueued();
dnsUtilsHelper.assertNoMoreDnsRequests();
Domain domain = reloadResourceByForeignKey();
assertThat(domain.getStatusValues()).contains(SERVER_HOLD);
assertPollMessagesWithCollisionOneTime(domain);
@@ -2646,13 +2618,8 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
"tld", "domain_create_response.xml", SUPERUSER, ImmutableMap.of("DOMAIN", "example.tld"));
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
void testSuccess_startDateSunriseRegistration_withEncodedSignedMark(boolean usePullQueue)
throws Exception {
if (!usePullQueue) {
useNordnSql();
}
@Test
void testSuccess_startDateSunriseRegistration_withEncodedSignedMark() throws Exception {
createTld("tld", START_DATE_SUNRISE);
clock.setTo(SMD_VALID_TIME);
setEppInput(
@@ -2670,17 +2637,12 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
"EXPIRATION_TIME",
SMD_VALID_TIME.plusYears(2).toString())));
assertSuccessfulCreate("tld", ImmutableSet.of(SUNRISE));
assertSunriseLordn("test-validate.tld");
assertSunriseLordn();
}
/** Test that missing type= argument on launch create works in start-date sunrise. */
@ParameterizedTest
@ValueSource(booleans = {true, false})
void testSuccess_startDateSunriseRegistration_withEncodedSignedMark_noType(boolean usePullQueue)
throws Exception {
if (!usePullQueue) {
useNordnSql();
}
@Test
void testSuccess_startDateSunriseRegistration_withEncodedSignedMark_noType() throws Exception {
createTld("tld", START_DATE_SUNRISE);
clock.setTo(SMD_VALID_TIME);
setEppInput(
@@ -2698,7 +2660,7 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
"EXPIRATION_TIME",
SMD_VALID_TIME.plusYears(2).toString())));
assertSuccessfulCreate("tld", ImmutableSet.of(SUNRISE));
assertSunriseLordn("test-validate.tld");
assertSunriseLordn();
}
@Test
@@ -3733,97 +3695,4 @@ class DomainCreateFlowTest extends ResourceFlowTestCase<DomainCreateFlow, Domain
.isEqualTo(
"The package token abc123 cannot be used to register names for longer than 1 year.");
}
private static void useNordnSql() {
tm().transact(
() ->
DatabaseMigrationStateSchedule.set(
new ImmutableSortedMap.Builder<DateTime, MigrationState>(Ordering.natural())
.put(START_OF_TIME, MigrationState.DATASTORE_ONLY)
.put(START_OF_TIME.plusMillis(1), MigrationState.DATASTORE_PRIMARY)
.build()));
tm().transact(
() ->
DatabaseMigrationStateSchedule.set(
new ImmutableSortedMap.Builder<DateTime, MigrationState>(Ordering.natural())
.put(START_OF_TIME, MigrationState.DATASTORE_ONLY)
.put(START_OF_TIME.plusMillis(1), MigrationState.DATASTORE_PRIMARY)
.put(START_OF_TIME.plusMillis(2), MigrationState.DATASTORE_PRIMARY_NO_ASYNC)
.build()));
tm().transact(
() ->
DatabaseMigrationStateSchedule.set(
new ImmutableSortedMap.Builder<DateTime, MigrationState>(Ordering.natural())
.put(START_OF_TIME, MigrationState.DATASTORE_ONLY)
.put(START_OF_TIME.plusMillis(1), MigrationState.DATASTORE_PRIMARY)
.put(START_OF_TIME.plusMillis(2), MigrationState.DATASTORE_PRIMARY_NO_ASYNC)
.put(
START_OF_TIME.plusMillis(3), MigrationState.DATASTORE_PRIMARY_READ_ONLY)
.build()));
tm().transact(
() ->
DatabaseMigrationStateSchedule.set(
new ImmutableSortedMap.Builder<DateTime, MigrationState>(Ordering.natural())
.put(START_OF_TIME, MigrationState.DATASTORE_ONLY)
.put(START_OF_TIME.plusMillis(1), MigrationState.DATASTORE_PRIMARY)
.put(START_OF_TIME.plusMillis(2), MigrationState.DATASTORE_PRIMARY_NO_ASYNC)
.put(
START_OF_TIME.plusMillis(3), MigrationState.DATASTORE_PRIMARY_READ_ONLY)
.put(START_OF_TIME.plusMillis(4), MigrationState.SQL_PRIMARY_READ_ONLY)
.build()));
tm().transact(
() ->
DatabaseMigrationStateSchedule.set(
new ImmutableSortedMap.Builder<DateTime, MigrationState>(Ordering.natural())
.put(START_OF_TIME, MigrationState.DATASTORE_ONLY)
.put(START_OF_TIME.plusMillis(1), MigrationState.DATASTORE_PRIMARY)
.put(START_OF_TIME.plusMillis(2), MigrationState.DATASTORE_PRIMARY_NO_ASYNC)
.put(
START_OF_TIME.plusMillis(3), MigrationState.DATASTORE_PRIMARY_READ_ONLY)
.put(START_OF_TIME.plusMillis(4), MigrationState.SQL_PRIMARY_READ_ONLY)
.put(START_OF_TIME.plusMillis(5), MigrationState.SQL_PRIMARY)
.build()));
tm().transact(
() ->
DatabaseMigrationStateSchedule.set(
new ImmutableSortedMap.Builder<DateTime, MigrationState>(Ordering.natural())
.put(START_OF_TIME, MigrationState.DATASTORE_ONLY)
.put(START_OF_TIME.plusMillis(1), MigrationState.DATASTORE_PRIMARY)
.put(START_OF_TIME.plusMillis(2), MigrationState.DATASTORE_PRIMARY_NO_ASYNC)
.put(
START_OF_TIME.plusMillis(3), MigrationState.DATASTORE_PRIMARY_READ_ONLY)
.put(START_OF_TIME.plusMillis(4), MigrationState.SQL_PRIMARY_READ_ONLY)
.put(START_OF_TIME.plusMillis(5), MigrationState.SQL_PRIMARY)
.put(START_OF_TIME.plusMillis(6), MigrationState.SQL_ONLY)
.build()));
tm().transact(
() ->
DatabaseMigrationStateSchedule.set(
new ImmutableSortedMap.Builder<DateTime, MigrationState>(Ordering.natural())
.put(START_OF_TIME, MigrationState.DATASTORE_ONLY)
.put(START_OF_TIME.plusMillis(1), MigrationState.DATASTORE_PRIMARY)
.put(START_OF_TIME.plusMillis(2), MigrationState.DATASTORE_PRIMARY_NO_ASYNC)
.put(
START_OF_TIME.plusMillis(3), MigrationState.DATASTORE_PRIMARY_READ_ONLY)
.put(START_OF_TIME.plusMillis(4), MigrationState.SQL_PRIMARY_READ_ONLY)
.put(START_OF_TIME.plusMillis(5), MigrationState.SQL_PRIMARY)
.put(START_OF_TIME.plusMillis(6), MigrationState.SQL_ONLY)
.put(START_OF_TIME.plusMillis(7), MigrationState.SEQUENCE_BASED_ALLOCATE_ID)
.build()));
tm().transact(
() ->
DatabaseMigrationStateSchedule.set(
new ImmutableSortedMap.Builder<DateTime, MigrationState>(Ordering.natural())
.put(START_OF_TIME, MigrationState.DATASTORE_ONLY)
.put(START_OF_TIME.plusMillis(1), MigrationState.DATASTORE_PRIMARY)
.put(START_OF_TIME.plusMillis(2), MigrationState.DATASTORE_PRIMARY_NO_ASYNC)
.put(
START_OF_TIME.plusMillis(3), MigrationState.DATASTORE_PRIMARY_READ_ONLY)
.put(START_OF_TIME.plusMillis(4), MigrationState.SQL_PRIMARY_READ_ONLY)
.put(START_OF_TIME.plusMillis(5), MigrationState.SQL_PRIMARY)
.put(START_OF_TIME.plusMillis(6), MigrationState.SQL_ONLY)
.put(START_OF_TIME.plusMillis(7), MigrationState.SEQUENCE_BASED_ALLOCATE_ID)
.put(START_OF_TIME.plusMillis(8), MigrationState.NORDN_SQL)
.build()));
}
}
@@ -52,7 +52,6 @@ import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.DomainSubject.assertAboutDomains;
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
import static google.registry.testing.HistoryEntrySubject.assertAboutHistoryEntries;
import static google.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static org.joda.money.CurrencyUnit.USD;
@@ -101,20 +100,16 @@ import google.registry.model.transfer.TransferResponse;
import google.registry.model.transfer.TransferStatus;
import google.registry.testing.CloudTasksHelper.TaskMatcher;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.TaskQueueExtension;
import java.util.Map;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainDeleteFlow}. */
class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain> {
@RegisterExtension final TaskQueueExtension taskQueue = new TaskQueueExtension();
private Domain domain;
private DomainHistory earlierHistoryEntry;
@@ -362,7 +357,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
// The add grace period is for a billable action, so it should trigger a cancellation.
assertAutorenewClosedAndCancellationCreatedFor(
graceBillingEvent, getOnlyHistoryEntryOfType(domain, DOMAIN_DELETE, DomainHistory.class));
assertDnsTasksEnqueued("example.tld");
dnsUtilsHelper.assertDomainDnsRequests("example.tld");
// There should be no poll messages. The previous autorenew poll message should now be deleted.
assertThat(getPollMessages("TheRegistrar")).isEmpty();
}
@@ -752,7 +747,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
.build());
DateTime eventTime = clock.nowUtc();
runFlowAssertResponse(loadFile("generic_success_response.xml"));
assertDnsTasksEnqueued("example.tld");
dnsUtilsHelper.assertDomainDnsRequests("example.tld");
assertAutorenewClosedAndCancellationCreatedFor(
graceBillingEvent,
getOnlyHistoryEntryOfType(domain, DOMAIN_DELETE, DomainHistory.class),
@@ -770,7 +765,7 @@ class DomainDeleteFlowTest extends ResourceFlowTestCase<DomainDeleteFlow, Domain
.build());
clock.advanceOneMilli();
runFlowAssertResponse(loadFile("domain_delete_response_pending.xml"));
assertDnsTasksEnqueued("example.tld");
dnsUtilsHelper.assertDomainDnsRequests("example.tld");
assertOnlyBillingEventIsClosedAutorenew("TheRegistrar");
}
@@ -29,7 +29,6 @@ import static google.registry.testing.DatabaseHelper.persistReservedList;
import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.DomainSubject.assertAboutDomains;
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
import static google.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static org.joda.money.CurrencyUnit.EUR;
@@ -75,20 +74,16 @@ import google.registry.model.reporting.DomainTransactionRecord.TransactionReport
import google.registry.model.reporting.HistoryEntry;
import google.registry.model.tld.Registry;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.TaskQueueExtension;
import java.util.Map;
import java.util.Optional;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainRestoreRequestFlow}. */
class DomainRestoreRequestFlowTest extends ResourceFlowTestCase<DomainRestoreRequestFlow, Domain> {
@RegisterExtension final TaskQueueExtension taskQueue = new TaskQueueExtension();
private static final ImmutableMap<String, String> FEE_06_MAP =
ImmutableMap.of("FEE_VERSION", "0.6", "FEE_NS", "fee", "CURRENCY", "USD");
private static final ImmutableMap<String, String> FEE_11_MAP =
@@ -192,7 +187,7 @@ class DomainRestoreRequestFlowTest extends ResourceFlowTestCase<DomainRestoreReq
.and()
.hasLastEppUpdateRegistrarId("TheRegistrar");
assertThat(domain.getGracePeriods()).isEmpty();
assertDnsTasksEnqueued("example.tld");
dnsUtilsHelper.assertDomainDnsRequests("example.tld");
// The poll message for the delete should now be gone. The only poll message should be the new
// autorenew poll message.
assertPollMessages(
@@ -261,7 +256,7 @@ class DomainRestoreRequestFlowTest extends ResourceFlowTestCase<DomainRestoreReq
.and()
.hasLastEppUpdateRegistrarId("TheRegistrar");
assertThat(domain.getGracePeriods()).isEmpty();
assertDnsTasksEnqueued("example.tld");
dnsUtilsHelper.assertDomainDnsRequests("example.tld");
// The poll message for the delete should now be gone. The only poll message should be the new
// autorenew poll message.
assertPollMessages(
@@ -46,8 +46,6 @@ import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.DomainSubject.assertAboutDomains;
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
import static google.registry.testing.HistoryEntrySubject.assertAboutHistoryEntries;
import static google.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
import static google.registry.testing.TaskQueueHelper.assertNoDnsTasksEnqueued;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static org.joda.money.CurrencyUnit.USD;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -106,19 +104,15 @@ import google.registry.model.poll.PollMessage;
import google.registry.model.tld.Registry;
import google.registry.persistence.VKey;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.TaskQueueExtension;
import java.util.Optional;
import org.joda.money.Money;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link DomainUpdateFlow}. */
class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain> {
@RegisterExtension final TaskQueueExtension taskQueue = new TaskQueueExtension();
private static final DomainDsData SOME_DSDATA =
DomainDsData.create(
1,
@@ -222,7 +216,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.and()
.hasNoAutorenewEndTime();
assertNoBillingEvents();
assertDnsTasksEnqueued("example.tld");
dnsUtilsHelper.assertDomainDnsRequests("example.tld");
assertLastHistoryContainsResource(reloadResourceByForeignKey());
}
@@ -351,7 +345,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
assertThat(domain.getContacts()).hasSize(3);
assertThat(loadByKey(domain.getRegistrant()).getContactId()).isEqualTo("max_test_7");
assertNoBillingEvents();
assertDnsTasksEnqueued("example.tld");
dnsUtilsHelper.assertDomainDnsRequests("example.tld");
}
@Test
@@ -502,9 +496,9 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.map(ds -> ds.cloneWithDomainRepoId(resource.getRepoId()))
.collect(toImmutableSet()));
if (dnsTaskEnqueued) {
assertDnsTasksEnqueued("example.tld");
dnsUtilsHelper.assertDomainDnsRequests("example.tld");
} else {
assertNoDnsTasksEnqueued();
dnsUtilsHelper.assertNoMoreDnsRequests();
}
}
@@ -1765,7 +1759,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.setStatusValues(ImmutableSet.of(StatusValue.CLIENT_TRANSFER_PROHIBITED))
.build());
runFlowAsSuperuser();
assertDnsTasksEnqueued("example.tld");
dnsUtilsHelper.assertDomainDnsRequests("example.tld");
}
@Test
@@ -1781,7 +1775,7 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.setStatusValues(ImmutableSet.of(StatusValue.SERVER_HOLD))
.build());
runFlowAsSuperuser();
assertDnsTasksEnqueued("example.tld");
dnsUtilsHelper.assertDomainDnsRequests("example.tld");
}
@Test
@@ -1797,6 +1791,6 @@ class DomainUpdateFlowTest extends ResourceFlowTestCase<DomainUpdateFlow, Domain
.setStatusValues(ImmutableSet.of(StatusValue.PENDING_DELETE, StatusValue.SERVER_HOLD))
.build());
runFlowAsSuperuser();
assertNoDnsTasksEnqueued();
dnsUtilsHelper.assertNoMoreDnsRequests();
}
}
@@ -26,8 +26,6 @@ import static google.registry.testing.DatabaseHelper.persistDeletedHost;
import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
import static google.registry.testing.HostSubject.assertAboutHosts;
import static google.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
import static google.registry.testing.TaskQueueHelper.assertNoDnsTasksEnqueued;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.base.Strings;
@@ -54,16 +52,12 @@ import google.registry.model.eppcommon.StatusValue;
import google.registry.model.host.Host;
import google.registry.model.reporting.HistoryEntry;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.TaskQueueExtension;
import org.joda.time.DateTime;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link HostCreateFlow}. */
class HostCreateFlowTest extends ResourceFlowTestCase<HostCreateFlow, Host> {
@RegisterExtension TaskQueueExtension taskQueue = new TaskQueueExtension();
private void setEppHostCreateInput(String hostName, String hostAddrs) {
setEppInput(
"host_create.xml",
@@ -122,7 +116,7 @@ class HostCreateFlowTest extends ResourceFlowTestCase<HostCreateFlow, Host> {
void testSuccess_externalNeverExisted() throws Exception {
doSuccessfulTest();
assertAboutHosts().that(reloadResourceByForeignKey()).hasSuperordinateDomain(null);
assertNoDnsTasksEnqueued();
dnsUtilsHelper.assertNoMoreDnsRequests();
}
@Test
@@ -133,7 +127,7 @@ class HostCreateFlowTest extends ResourceFlowTestCase<HostCreateFlow, Host> {
loadByForeignKey(Domain.class, "example.tld", clock.nowUtc()).get();
assertAboutHosts().that(host).hasSuperordinateDomain(superordinateDomain.createVKey());
assertThat(superordinateDomain.getSubordinateHosts()).containsExactly("ns1.example.tld");
assertDnsTasksEnqueued("ns1.example.tld");
dnsUtilsHelper.assertHostDnsRequests("ns1.example.tld");
}
@Test
@@ -150,7 +144,7 @@ class HostCreateFlowTest extends ResourceFlowTestCase<HostCreateFlow, Host> {
persistDeletedHost(getUniqueIdFromCommand(), clock.nowUtc().minusDays(1));
doSuccessfulTest();
assertAboutHosts().that(reloadResourceByForeignKey()).hasSuperordinateDomain(null);
assertNoDnsTasksEnqueued();
dnsUtilsHelper.assertNoMoreDnsRequests();
}
@Test
@@ -162,7 +156,7 @@ class HostCreateFlowTest extends ResourceFlowTestCase<HostCreateFlow, Host> {
loadByForeignKey(Domain.class, "example.tld", clock.nowUtc()).get();
assertAboutHosts().that(host).hasSuperordinateDomain(superordinateDomain.createVKey());
assertThat(superordinateDomain.getSubordinateHosts()).containsExactly("ns1.example.tld");
assertDnsTasksEnqueued("ns1.example.tld");
dnsUtilsHelper.assertHostDnsRequests("ns1.example.tld");
}
@Test
@@ -24,8 +24,6 @@ import static google.registry.testing.DatabaseHelper.persistDeletedHost;
import static google.registry.testing.DatabaseHelper.persistResource;
import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptions;
import static google.registry.testing.HostSubject.assertAboutHosts;
import static google.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
import static google.registry.testing.TaskQueueHelper.assertNoDnsTasksEnqueued;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.collect.ImmutableMap;
@@ -48,17 +46,13 @@ import google.registry.model.tld.Registry;
import google.registry.model.transfer.DomainTransferData;
import google.registry.model.transfer.TransferStatus;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.TaskQueueExtension;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link HostDeleteFlow}. */
class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, Host> {
@RegisterExtension TaskQueueExtension taskQueue = new TaskQueueExtension();
@BeforeEach
void initFlowTest() {
setEppInput("host_delete.xml", ImmutableMap.of("HOSTNAME", "ns1.example.tld"));
@@ -320,10 +314,10 @@ class HostDeleteFlowTest extends ResourceFlowTestCase<HostDeleteFlow, Host> {
.hasType(Type.HOST_DELETE);
assertNoBillingEvents();
if (isSubordinate) {
assertDnsTasksEnqueued(deletedHost.getHostName());
dnsUtilsHelper.assertHostDnsRequests(deletedHost.getHostName());
assertThat(loadByKey(deletedHost.getSuperordinateDomain()).getSubordinateHosts()).isEmpty();
} else {
assertNoDnsTasksEnqueued();
dnsUtilsHelper.assertNoMoreDnsRequests();
}
assertLastHistoryContainsResource(deletedHost);
}
@@ -35,8 +35,6 @@ import static google.registry.testing.EppExceptionSubject.assertAboutEppExceptio
import static google.registry.testing.GenericEppResourceSubject.assertAboutEppResources;
import static google.registry.testing.HistoryEntrySubject.assertAboutHistoryEntries;
import static google.registry.testing.HostSubject.assertAboutHosts;
import static google.registry.testing.TaskQueueHelper.assertDnsTasksEnqueued;
import static google.registry.testing.TaskQueueHelper.assertNoDnsTasksEnqueued;
import static google.registry.util.DateTimeUtils.END_OF_TIME;
import static org.junit.jupiter.api.Assertions.assertThrows;
@@ -81,17 +79,13 @@ import google.registry.model.transfer.TransferStatus;
import google.registry.persistence.VKey;
import google.registry.testing.CloudTasksHelper.TaskMatcher;
import google.registry.testing.DatabaseHelper;
import google.registry.testing.TaskQueueExtension;
import javax.annotation.Nullable;
import org.joda.time.DateTime;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link HostUpdateFlow}. */
class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
@RegisterExtension TaskQueueExtension taskQueue = new TaskQueueExtension();
private void setEppHostUpdateInput(
String oldHostName, String newHostName, String ipOrStatusToAdd, String ipOrStatusToRem) {
setEppInput(
@@ -189,7 +183,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
persistActiveSubordinateHost(oldHostName(), persistActiveDomain("example.tld"));
Host renamedHost = doSuccessfulTest();
assertThat(renamedHost.isSubordinate()).isTrue();
assertDnsTasksEnqueued("ns1.example.tld", "ns2.example.tld");
dnsUtilsHelper.assertHostDnsRequests("ns1.example.tld", "ns2.example.tld");
VKey<Host> oldVKeyAfterRename = ForeignKeyUtils.load(Host.class, oldHostName(), clock.nowUtc());
assertThat(oldVKeyAfterRename).isNull();
}
@@ -238,7 +232,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
.and()
.hasOnlyOneHistoryEntryWhich()
.hasType(HistoryEntry.Type.HOST_UPDATE);
assertDnsTasksEnqueued("ns1.example.tld");
dnsUtilsHelper.assertHostDnsRequests("ns1.example.tld");
}
@Test
@@ -264,7 +258,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
.and()
.hasOnlyOneHistoryEntryWhich()
.hasType(HistoryEntry.Type.HOST_UPDATE);
assertDnsTasksEnqueued("ns1.example.tld");
dnsUtilsHelper.assertHostDnsRequests("ns1.example.tld");
}
@Test
@@ -298,7 +292,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
.hasLastTransferTime(oneDayAgo);
Domain reloadedDomain = loadByEntity(domain).cloneProjectedAtTime(now);
assertThat(reloadedDomain.getSubordinateHosts()).containsExactly("ns2.example.tld");
assertDnsTasksEnqueued("ns1.example.tld", "ns2.example.tld");
dnsUtilsHelper.assertHostDnsRequests("ns1.example.tld", "ns2.example.tld");
}
@Test
@@ -333,7 +327,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
assertThat(loadByEntity(foo).cloneProjectedAtTime(now).getSubordinateHosts()).isEmpty();
assertThat(loadByEntity(example).cloneProjectedAtTime(now).getSubordinateHosts())
.containsExactly("ns2.example.tld");
assertDnsTasksEnqueued("ns2.foo.tld", "ns2.example.tld");
dnsUtilsHelper.assertHostDnsRequests("ns2.foo.tld", "ns2.example.tld");
}
@Test
@@ -370,7 +364,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
assertThat(reloadedFooDomain.getSubordinateHosts()).isEmpty();
Domain reloadedTldDomain = loadByEntity(tldDomain).cloneProjectedAtTime(now);
assertThat(reloadedTldDomain.getSubordinateHosts()).containsExactly("ns2.example.tld");
assertDnsTasksEnqueued("ns1.example.foo", "ns2.example.tld");
dnsUtilsHelper.assertHostDnsRequests("ns1.example.foo", "ns2.example.tld");
}
@Test
@@ -413,7 +407,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
assertThat(renamedHost.getLastTransferTime()).isEqualTo(oneDayAgo);
Domain reloadedDomain = loadByEntity(domain).cloneProjectedAtTime(clock.nowUtc());
assertThat(reloadedDomain.getSubordinateHosts()).isEmpty();
assertDnsTasksEnqueued("ns1.example.foo");
dnsUtilsHelper.assertHostDnsRequests("ns1.example.foo");
}
@Test
@@ -425,7 +419,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
persistActiveHost(oldHostName());
assertThat(domain.getSubordinateHosts()).isEmpty();
assertThrows(CannotRenameExternalHostException.class, this::runFlow);
assertNoDnsTasksEnqueued();
dnsUtilsHelper.assertNoMoreDnsRequests();
}
@Test
@@ -449,7 +443,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
.hasLastTransferTime(null);
assertThat(loadByEntity(domain).cloneProjectedAtTime(now).getSubordinateHosts())
.containsExactly("ns2.example.tld");
assertDnsTasksEnqueued("ns2.example.tld");
dnsUtilsHelper.assertHostDnsRequests("ns2.example.tld");
}
@Test
@@ -474,7 +468,7 @@ class HostUpdateFlowTest extends ResourceFlowTestCase<HostUpdateFlow, Host> {
.hasPersistedCurrentSponsorRegistrarId("TheRegistrar")
.and()
.hasLastTransferTime(null);
assertNoDnsTasksEnqueued();
dnsUtilsHelper.assertNoMoreDnsRequests();
}
@Test
@@ -0,0 +1,93 @@
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.model.common;
import static com.google.common.truth.Truth.assertThat;
import static google.registry.model.ImmutableObjectSubject.assertAboutImmutableObjects;
import static google.registry.testing.DatabaseHelper.insertInDb;
import static google.registry.testing.DatabaseHelper.loadAllOf;
import static google.registry.util.DateTimeUtils.START_OF_TIME;
import static org.junit.jupiter.api.Assertions.assertThrows;
import com.google.common.collect.ImmutableList;
import google.registry.dns.DnsConstants.TargetType;
import google.registry.model.EntityTestCase;
import org.junit.jupiter.api.Test;
/** Unit tests for {@link DnsRefreshRequest}. */
public class DnsRefreshRequestTest extends EntityTestCase {
DnsRefreshRequestTest() {
super(JpaEntityCoverageCheck.ENABLED);
}
private final DnsRefreshRequest request =
new DnsRefreshRequest(TargetType.DOMAIN, "test.example", "example", fakeClock.nowUtc());
@Test
void testPersistence() {
assertThat(request.getLastProcessTime()).isEqualTo(START_OF_TIME);
fakeClock.advanceOneMilli();
insertInDb(request);
fakeClock.advanceOneMilli();
ImmutableList<DnsRefreshRequest> requests = loadAllOf(DnsRefreshRequest.class);
assertThat(requests.size()).isEqualTo(1);
assertThat(requests.get(0)).isEqualTo(request);
}
@Test
void testNullValues() {
// type
assertThrows(
NullPointerException.class,
() -> new DnsRefreshRequest(null, "test.example", "example", fakeClock.nowUtc()));
// name
assertThrows(
NullPointerException.class,
() -> new DnsRefreshRequest(TargetType.DOMAIN, null, "example", fakeClock.nowUtc()));
// tld
assertThrows(
NullPointerException.class,
() -> new DnsRefreshRequest(TargetType.DOMAIN, "test.example", null, fakeClock.nowUtc()));
// request time
assertThrows(
NullPointerException.class,
() -> new DnsRefreshRequest(TargetType.DOMAIN, "test.example", "example", null));
}
@Test
void testUpdateProcessTime() {
assertThat(
assertThrows(
IllegalArgumentException.class,
() -> request.updateProcessTime(fakeClock.nowUtc())))
.hasMessageThat()
.contains("must be later than request time");
fakeClock.advanceOneMilli();
fakeClock.advanceOneMilli();
DnsRefreshRequest newRequest = request.updateProcessTime(fakeClock.nowUtc());
assertAboutImmutableObjects().that(newRequest).isEqualExceptFields(request, "lastProcessTime");
assertThat(newRequest.getLastProcessTime()).isEqualTo(fakeClock.nowUtc());
assertThat(
assertThrows(
IllegalArgumentException.class,
() -> newRequest.updateProcessTime(fakeClock.nowUtc().minusMillis(1))))
.hasMessageThat()
.contains("must be later than the old one");
}
}
@@ -37,6 +37,7 @@ import google.registry.model.Buildable;
import google.registry.model.EntityTestCase;
import google.registry.model.billing.BillingEvent.RenewalPriceBehavior;
import google.registry.model.domain.Domain;
import google.registry.model.domain.fee.FeeQueryCommandExtensionItem.CommandName;
import google.registry.model.domain.token.AllocationToken.RegistrationBehavior;
import google.registry.model.domain.token.AllocationToken.TokenStatus;
import google.registry.model.domain.token.AllocationToken.TokenType;
@@ -77,6 +78,7 @@ public class AllocationTokenTest extends EntityTestCase {
.put(DateTime.now(UTC), TokenStatus.VALID)
.put(DateTime.now(UTC).plusWeeks(8), TokenStatus.ENDED)
.build())
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE, CommandName.RENEW))
.build());
assertThat(loadByEntity(unlimitedUseToken)).isEqualTo(unlimitedUseToken);
@@ -113,6 +115,7 @@ public class AllocationTokenTest extends EntityTestCase {
.put(DateTime.now(UTC), TokenStatus.VALID)
.put(DateTime.now(UTC).plusWeeks(8), TokenStatus.ENDED)
.build())
.setAllowedEppActions(ImmutableSet.of(CommandName.CREATE, CommandName.RENEW))
.build());
AllocationToken persisted = loadByEntity(unlimitedUseToken);
assertThat(SerializeUtils.serializeDeserialize(persisted)).isEqualTo(persisted);
@@ -23,6 +23,7 @@ import static org.mockito.Mockito.when;
import com.google.cloud.tasks.v2.HttpMethod;
import com.google.common.net.MediaType;
import google.registry.batch.CloudTasksUtils;
import google.registry.beam.BeamActionTestBase;
import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
@@ -30,7 +31,6 @@ import google.registry.reporting.ReportingModule;
import google.registry.testing.CloudTasksHelper;
import google.registry.testing.CloudTasksHelper.TaskMatcher;
import google.registry.testing.FakeClock;
import google.registry.util.CloudTasksUtils;
import java.io.IOException;
import org.joda.time.Duration;
import org.joda.time.YearMonth;
@@ -31,10 +31,10 @@ import com.google.api.services.dataflow.Dataflow.Projects.Locations.Jobs.Get;
import com.google.api.services.dataflow.model.Job;
import com.google.cloud.tasks.v2.HttpMethod;
import com.google.common.net.MediaType;
import google.registry.batch.CloudTasksUtils;
import google.registry.testing.CloudTasksHelper;
import google.registry.testing.CloudTasksHelper.TaskMatcher;
import google.registry.testing.FakeResponse;
import google.registry.util.CloudTasksUtils;
import java.io.IOException;
import org.joda.time.YearMonth;
import org.junit.jupiter.api.BeforeEach;
@@ -21,12 +21,12 @@ import static org.mockito.Mockito.when;
import com.google.cloud.tasks.v2.HttpMethod;
import com.google.common.net.MediaType;
import google.registry.batch.CloudTasksUtils;
import google.registry.beam.BeamActionTestBase;
import google.registry.reporting.ReportingModule;
import google.registry.testing.CloudTasksHelper;
import google.registry.testing.CloudTasksHelper.TaskMatcher;
import google.registry.testing.FakeClock;
import google.registry.util.CloudTasksUtils;
import java.io.IOException;
import org.joda.time.DateTime;
import org.joda.time.Duration;
@@ -22,6 +22,7 @@ import com.google.api.client.googleapis.auth.oauth2.GoogleIdToken.Payload;
import com.google.api.client.json.webtoken.JsonWebSignature;
import com.google.api.client.json.webtoken.JsonWebSignature.Header;
import com.google.auth.oauth2.TokenVerifier;
import com.google.common.collect.ImmutableList;
import javax.servlet.http.HttpServletRequest;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
@@ -44,7 +45,8 @@ class ServiceAccountAuthenticationMechanismTest {
@BeforeEach
void beforeEach() throws Exception {
serviceAccountAuthenticationMechanism =
new ServiceAccountAuthenticationMechanism(tokenVerifier, "sa-prefix@email.com");
new ServiceAccountAuthenticationMechanism(
tokenVerifier, ImmutableList.of("sa-prefix@email.com", "cloud-tasks@email.com"));
when(request.getHeader(AUTHORIZATION)).thenReturn("Bearer jwtValue");
Payload payload = new Payload();
payload.setEmail("sa-prefix@email.com");
@@ -59,6 +61,18 @@ class ServiceAccountAuthenticationMechanismTest {
assertThat(authResult.authLevel()).isEqualTo(AuthLevel.APP);
}
@Test
void testSuccess_secondEmail() throws Exception {
Payload payload = new Payload();
payload.setEmail("cloud-tasks@email.com");
token = new JsonWebSignature(new Header(), payload, new byte[0], new byte[0]);
when(tokenVerifier.verify("jwtValue")).thenReturn(token);
AuthResult authResult = serviceAccountAuthenticationMechanism.authenticate(request);
assertThat(authResult.isAuthenticated()).isTrue();
assertThat(authResult.authLevel()).isEqualTo(AuthLevel.APP);
}
@Test
void testFails_authenticateWrongEmail() throws Exception {
token.getPayload().set("email", "not-service-account-email@email.com");
@@ -18,6 +18,7 @@ import static com.google.common.truth.Truth.assert_;
import google.registry.model.billing.BillingEventTest;
import google.registry.model.common.CursorTest;
import google.registry.model.common.DnsRefreshRequestTest;
import google.registry.model.console.UserTest;
import google.registry.model.contact.ContactTest;
import google.registry.model.domain.DomainSqlTest;
@@ -85,6 +86,7 @@ import org.junit.runner.RunWith;
ContactHistoryTest.class,
ContactTest.class,
CursorTest.class,
DnsRefreshRequestTest.class,
DomainSqlTest.class,
DomainHistoryTest.class,
HostHistoryTest.class,
@@ -43,8 +43,8 @@ import com.google.protobuf.Timestamp;
import com.google.protobuf.util.Timestamps;
import dagger.Module;
import dagger.Provides;
import google.registry.batch.CloudTasksUtils;
import google.registry.model.ImmutableObject;
import google.registry.util.CloudTasksUtils;
import google.registry.util.Retrier;
import java.io.Serializable;
import java.net.URI;
@@ -104,7 +104,6 @@ import google.registry.model.transfer.DomainTransferData;
import google.registry.model.transfer.TransferData;
import google.registry.model.transfer.TransferStatus;
import google.registry.persistence.VKey;
import google.registry.tmch.LordnTaskUtils;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
@@ -312,17 +311,6 @@ public final class DatabaseHelper {
return persistResource(domain.asBuilder().setDeletionTime(deletionTime).build());
}
// TODO: delete after pull queue migration.
/** Persists a domain and enqueues a LORDN task of the appropriate type for it. */
public static Domain persistDomainAndEnqueueLordn(final Domain domain) {
final Domain persistedDomain = persistResource(domain);
// Calls {@link LordnTaskUtils#enqueueDomainTask} wrapped in a transaction so that the
// transaction time is set correctly.
tm().transact(() -> LordnTaskUtils.enqueueDomainTask(persistedDomain));
maybeAdvanceClock();
return persistedDomain;
}
/** Persists a {@link Recurring} and {@link HistoryEntry} for a domain that already exists. */
public static Domain persistBillingRecurrenceForDomain(
Domain domain, RenewalPriceBehavior renewalPriceBehavior, @Nullable Money renewalPrice) {
@@ -0,0 +1,73 @@
// Copyright 2023 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.testing;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import google.registry.dns.DnsUtils;
import google.registry.model.annotations.DeleteAfterMigration;
import org.joda.time.Duration;
/**
* Test helper for {@link DnsUtils}.
*
* <p>This is a temporary test class that is only used during DNS pull queue migration. Once we are
* no longer using the pull queue method, we can just assert on the inserted SQL entry instead in
* {@link DatabaseHelper}.
*/
@DeleteAfterMigration
public class DnsUtilsHelper {
private final DnsUtils dnsUtils;
public DnsUtilsHelper() {
dnsUtils = mock(DnsUtils.class);
}
public DnsUtilsHelper(DnsUtils dnsUtils) {
this.dnsUtils = dnsUtils;
}
public DnsUtils getDnsUtils() {
return dnsUtils;
}
public void assertDomainDnsRequests(String... domainNames) {
for (String domainName : domainNames) {
verify(dnsUtils).requestDomainDnsRefresh(domainName);
}
}
public void assertDomainDnsRequestWithDelay(String domainName, Duration delay) {
verify(dnsUtils).requestDomainDnsRefresh(domainName, delay);
}
public void assertNoDomainDnsRequestWithDelay(String domainName, Duration delay) {
verify(dnsUtils, never()).requestDomainDnsRefresh(domainName, delay);
}
public void assertHostDnsRequests(String... hostNames) {
for (String hostName : hostNames) {
verify(dnsUtils).requestHostDnsRefresh(hostName);
}
}
public void assertNoMoreDnsRequests() {
verifyNoMoreInteractions(dnsUtils);
}
}
@@ -1,111 +0,0 @@
// Copyright 2017 The Nomulus Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package google.registry.tmch;
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.DatabaseHelper.persistActiveContact;
import static google.registry.testing.DatabaseHelper.persistDomainAndEnqueueLordn;
import static google.registry.testing.TaskQueueHelper.assertTasksEnqueued;
import static org.junit.jupiter.api.Assertions.assertThrows;
import google.registry.model.domain.Domain;
import google.registry.model.domain.launch.LaunchNotice;
import google.registry.model.registrar.Registrar.Type;
import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
import google.registry.testing.FakeClock;
import google.registry.testing.TaskQueueExtension;
import google.registry.testing.TaskQueueHelper.TaskMatcher;
import google.registry.util.Clock;
import org.joda.time.DateTime;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
/** Unit tests for {@link LordnTaskUtils}. */
public class LordnTaskUtilsTest {
private static final Clock clock = new FakeClock(DateTime.parse("2010-05-01T10:11:12Z"));
@RegisterExtension
final JpaIntegrationTestExtension jpa =
new JpaTestExtensions.Builder().withClock(clock).buildIntegrationTestExtension();
@RegisterExtension final TaskQueueExtension taskQueue = new TaskQueueExtension();
@BeforeEach
void beforeEach() {
createTld("example");
}
private static Domain.Builder newDomainBuilder() {
return new Domain.Builder()
.setDomainName("fleece.example")
.setPersistedCurrentSponsorRegistrarId("TheRegistrar")
.setCreationRegistrarId("TheRegistrar")
.setRegistrant(persistActiveContact("jd1234").createVKey())
.setSmdId("smdzzzz")
.setCreationRegistrarId("TheRegistrar");
}
@Test
void test_enqueueDomainTask_sunrise() {
persistDomainAndEnqueueLordn(newDomainBuilder().setRepoId("A-EXAMPLE").build());
String expectedPayload =
"A-EXAMPLE,fleece.example,smdzzzz,1,2010-05-01T10:11:12.000Z";
assertTasksEnqueued(
"lordn-sunrise", new TaskMatcher().payload(expectedPayload).tag("example"));
}
@Test
void test_enqueueDomainTask_claims() {
Domain domain =
newDomainBuilder()
.setRepoId("11-EXAMPLE")
.setLaunchNotice(
LaunchNotice.create(
"landrush1tcn", null, null, DateTime.parse("2010-05-01T09:11:12Z")))
.build();
persistDomainAndEnqueueLordn(domain);
String expectedPayload = "11-EXAMPLE,fleece.example,landrush1tcn,1,2010-05-01T10:11:12.000Z,"
+ "2010-05-01T09:11:12.000Z";
assertTasksEnqueued("lordn-claims", new TaskMatcher().payload(expectedPayload).tag("example"));
}
@Test
void test_oteRegistrarWithNullIanaId() {
tm().transact(
() ->
tm().put(
loadRegistrar("TheRegistrar")
.asBuilder()
.setType(Type.OTE)
.setIanaIdentifier(null)
.build()));
persistDomainAndEnqueueLordn(newDomainBuilder().setRepoId("3-EXAMPLE").build());
String expectedPayload = "3-EXAMPLE,fleece.example,smdzzzz,null,2010-05-01T10:11:12.000Z";
assertTasksEnqueued(
"lordn-sunrise", new TaskMatcher().payload(expectedPayload).tag("example"));
}
@Test
void test_enqueueDomainTask_throwsNpeOnNullDomain() {
assertThrows(
NullPointerException.class,
() -> tm().transact(() -> LordnTaskUtils.enqueueDomainTask(null)));
}
}
@@ -14,7 +14,6 @@
package google.registry.tmch;
import static com.google.appengine.api.taskqueue.QueueFactory.getQueue;
import static com.google.common.net.HttpHeaders.AUTHORIZATION;
import static com.google.common.net.HttpHeaders.CONTENT_TYPE;
import static com.google.common.net.HttpHeaders.LOCATION;
@@ -25,7 +24,6 @@ import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.loadByKey;
import static google.registry.testing.DatabaseHelper.loadRegistrar;
import static google.registry.testing.DatabaseHelper.newDomain;
import static google.registry.testing.DatabaseHelper.persistDomainAndEnqueueLordn;
import static google.registry.testing.DatabaseHelper.persistResource;
import static java.nio.charset.StandardCharsets.UTF_8;
import static javax.servlet.http.HttpServletResponse.SC_ACCEPTED;
@@ -50,6 +48,7 @@ import com.google.appengine.api.taskqueue.TransientFailureException;
import com.google.apphosting.api.DeadlineExceededException;
import com.google.common.base.VerifyException;
import com.google.common.collect.ImmutableList;
import google.registry.batch.CloudTasksUtils;
import google.registry.model.domain.Domain;
import google.registry.model.domain.launch.LaunchNotice;
import google.registry.model.tld.Registry;
@@ -62,9 +61,7 @@ import google.registry.testing.CloudTasksHelper.TaskMatcher;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeSleeper;
import google.registry.testing.FakeUrlConnectionService;
import google.registry.testing.TaskQueueExtension;
import google.registry.tmch.LordnTaskUtils.LordnPhase;
import google.registry.util.CloudTasksUtils;
import google.registry.util.Retrier;
import google.registry.util.UrlConnectionException;
import java.io.ByteArrayInputStream;
@@ -74,14 +71,11 @@ import java.net.URL;
import java.security.SecureRandom;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
/** Unit tests for {@link NordnUploadAction}. */
class NordnUploadActionTest {
@@ -111,8 +105,6 @@ class NordnUploadActionTest {
final JpaIntegrationTestExtension jpa =
new JpaTestExtensions.Builder().withClock(clock).buildIntegrationTestExtension();
@RegisterExtension final TaskQueueExtension taskQueueExtension = new TaskQueueExtension();
private final LordnRequestInitializer lordnRequestInitializer =
new LordnRequestInitializer(Optional.of("attack"));
private final NordnUploadAction action = new NordnUploadAction();
@@ -145,7 +137,6 @@ class NordnUploadActionTest {
action.tmchMarksdbUrl = "http://127.0.0.1";
action.random = new SecureRandom();
action.retrier = new Retrier(new FakeSleeper(clock), 3);
action.usePullQueue = Optional.empty();
}
@Test
@@ -229,23 +220,21 @@ class NordnUploadActionTest {
cloudTasksHelper.assertNoTasksEnqueued(NordnVerifyAction.QUEUE);
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
void testSuccess_claimsMode(boolean usePullQueue) throws Exception {
testRun("claims", "claims-landrush1.tld", "claims-landrush2.tld", CLAIMS_CSV, usePullQueue);
@Test
void testSuccess_claimsMode() throws Exception {
testRun("claims", "claims-landrush1.tld", "claims-landrush2.tld", CLAIMS_CSV);
}
@ParameterizedTest
@ValueSource(booleans = {true, false})
void testSuccess_sunriseMode(boolean usePullQueue) throws Exception {
testRun("sunrise", "sunrise1.tld", "sunrise2.tld", SUNRISE_CSV, usePullQueue);
@Test
void testSuccess_sunriseMode() throws Exception {
testRun("sunrise", "sunrise1.tld", "sunrise2.tld", SUNRISE_CSV);
}
@Test
void testSuccess_noResponseContent_stillWorksNormally() throws Exception {
// Returning null only affects logging.
when(httpUrlConnection.getInputStream()).thenReturn(new ByteArrayInputStream(new byte[] {}));
testRun("claims", "claims-landrush1.tld", "claims-landrush2.tld", CLAIMS_CSV, false);
testRun("claims", "claims-landrush1.tld", "claims-landrush2.tld", CLAIMS_CSV);
}
@Test
@@ -268,7 +257,7 @@ class NordnUploadActionTest {
}
private void persistClaimsModeDomain() {
persistDomainAndEnqueueLordn(
persistResource(
newDomain("claims-landrush2.tld")
.asBuilder()
.setCreationTimeForTest(clock.nowUtc())
@@ -278,7 +267,7 @@ class NordnUploadActionTest {
.setLordnPhase(LordnPhase.CLAIMS)
.build());
clock.advanceBy(Duration.standardDays(1));
persistDomainAndEnqueueLordn(
persistResource(
newDomain("claims-landrush1.tld")
.asBuilder()
.setCreationTimeForTest(clock.nowUtc())
@@ -289,7 +278,7 @@ class NordnUploadActionTest {
}
private void persistSunriseModeDomain() {
persistDomainAndEnqueueLordn(
persistResource(
newDomain("sunrise2.tld")
.asBuilder()
.setCreationTimeForTest(clock.nowUtc())
@@ -298,7 +287,7 @@ class NordnUploadActionTest {
.setLordnPhase(LordnPhase.SUNRISE)
.build());
clock.advanceBy(Duration.standardDays(1));
persistDomainAndEnqueueLordn(
persistResource(
newDomain("sunrise1.tld")
.asBuilder()
.setCreationTimeForTest(clock.nowUtc())
@@ -320,10 +309,7 @@ class NordnUploadActionTest {
assertThat(domain.getLordnPhase()).isEqualTo(LordnPhase.NONE);
}
private void testRun(
String phase, String domain1, String domain2, String csv, boolean usePullQueue)
throws Exception {
action.usePullQueue = Optional.of(usePullQueue);
private void testRun(String phase, String domain1, String domain2, String csv) throws Exception {
action.phase = phase;
action.run();
verify(httpUrlConnection)
@@ -335,18 +321,8 @@ class NordnUploadActionTest {
assertThat(httpUrlConnection.getURL())
.isEqualTo(new URL("http://127.0.0.1/LORDN/tld/" + phase));
assertThat(connectionOutputStream.toString(UTF_8)).contains(csv);
if (!usePullQueue) {
verifyColumnCleared(domain1);
verifyColumnCleared(domain2);
} else {
assertThat(
getQueue("lordn-" + phase)
.leaseTasks(
LeaseOptions.Builder.withTag("tld")
.leasePeriod(1, TimeUnit.HOURS)
.countLimit(100)))
.isEmpty();
}
verifyColumnCleared(domain1);
verifyColumnCleared(domain2);
cloudTasksHelper.assertTasksEnqueued(
NordnVerifyAction.QUEUE,
new TaskMatcher()
@@ -21,7 +21,6 @@ import org.junit.runners.Suite.SuiteClasses;
/** Convenience class to run all TMCH tests inside IDE with one keystroke. */
@RunWith(Suite.class)
@SuiteClasses({
LordnTaskUtilsTest.class,
NordnUploadAction.class,
NordnVerifyAction.class,
SmdrlCsvParserTest.class,
@@ -18,21 +18,18 @@ import static com.google.common.truth.Truth.assertThat;
import static google.registry.testing.DatabaseHelper.createTld;
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
import static google.registry.testing.DatabaseHelper.persistDeletedDomain;
import static org.joda.time.Duration.standardMinutes;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import com.google.common.collect.ImmutableSet;
import google.registry.dns.DnsQueue;
import google.registry.dns.DnsUtils;
import google.registry.persistence.transaction.JpaTestExtensions;
import google.registry.persistence.transaction.JpaTestExtensions.JpaIntegrationTestExtension;
import google.registry.testing.DnsUtilsHelper;
import google.registry.testing.FakeClock;
import google.registry.testing.FakeResponse;
import java.util.Random;
@@ -42,14 +39,13 @@ import org.joda.time.Duration;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.mockito.ArgumentCaptor;
import org.mockito.InOrder;
/** Unit tests for {@link RefreshDnsForAllDomainsAction}. */
public class RefreshDnsForAllDomainsActionTest {
private final FakeClock clock = new FakeClock(DateTime.parse("2020-02-02T02:02:02Z"));
private final DnsQueue dnsQueue = mock(DnsQueue.class);
private final DnsUtils dnsUtils = mock(DnsUtils.class);
private final DnsUtilsHelper dnsUtilsHelper = new DnsUtilsHelper(dnsUtils);
private RefreshDnsForAllDomainsAction action;
private final FakeResponse response = new FakeResponse();
@@ -64,27 +60,26 @@ public class RefreshDnsForAllDomainsActionTest {
action.random = new Random();
action.random.setSeed(123L);
action.clock = clock;
action.dnsQueue = dnsQueue;
action.dnsUtils = dnsUtils;
action.response = response;
createTld("bar");
}
@Test
void test_runAction_errorEnqueuingToDnsQueue() throws Exception {
void test_runAction_errorRequestDnsRefresh() throws Exception {
persistActiveDomain("foo.bar");
persistActiveDomain("baz.bar");
persistActiveDomain("low.bar");
action.tlds = ImmutableSet.of("bar");
doThrow(new RuntimeException("Error enqueuing task."))
.when(dnsQueue)
.addDomainRefreshTask(eq("baz.bar"), any(Duration.class));
.when(dnsUtils)
.requestDomainDnsRefresh(eq("baz.bar"), any(Duration.class));
action.run();
InOrder inOrder = inOrder(dnsQueue);
inOrder.verify(dnsQueue).addDomainRefreshTask("low.bar", Duration.ZERO);
inOrder.verify(dnsQueue).addDomainRefreshTask("baz.bar", Duration.ZERO);
inOrder.verify(dnsQueue).addDomainRefreshTask("foo.bar", Duration.ZERO);
verifyNoMoreInteractions(dnsQueue);
dnsUtilsHelper.assertDomainDnsRequestWithDelay("low.bar", Duration.ZERO);
dnsUtilsHelper.assertDomainDnsRequestWithDelay("baz.bar", Duration.ZERO);
dnsUtilsHelper.assertDomainDnsRequestWithDelay("foo.bar", Duration.ZERO);
verifyNoMoreInteractions(dnsUtils);
assertThat(response.getStatus()).isEqualTo(HttpStatus.SC_INTERNAL_SERVER_ERROR);
}
@@ -94,8 +89,8 @@ public class RefreshDnsForAllDomainsActionTest {
persistActiveDomain("low.bar");
action.tlds = ImmutableSet.of("bar");
action.run();
verify(dnsQueue).addDomainRefreshTask("foo.bar", Duration.ZERO);
verify(dnsQueue).addDomainRefreshTask("low.bar", Duration.ZERO);
dnsUtilsHelper.assertDomainDnsRequestWithDelay("foo.bar", Duration.ZERO);
dnsUtilsHelper.assertDomainDnsRequestWithDelay("low.bar", Duration.ZERO);
}
@Test
@@ -105,10 +100,8 @@ public class RefreshDnsForAllDomainsActionTest {
action.tlds = ImmutableSet.of("bar");
action.smearMinutes = 1000;
action.run();
ArgumentCaptor<Duration> captor = ArgumentCaptor.forClass(Duration.class);
verify(dnsQueue).addDomainRefreshTask(eq("foo.bar"), captor.capture());
verify(dnsQueue).addDomainRefreshTask(eq("low.bar"), captor.capture());
assertThat(captor.getAllValues()).containsExactly(standardMinutes(450), standardMinutes(782));
dnsUtilsHelper.assertDomainDnsRequestWithDelay("foo.bar", Duration.standardMinutes(450));
dnsUtilsHelper.assertDomainDnsRequestWithDelay("low.bar", Duration.standardMinutes(782));
}
@Test
@@ -117,8 +110,8 @@ public class RefreshDnsForAllDomainsActionTest {
persistDeletedDomain("deleted.bar", clock.nowUtc().minusYears(1));
action.tlds = ImmutableSet.of("bar");
action.run();
verify(dnsQueue).addDomainRefreshTask("foo.bar", Duration.ZERO);
verify(dnsQueue, never()).addDomainRefreshTask("deleted.bar", Duration.ZERO);
dnsUtilsHelper.assertDomainDnsRequestWithDelay("foo.bar", Duration.ZERO);
dnsUtilsHelper.assertNoDomainDnsRequestWithDelay("deleted.bar", Duration.ZERO);
}
@Test
@@ -129,9 +122,9 @@ public class RefreshDnsForAllDomainsActionTest {
persistActiveDomain("ignore.baz");
action.tlds = ImmutableSet.of("bar");
action.run();
verify(dnsQueue).addDomainRefreshTask("foo.bar", Duration.ZERO);
verify(dnsQueue).addDomainRefreshTask("low.bar", Duration.ZERO);
verify(dnsQueue, never()).addDomainRefreshTask("ignore.baz", Duration.ZERO);
dnsUtilsHelper.assertDomainDnsRequestWithDelay("foo.bar", Duration.ZERO);
dnsUtilsHelper.assertDomainDnsRequestWithDelay("low.bar", Duration.ZERO);
dnsUtilsHelper.assertNoDomainDnsRequestWithDelay("ignore.baz", Duration.ZERO);
}
@Test
@@ -0,0 +1,54 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<domain:chkData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:cd>
<domain:name avail="1">rich.example</domain:name>
</domain:cd>
<domain:cd>
<domain:name avail="0">example1.tld</domain:name>
<domain:reason>In use</domain:reason>
</domain:cd>
<domain:cd>
<domain:name avail="1">example2.tld</domain:name>
</domain:cd>
<domain:cd>
<domain:name avail="1">example3.tld</domain:name>
</domain:cd>
</domain:chkData>
</resData>
<extension>
<fee:chkData xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:cd xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:name>rich.example</fee:name>
<fee:currency>USD</fee:currency>
<fee:command>create</fee:command>
<fee:period unit="y">1</fee:period>
<fee:fee description="create">100.00</fee:fee>
<fee:class>premium</fee:class>
</fee:cd>
<fee:cd xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:name>example2.tld</fee:name>
<fee:currency>USD</fee:currency>
<fee:command>create</fee:command>
<fee:period unit="y">1</fee:period>
<fee:fee description="create">4.00</fee:fee>
</fee:cd>
<fee:cd xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:name>example3.tld</fee:name>
<fee:currency>USD</fee:currency>
<fee:command>create</fee:command>
<fee:period unit="y">2</fee:period>
<fee:fee description="create">12.00</fee:fee>
</fee:cd>
</fee:chkData>
</extension>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>
@@ -0,0 +1,70 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<domain:chkData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:cd>
<domain:name avail="1">rich.example</domain:name>
</domain:cd>
<domain:cd>
<domain:name avail="0">example1.tld</domain:name>
<domain:reason>In use</domain:reason>
</domain:cd>
<domain:cd>
<domain:name avail="1">example2.tld</domain:name>
</domain:cd>
<domain:cd>
<domain:name avail="1">example3.tld</domain:name>
</domain:cd>
</domain:chkData>
</resData>
<extension>
<fee:chkData xmlns:fee="urn:ietf:params:xml:ns:fee-0.11"
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<fee:cd avail="1">
<fee:object>
<domain:name>rich.example</domain:name>
</fee:object>
<fee:command>create</fee:command>
<fee:currency>USD</fee:currency>
<fee:period unit="y">1</fee:period>
<fee:fee description="create">100.00</fee:fee>
<fee:class>premium</fee:class>
</fee:cd>
<fee:cd avail="1">
<fee:object>
<domain:name>example1.tld</domain:name>
</fee:object>
<fee:command>create</fee:command>
<fee:currency>USD</fee:currency>
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:cd>
<fee:cd avail="1">
<fee:object>
<domain:name>example2.tld</domain:name>
</fee:object>
<fee:command>create</fee:command>
<fee:currency>USD</fee:currency>
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:cd>
<fee:cd avail="1">
<fee:object>
<domain:name>example3.tld</domain:name>
</fee:object>
<fee:command>create</fee:command>
<fee:currency>USD</fee:currency>
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:cd>
</fee:chkData>
</extension>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>
@@ -0,0 +1,71 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<domain:chkData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:cd>
<domain:name avail="1">rich.example</domain:name>
</domain:cd>
<domain:cd>
<domain:name avail="0">example1.tld</domain:name>
<domain:reason>In use</domain:reason>
</domain:cd>
<domain:cd>
<domain:name avail="1">example2.tld</domain:name>
</domain:cd>
<domain:cd>
<domain:name avail="1">example3.tld</domain:name>
</domain:cd>
</domain:chkData>
</resData>
<extension>
<fee:chkData xmlns:fee="urn:ietf:params:xml:ns:fee-0.12"
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<fee:currency>USD</fee:currency>
<fee:cd>
<fee:object>
<domain:name>rich.example</domain:name>
</fee:object>
<fee:command name="create">
<fee:period unit="y">1</fee:period>
<fee:fee description="create">100.00</fee:fee>
<fee:class>premium</fee:class>
</fee:command>
</fee:cd>
<fee:cd>
<fee:object>
<domain:name>example1.tld</domain:name>
</fee:object>
<fee:command name="create">
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:command>
</fee:cd>
<fee:cd>
<fee:object>
<domain:name>example2.tld</domain:name>
</fee:object>
<fee:command name="create">
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:command>
</fee:cd>
<fee:cd>
<fee:object>
<domain:name>example3.tld</domain:name>
</fee:object>
<fee:command name="create">
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:command>
</fee:cd>
</fee:chkData>
</extension>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>
@@ -0,0 +1,33 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<check>
<domain:check xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>rich.example</domain:name>
<domain:name>example1.example</domain:name>
<domain:name>example2.example</domain:name>
<domain:name>example3.example</domain:name>
</domain:check>
</check>
<extension>
<fee:check xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:domain>
<fee:name>rich.example</fee:name>
<fee:command>create</fee:command>
</fee:domain>
<fee:domain>
<fee:name>example2.tld</fee:name>
<fee:currency>%CURRENCY%</fee:currency>
<fee:command>create</fee:command>
<fee:period unit="y">1</fee:period>
</fee:domain>
<fee:domain>
<fee:name>example3.tld</fee:name>
<fee:currency>%CURRENCY%</fee:currency>
<fee:command>create</fee:command>
<fee:period unit="y">2</fee:period>
</fee:domain>
</fee:check>
</extension>
<clTRID>ABC-12345</clTRID>
</command>
</epp>
@@ -0,0 +1,24 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<check>
<domain:check xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>rich.example</domain:name>
<domain:name>example1.tld</domain:name>
<domain:name>example2.tld</domain:name>
<domain:name>example3.tld</domain:name>
</domain:check>
</check>
<extension>
<launch:check xmlns:launch="urn:ietf:params:xml:ns:launch-1.0" type="avail">
<launch:phase name="foo">custom</launch:phase>
</launch:check>
<fee:check xmlns:fee="urn:ietf:params:xml:ns:fee-0.11">
<fee:command>create</fee:command>
<fee:currency>USD</fee:currency>
<fee:period unit="y">1</fee:period>
<fee:class>premium</fee:class>
</fee:check>
</extension>
<clTRID>ABC-12345</clTRID>
</command>
</epp>
@@ -0,0 +1,25 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<check>
<domain:check xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:name>rich.example</domain:name>
<domain:name>example1.tld</domain:name>
<domain:name>example2.tld</domain:name>
<domain:name>example3.tld</domain:name>
</domain:check>
</check>
<extension>
<launch:check xmlns:launch="urn:ietf:params:xml:ns:launch-1.0" type="avail">
<launch:phase name="foo">custom</launch:phase>
</launch:check>
<fee:check xmlns:fee="urn:ietf:params:xml:ns:fee-0.12">
<fee:currency>USD</fee:currency>
<fee:command name="create">
<fee:period unit="y">1</fee:period>
<fee:class>premium</fee:class>
</fee:command>
</fee:check>
</extension>
<clTRID>ABC-12345</clTRID>
</command>
</epp>
@@ -0,0 +1,57 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<domain:chkData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:cd>
<domain:name avail="1">example1.tld</domain:name>
</domain:cd>
</domain:chkData>
</resData>
<extension>
<fee:chkData xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:cd xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:name>example1.tld</fee:name>
<fee:currency>USD</fee:currency>
<fee:command>create</fee:command>
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:cd>
<fee:cd xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:name>example1.tld</fee:name>
<fee:currency>USD</fee:currency>
<fee:command>renew</fee:command>
<fee:period unit="y">1</fee:period>
<fee:fee description="renew">11.00</fee:fee>
</fee:cd>
<fee:cd xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:name>example1.tld</fee:name>
<fee:currency>USD</fee:currency>
<fee:command>transfer</fee:command>
<fee:period unit="y">1</fee:period>
<fee:fee description="renew">11.00</fee:fee>
</fee:cd>
<fee:cd xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:name>example1.tld</fee:name>
<fee:currency>USD</fee:currency>
<fee:command>restore</fee:command>
<fee:period unit="y">1</fee:period>
<fee:fee description="restore">17.00</fee:fee>
</fee:cd>
<fee:cd xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:name>example1.tld</fee:name>
<fee:currency>USD</fee:currency>
<fee:command>update</fee:command>
<fee:period unit="y">1</fee:period>
<fee:fee description="update">0.00</fee:fee>
</fee:cd>
</fee:chkData>
</extension>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>
@@ -0,0 +1,68 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<domain:chkData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:cd>
<domain:name avail="1">example1.tld</domain:name>
</domain:cd>
</domain:chkData>
</resData>
<extension>
<fee:chkData xmlns:fee="urn:ietf:params:xml:ns:fee-0.12"
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<fee:cd>
<fee:object>
<domain:name>example1.tld</domain:name>
</fee:object>
<fee:command name="create">
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:command>
</fee:cd>
<fee:cd>
<fee:object>
<domain:name>example1.tld</domain:name>
</fee:object>
<fee:command name="renew">
<fee:period unit="y">1</fee:period>
<fee:fee description="renew">11.00</fee:fee>
</fee:command>
</fee:cd>
<fee:cd>
<fee:object>
<domain:name>example1.tld</domain:name>
</fee:object>
<fee:command name="transfer">
<fee:period unit="y">1</fee:period>
<fee:fee description="renew">11.00</fee:fee>
</fee:command>
</fee:cd>
<fee:cd>
<fee:object>
<domain:name>example1.tld</domain:name>
</fee:object>
<fee:command name="restore">
<fee:period unit="y">1</fee:period>
<fee:fee description="restore">17.00</fee:fee>
</fee:command>
</fee:cd>
<fee:cd>
<fee:object>
<domain:name>example1.tld</domain:name>
</fee:object>
<fee:command name="update">
<fee:period unit="y">1</fee:period>
<fee:fee description="update">0.00</fee:fee>
</fee:command>
</fee:cd>
</fee:chkData>
</extension>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>
@@ -0,0 +1,43 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<domain:chkData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:cd>
<domain:name avail="0">example1.tld</domain:name>
<domain:reason>In use</domain:reason>
</domain:cd>
<domain:cd>
<domain:name avail="1">example2.tld</domain:name>
</domain:cd>
<domain:cd>
<domain:name avail="1">example3.tld</domain:name>
</domain:cd>
</domain:chkData>
</resData>
<extension>
<fee:chkData xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:cd xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:name>example2.tld</fee:name>
<fee:currency>USD</fee:currency>
<fee:command>create</fee:command>
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:cd>
<fee:cd xmlns:fee="urn:ietf:params:xml:ns:fee-0.6">
<fee:name>example3.tld</fee:name>
<fee:currency>USD</fee:currency>
<fee:command>create</fee:command>
<fee:period unit="y">2</fee:period>
<fee:fee description="create">19.50</fee:fee>
</fee:cd>
</fee:chkData>
</extension>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>
@@ -0,0 +1,57 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<domain:chkData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:cd>
<domain:name avail="0">example1.tld</domain:name>
<domain:reason>In use</domain:reason>
</domain:cd>
<domain:cd>
<domain:name avail="1">example2.tld</domain:name>
</domain:cd>
<domain:cd>
<domain:name avail="1">example3.tld</domain:name>
</domain:cd>
</domain:chkData>
</resData>
<extension>
<fee:chkData xmlns:fee="urn:ietf:params:xml:ns:fee-0.11"
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<fee:cd avail="1">
<fee:object>
<domain:name>example1.tld</domain:name>
</fee:object>
<fee:command>create</fee:command>
<fee:currency>USD</fee:currency>
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:cd>
<fee:cd avail="1">
<fee:object>
<domain:name>example2.tld</domain:name>
</fee:object>
<fee:command>create</fee:command>
<fee:currency>USD</fee:currency>
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:cd>
<fee:cd avail="1">
<fee:object>
<domain:name>example3.tld</domain:name>
</fee:object>
<fee:command>create</fee:command>
<fee:currency>USD</fee:currency>
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:cd>
</fee:chkData>
</extension>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>
@@ -0,0 +1,58 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<response>
<result code="1000">
<msg>Command completed successfully</msg>
</result>
<resData>
<domain:chkData xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<domain:cd>
<domain:name avail="0">example1.tld</domain:name>
<domain:reason>In use</domain:reason>
</domain:cd>
<domain:cd>
<domain:name avail="1">example2.tld</domain:name>
</domain:cd>
<domain:cd>
<domain:name avail="1">example3.tld</domain:name>
</domain:cd>
</domain:chkData>
</resData>
<extension>
<fee:chkData xmlns:fee="urn:ietf:params:xml:ns:fee-0.12"
xmlns:domain="urn:ietf:params:xml:ns:domain-1.0">
<fee:currency>USD</fee:currency>
<fee:cd>
<fee:object>
<domain:name>example1.tld</domain:name>
</fee:object>
<fee:command name="create">
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:command>
</fee:cd>
<fee:cd>
<fee:object>
<domain:name>example2.tld</domain:name>
</fee:object>
<fee:command name="create">
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:command>
</fee:cd>
<fee:cd>
<fee:object>
<domain:name>example3.tld</domain:name>
</fee:object>
<fee:command name="create">
<fee:period unit="y">1</fee:period>
<fee:fee description="create">6.50</fee:fee>
</fee:command>
</fee:cd>
</fee:chkData>
</extension>
<trID>
<clTRID>ABC-12345</clTRID>
<svTRID>server-trid</svTRID>
</trID>
</response>
</epp>
@@ -261,11 +261,11 @@ td.section {
</tr>
<tr>
<td class="property_name">generated on</td>
<td class="property_value">2023-03-09 22:05:25.449957</td>
<td class="property_value">2023-03-16 20:10:49.374346</td>
</tr>
<tr>
<td class="property_name">last flyway file</td>
<td id="lastFlywayFile" class="property_value">V139__add_allowed_epp_actions_column.sql</td>
<td id="lastFlywayFile" class="property_value">V141__add_ttl_columns_to_tld.sql</td>
</tr>
</tbody>
</table>
@@ -284,7 +284,7 @@ td.section {
generated on
</text>
<text text-anchor="start" x="3835.5" y="-10.8" font-family="Helvetica,sans-Serif" font-size="14.00">
2023-03-09 22:05:25.449957
2023-03-16 20:10:49.374346
</text>
<polygon fill="none" stroke="#888888" points="3748,-4 3748,-44 4013,-44 4013,-4 3748,-4" /> <!-- allocationtoken_a08ccbef -->
<g id="node1" class="node">
@@ -2255,12 +2255,12 @@ td.section {
<text text-anchor="start" x="3676.5" y="-2039.8" font-family="Helvetica,sans-Serif" font-weight="bold" font-style="italic" font-size="14.00">
id
</text>
<text text-anchor="start" x="3803.5" y="-2038.8" font-family="Helvetica,sans-Serif" font-size="14.00">
<text text-anchor="start" x="3817.5" y="-2038.8" font-family="Helvetica,sans-Serif" font-size="14.00">
</text>
<text text-anchor="start" x="3853.5" y="-2038.8" font-family="Helvetica,sans-Serif" font-size="14.00">
bigserial not null
</text>
<text text-anchor="start" x="3803.5" y="-2019.8" font-family="Helvetica,sans-Serif" font-size="14.00">
<text text-anchor="start" x="3817.5" y="-2019.8" font-family="Helvetica,sans-Serif" font-size="14.00">
</text>
<text text-anchor="start" x="3853.5" y="-2019.8" font-family="Helvetica,sans-Serif" font-size="14.00">
auto-incremented
@@ -2268,15 +2268,15 @@ td.section {
<text text-anchor="start" x="3676.5" y="-2000.8" font-family="Helvetica,sans-Serif" font-size="14.00">
request_time
</text>
<text text-anchor="start" x="3803.5" y="-2000.8" font-family="Helvetica,sans-Serif" font-size="14.00">
<text text-anchor="start" x="3817.5" y="-2000.8" font-family="Helvetica,sans-Serif" font-size="14.00">
</text>
<text text-anchor="start" x="3853.5" y="-2000.8" font-family="Helvetica,sans-Serif" font-size="14.00">
timestamptz not null
</text>
<text text-anchor="start" x="3676.5" y="-1981.8" font-family="Helvetica,sans-Serif" font-size="14.00">
process_time
last_process_time
</text>
<text text-anchor="start" x="3803.5" y="-1981.8" font-family="Helvetica,sans-Serif" font-size="14.00">
<text text-anchor="start" x="3817.5" y="-1981.8" font-family="Helvetica,sans-Serif" font-size="14.00">
</text>
<text text-anchor="start" x="3853.5" y="-1981.8" font-family="Helvetica,sans-Serif" font-size="14.00">
timestamptz not null
@@ -4432,7 +4432,7 @@ td.section {
</tr>
<tr>
<td class="spacer"></td>
<td class="minwidth">process_time</td>
<td class="minwidth">last_process_time</td>
<td class="minwidth">timestamptz not null</td>
</tr>
<tr>
File diff suppressed because it is too large Load Diff
+2
View File
@@ -137,3 +137,5 @@ V136__add_dns_refresh_request_table.sql
V137__add_process_time_column.sql
V138__drop_dns_refresh_request_time_column.sql
V139__add_allowed_epp_actions_column.sql
V140__rename_process_time_column_in_dns_refresh_request_table.sql
V141__add_ttl_columns_to_tld.sql
@@ -0,0 +1,20 @@
-- Copyright 2023 The Nomulus Authors. All Rights Reserved.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
ALTER TABLE "DnsRefreshRequest" RENAME COLUMN process_time TO last_process_time;
CREATE INDEX IDXfdk2xpil2x1gh0omt84k2y3o1 ON "DnsRefreshRequest" (last_process_time);
DROP INDEX IDX3i7i2ktts9d7lcjbs34h0pvwo;
@@ -0,0 +1,18 @@
-- Copyright 2023 The Nomulus Authors. All Rights Reserved.
--
-- Licensed under the Apache License, Version 2.0 (the "License");
-- you may not use this file except in compliance with the License.
-- You may obtain a copy of the License at
--
-- http://www.apache.org/licenses/LICENSE-2.0
--
-- Unless required by applicable law or agreed to in writing, software
-- distributed under the License is distributed on an "AS IS" BASIS,
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-- See the License for the specific language governing permissions and
-- limitations under the License.
ALTER TABLE "Tld"
ADD COLUMN dns_a_plus_aaaa_ttl interval,
ADD COLUMN dns_ds_ttl interval,
ADD COLUMN dns_ns_ttl interval;
@@ -16,6 +16,7 @@
token text not null,
update_timestamp timestamptz,
allowed_registrar_ids text[],
allowed_epp_actions text[],
allowed_tlds text[],
creation_time timestamptz not null,
discount_fraction float8 not null,
@@ -255,6 +256,16 @@
primary key (algorithm, digest, digest_type, domain_repo_id, key_tag)
);
create table "DnsRefreshRequest" (
id bigserial not null,
last_process_time timestamptz not null,
name text not null,
request_time timestamptz not null,
tld text not null,
type text not null,
primary key (id)
);
create table "Domain" (
repo_id text not null,
update_timestamp timestamptz,
@@ -786,6 +797,8 @@ create index IDXhp33wybmb6tbpr1bq7ttwk8je on "ContactHistory" (history_registrar
create index IDX9q53px6r302ftgisqifmc6put on "ContactHistory" (history_type);
create index IDXsudwswtwqnfnx2o1hx4s0k0g5 on "ContactHistory" (history_modification_time);
create index IDXhlqqd5uy98cjyos72d81x9j95 on "DelegationSignerData" (domain_repo_id);
create index IDX8gtvnbk64yskcvrdp61f5ied3 on "DnsRefreshRequest" (request_time);
create index IDXfdk2xpil2x1gh0omt84k2y3o1 on "DnsRefreshRequest" (last_process_time);
create index IDXnb02m43jcx24r64n8rbg22u4q on "Domain" (admin_contact);
create index IDXlrq7v63pc21uoh3auq6eybyhl on "Domain" (autorenew_end_time);
create index IDXq9gy8x2xynt9tb16yajn1gcm8 on "Domain" (billing_contact);
@@ -351,7 +351,7 @@ CREATE TABLE public."DnsRefreshRequest" (
request_time timestamp with time zone NOT NULL,
tld text NOT NULL,
type text NOT NULL,
process_time timestamp with time zone NOT NULL
last_process_time timestamp with time zone NOT NULL
);
@@ -1092,7 +1092,10 @@ CREATE TABLE public."Tld" (
tld_type text NOT NULL,
tld_unicode text NOT NULL,
transfer_grace_period_length interval NOT NULL,
default_promo_tokens text[]
default_promo_tokens text[],
dns_a_plus_aaaa_ttl interval,
dns_ds_ttl interval,
dns_ns_ttl interval
);
@@ -1618,13 +1621,6 @@ CREATE INDEX idx1rcgkdd777bpvj0r94sltwd5y ON public."Domain" USING btree (domain
CREATE INDEX idx2exdfbx6oiiwnhr8j6gjpqt2j ON public."BillingCancellation" USING btree (event_time);
--
-- Name: idx3i7i2ktts9d7lcjbs34h0pvwo; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX idx3i7i2ktts9d7lcjbs34h0pvwo ON public."DnsRefreshRequest" USING btree (process_time);
--
-- Name: idx3y3k7m2bkgahm9sixiohgyrga; Type: INDEX; Schema: public; Owner: -
--
@@ -1821,6 +1817,13 @@ CREATE INDEX idxe7wu46c7wpvfmfnj4565abibp ON public."PollMessage" USING btree (r
CREATE INDEX idxeokttmxtpq2hohcioe5t2242b ON public."BillingCancellation" USING btree (registrar_id);
--
-- Name: idxfdk2xpil2x1gh0omt84k2y3o1; Type: INDEX; Schema: public; Owner: -
--
CREATE INDEX idxfdk2xpil2x1gh0omt84k2y3o1 ON public."DnsRefreshRequest" USING btree (last_process_time);
--
-- Name: idxfg2nnjlujxo6cb9fha971bq2n; Type: INDEX; Schema: public; Owner: -
--