1
0
mirror of https://github.com/google/nomulus synced 2025-12-23 06:15:42 +00:00

Update LoadTestAction for GKE and no-contacts (#2800)

It's necessary to remove the GAE-related code (and use GKE launch
commands instead), and we might as well remove contact-related fields
and actions because of the upcoming move to the minimum data set.
This commit is contained in:
gbrodman
2025-08-13 14:35:46 -04:00
committed by GitHub
parent cc347264f1
commit d23640a54f
10 changed files with 28 additions and 201 deletions

View File

@@ -17,10 +17,7 @@ package google.registry.loadtest;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.collect.Lists.partition;
import static google.registry.security.XsrfTokenManager.X_CSRF_TOKEN;
import static google.registry.util.ResourceUtils.readResourceUtf8;
import static java.util.Arrays.asList;
import static org.joda.time.DateTimeZone.UTC;
import com.google.cloud.tasks.v2.Task;
import com.google.common.collect.ImmutableList;
@@ -34,7 +31,7 @@ import google.registry.request.Action;
import google.registry.request.Action.GaeService;
import google.registry.request.Parameter;
import google.registry.request.auth.Auth;
import google.registry.security.XsrfTokenManager;
import google.registry.util.Clock;
import google.registry.util.RegistryEnvironment;
import jakarta.inject.Inject;
import java.time.Instant;
@@ -67,11 +64,9 @@ public class LoadTestAction implements Runnable {
private static final int NUM_QUEUES = 10;
private static final int MAX_TASKS_PER_LOAD = 100;
private static final int ARBITRARY_VALID_HOST_LENGTH = 40;
private static final int MAX_CONTACT_LENGTH = 13;
private static final int MAX_DOMAIN_LABEL_LENGTH = 63;
private static final String EXISTING_DOMAIN = "testdomain";
private static final String EXISTING_CONTACT = "contact";
private static final String EXISTING_HOST = "ns1";
private static final Random random = new Random();
@@ -85,8 +80,8 @@ public class LoadTestAction implements Runnable {
/**
* The number of seconds to delay the execution of the first load testing tasks by. Preparatory
* work of creating independent contacts and hosts that will be used for later domain creation
* testing occurs during this period, so make sure that it is long enough.
* work of creating independent hosts that will be used for later domain creation testing occurs
* during this period, so make sure that it is long enough.
*/
@Inject
@Parameter("delaySeconds")
@@ -120,21 +115,6 @@ public class LoadTestAction implements Runnable {
@Parameter("domainChecks")
int domainChecksPerSecond;
/** The number of successful contact creates to enqueue per second over the length of the test. */
@Inject
@Parameter("successfulContactCreates")
int successfulContactCreatesPerSecond;
/** The number of failed contact creates to enqueue per second over the length of the test. */
@Inject
@Parameter("failedContactCreates")
int failedContactCreatesPerSecond;
/** The number of successful contact infos to enqueue per second over the length of the test. */
@Inject
@Parameter("contactInfos")
int contactInfosPerSecond;
/** The number of successful host creates to enqueue per second over the length of the test. */
@Inject
@Parameter("successfulHostCreates")
@@ -152,9 +132,8 @@ public class LoadTestAction implements Runnable {
@Inject CloudTasksUtils cloudTasksUtils;
private final String xmlContactCreateTmpl;
private final String xmlContactCreateFail;
private final String xmlContactInfo;
@Inject Clock clock;
private final String xmlDomainCheck;
private final String xmlDomainCreateTmpl;
private final String xmlDomainCreateFail;
@@ -163,53 +142,35 @@ public class LoadTestAction implements Runnable {
private final String xmlHostCreateFail;
private final String xmlHostInfo;
/**
* The XSRF token to be used for making requests to the epptool endpoint.
*
* <p>Note that the email address is set to empty, because the logged-in user hitting this
* endpoint will not be the same as when the tasks themselves fire and hit the epptool endpoint.
*/
private final String xsrfToken;
@Inject
LoadTestAction(@Parameter("tld") String tld, XsrfTokenManager xsrfTokenManager) {
xmlContactCreateTmpl = loadXml("contact_create");
xmlContactCreateFail = xmlContactCreateTmpl.replace("%contact%", EXISTING_CONTACT);
xmlContactInfo = loadXml("contact_info").replace("%contact%", EXISTING_CONTACT);
LoadTestAction(@Parameter("tld") String tld) {
xmlDomainCheck =
loadXml("domain_check").replace("%tld%", tld).replace("%domain%", EXISTING_DOMAIN);
xmlDomainCreateTmpl = loadXml("domain_create").replace("%tld%", tld);
xmlDomainCreateFail =
xmlDomainCreateTmpl
.replace("%domain%", EXISTING_DOMAIN)
.replace("%contact%", EXISTING_CONTACT)
.replace("%host%", EXISTING_HOST);
xmlDomainInfo =
loadXml("domain_info").replace("%tld%", tld).replace("%domain%", EXISTING_DOMAIN);
xmlHostCreateTmpl = loadXml("host_create");
xmlHostCreateFail = xmlHostCreateTmpl.replace("%host%", EXISTING_HOST);
xmlHostInfo = loadXml("host_info").replace("%host%", EXISTING_HOST);
xsrfToken = xsrfTokenManager.generateToken("");
}
@Override
public void run() {
validateAndLogRequest();
DateTime initialStartSecond = DateTime.now(UTC).plusSeconds(delaySeconds);
DateTime initialStartSecond = clock.nowUtc().plusSeconds(delaySeconds);
ImmutableList.Builder<String> preTaskXmls = new ImmutableList.Builder<>();
ImmutableList.Builder<String> contactNamesBuilder = new ImmutableList.Builder<>();
ImmutableList.Builder<String> hostPrefixesBuilder = new ImmutableList.Builder<>();
for (int i = 0; i < successfulDomainCreatesPerSecond; i++) {
String contactName = getRandomLabel(MAX_CONTACT_LENGTH);
String hostPrefix = getRandomLabel(ARBITRARY_VALID_HOST_LENGTH);
contactNamesBuilder.add(contactName);
hostPrefixesBuilder.add(hostPrefix);
preTaskXmls.add(
xmlContactCreateTmpl.replace("%contact%", contactName),
xmlHostCreateTmpl.replace("%host%", hostPrefix));
}
enqueue(createTasks(preTaskXmls.build(), DateTime.now(UTC)));
ImmutableList<String> contactNames = contactNamesBuilder.build();
enqueue(createTasks(preTaskXmls.build(), clock.nowUtc()));
ImmutableList<String> hostPrefixes = hostPrefixesBuilder.build();
ImmutableList.Builder<Task> tasks = new ImmutableList.Builder<>();
@@ -217,30 +178,17 @@ public class LoadTestAction implements Runnable {
DateTime startSecond = initialStartSecond.plusSeconds(offsetSeconds);
// The first "failed" creates might actually succeed if the object doesn't already exist, but
// that shouldn't affect the load numbers.
tasks.addAll(
createTasks(
createNumCopies(xmlContactCreateFail, failedContactCreatesPerSecond), startSecond));
tasks.addAll(
createTasks(createNumCopies(xmlHostCreateFail, failedHostCreatesPerSecond), startSecond));
tasks.addAll(
createTasks(
createNumCopies(xmlDomainCreateFail, failedDomainCreatesPerSecond), startSecond));
// We can do infos on the known existing objects.
tasks.addAll(
createTasks(createNumCopies(xmlContactInfo, contactInfosPerSecond), startSecond));
tasks.addAll(createTasks(createNumCopies(xmlHostInfo, hostInfosPerSecond), startSecond));
tasks.addAll(createTasks(createNumCopies(xmlDomainInfo, domainInfosPerSecond), startSecond));
// The domain check template uses "example.TLD" which won't exist, and one existing domain.
tasks.addAll(
createTasks(createNumCopies(xmlDomainCheck, domainChecksPerSecond), startSecond));
// Do successful creates on random names
tasks.addAll(
createTasks(
createNumCopies(xmlContactCreateTmpl, successfulContactCreatesPerSecond)
.stream()
.map(randomNameReplacer("%contact%", MAX_CONTACT_LENGTH))
.collect(toImmutableList()),
startSecond));
tasks.addAll(
createTasks(
createNumCopies(xmlHostCreateTmpl, successfulHostCreatesPerSecond)
@@ -253,7 +201,6 @@ public class LoadTestAction implements Runnable {
createNumCopies(xmlDomainCreateTmpl, successfulDomainCreatesPerSecond)
.stream()
.map(randomNameReplacer("%domain%", MAX_DOMAIN_LABEL_LENGTH))
.map(listNameReplacer("%contact%", contactNames))
.map(listNameReplacer("%host%", hostPrefixes))
.collect(toImmutableList()),
startSecond));
@@ -272,9 +219,6 @@ public class LoadTestAction implements Runnable {
|| failedDomainCreatesPerSecond > 0
|| domainInfosPerSecond > 0
|| domainChecksPerSecond > 0
|| successfulContactCreatesPerSecond > 0
|| failedContactCreatesPerSecond > 0
|| contactInfosPerSecond > 0
|| successfulHostCreatesPerSecond > 0
|| failedHostCreatesPerSecond > 0
|| hostInfosPerSecond > 0,
@@ -282,8 +226,7 @@ public class LoadTestAction implements Runnable {
logger.atInfo().log(
"Running load test with the following params. registrarId: %s, delaySeconds: %d, "
+ "runSeconds: %d, successful|failed domain creates/s: %d|%d, domain infos/s: %d, "
+ "domain checks/s: %d, successful|failed contact creates/s: %d|%d, "
+ "contact infos/s: %d, successful|failed host creates/s: %d|%d, host infos/s: %d.",
+ "domain checks/s: %d, successful|failed host creates/s: %d|%d, host infos/s: %d.",
registrarId,
delaySeconds,
runSeconds,
@@ -291,9 +234,6 @@ public class LoadTestAction implements Runnable {
failedDomainCreatesPerSecond,
domainInfosPerSecond,
domainChecksPerSecond,
successfulContactCreatesPerSecond,
failedContactCreatesPerSecond,
contactInfosPerSecond,
successfulHostCreatesPerSecond,
failedHostCreatesPerSecond,
hostInfosPerSecond);
@@ -303,10 +243,10 @@ public class LoadTestAction implements Runnable {
return readResourceUtf8(LoadTestAction.class, String.format("templates/%s.xml", name));
}
private List<String> createNumCopies(String xml, int numCopies) {
private ImmutableList<String> createNumCopies(String xml, int numCopies) {
String[] xmls = new String[numCopies];
Arrays.fill(xmls, xml);
return asList(xmls);
return ImmutableList.copyOf(xmls);
}
private Function<String, String> listNameReplacer(final String toReplace, List<String> choices) {
@@ -326,35 +266,27 @@ public class LoadTestAction implements Runnable {
return name.toString();
}
private List<Task> createTasks(List<String> xmls, DateTime start) {
private ImmutableList<Task> createTasks(ImmutableList<String> xmls, DateTime start) {
ImmutableList.Builder<Task> tasks = new ImmutableList.Builder<>();
for (int i = 0; i < xmls.size(); i++) {
// Space tasks evenly within across a second.
Instant scheduleTime =
Instant.ofEpochMilli(start.plusMillis((int) (1000.0 / xmls.size() * i)).getMillis());
tasks.add(
Task.newBuilder()
.setAppEngineHttpRequest(
cloudTasksUtils
.createTask(
EppToolAction.class,
Action.Method.POST,
ImmutableMultimap.of(
"clientId",
registrarId,
"superuser",
Boolean.FALSE.toString(),
"dryRun",
Boolean.FALSE.toString(),
"xml",
xmls.get(i)))
.toBuilder()
.getAppEngineHttpRequest()
.toBuilder()
// TODO: investigate if the following is necessary now that
// LegacyAuthenticationMechanism is gone.
.putHeaders(X_CSRF_TOKEN, xsrfToken)
.build())
cloudTasksUtils
.createTask(
EppToolAction.class,
Action.Method.POST,
ImmutableMultimap.of(
"clientId",
registrarId,
"superuser",
Boolean.FALSE.toString(),
"dryRun",
Boolean.FALSE.toString(),
"xml",
xmls.get(i)))
.toBuilder()
.setScheduleTime(
Timestamp.newBuilder()
.setSeconds(scheduleTime.getEpochSecond())
@@ -365,7 +297,7 @@ public class LoadTestAction implements Runnable {
return tasks.build();
}
private void enqueue(List<Task> tasks) {
private void enqueue(ImmutableList<Task> tasks) {
List<List<Task>> chunks = partition(tasks, MAX_TASKS_PER_LOAD);
// Farm out tasks to multiple queues to work around queue qps quotas.
for (int i = 0; i < chunks.size(); i++) {

View File

@@ -1,33 +0,0 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<create>
<contact:create
xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
<contact:id>%contact%</contact:id>
<contact:postalInfo type="int">
<contact:name>John Doe</contact:name>
<contact:org>Example Inc.</contact:org>
<contact:addr>
<contact:street>123 Example Dr.</contact:street>
<contact:street>Suite 100</contact:street>
<contact:city>Dulles</contact:city>
<contact:sp>VA</contact:sp>
<contact:pc>20166-6503</contact:pc>
<contact:cc>US</contact:cc>
</contact:addr>
</contact:postalInfo>
<contact:voice x="1234">+1.7035555555</contact:voice>
<contact:fax>+1.7035555556</contact:fax>
<contact:email>jdoe@example.com</contact:email>
<contact:authInfo>
<contact:pw>2fooBAR</contact:pw>
</contact:authInfo>
<contact:disclose flag="1">
<contact:voice/>
<contact:email/>
</contact:disclose>
</contact:create>
</create>
<clTRID>trid</clTRID>
</command>
</epp>

View File

@@ -1,14 +0,0 @@
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<info>
<contact:info
xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
<contact:id>%contact%</contact:id>
<contact:authInfo>
<contact:pw>2fooBAR</contact:pw>
</contact:authInfo>
</contact:info>
</info>
<clTRID>trid</clTRID>
</command>
</epp>

View File

@@ -8,9 +8,6 @@
<domain:ns>
<domain:hostObj>%host%.example.com</domain:hostObj>
</domain:ns>
<domain:registrant>%contact%</domain:registrant>
<domain:contact type="admin">%contact%</domain:contact>
<domain:contact type="tech">%contact%</domain:contact>
<domain:authInfo>
<domain:pw>2fooBAR</domain:pw>
</domain:authInfo>

View File

@@ -4,6 +4,7 @@
<host:create
xmlns:host="urn:ietf:params:xml:ns:host-1.0">
<host:name>%host%.example.com</host:name>
<host:addr ip="v4">8.8.8.8</host:addr>
</host:create>
</create>
<clTRID>trid</clTRID>

View File

@@ -14,7 +14,6 @@
package google.registry.tools;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.Parameters;
import com.google.common.collect.ImmutableMap;
@@ -52,11 +51,6 @@ class LoadTestCommand extends ConfirmingCommand implements CommandWithConnection
description = "Number of domains to create per second.")
int successfulDomainCreates = 1;
@Parameter(
names = {"--successful_contact_creates"},
description = "Number of contact records to create per second.")
int successfulContactCreates = 1;
@Parameter(
names = {"--host_infos"},
description = "Number of successful host:info commands to send per second.")
@@ -67,11 +61,6 @@ class LoadTestCommand extends ConfirmingCommand implements CommandWithConnection
description = "Number of successful domain:info commands to send per second.")
int domainInfos = 1;
@Parameter(
names = {"--contact_infos"},
description = "Number of successful contact:info commands to send per second.")
int contactInfos = 1;
@Parameter(
names = {"--run_seconds"},
description = "Time to run the load test in seconds.")
@@ -120,10 +109,8 @@ class LoadTestCommand extends ConfirmingCommand implements CommandWithConnection
.put("clientId", clientId)
.put("successfulHostCreates", successfulHostCreates)
.put("successfulDomainCreates", successfulDomainCreates)
.put("successfulContactCreates", successfulContactCreates)
.put("hostInfos", hostInfos)
.put("domainInfos", domainInfos)
.put("contactInfos", contactInfos)
.put("runSeconds", runSeconds)
.build();

View File

@@ -35,7 +35,6 @@ import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.CharStreams;
import com.google.common.net.MediaType;
import com.google.re2j.Pattern;
import google.registry.config.RegistryConfig.Config;
import google.registry.request.Action.GaeService;
import google.registry.request.Action.GkeService;
@@ -56,9 +55,6 @@ import org.json.simple.JSONValue;
*/
public class ServiceConnection {
/** Pattern to heuristically extract title tag contents in HTML responses. */
protected static final Pattern HTML_TITLE_TAG_PATTERN = Pattern.compile("<title>(.*?)</title>");
private final Service service;
private final boolean useCanary;
private final HttpRequestFactory requestFactory;

View File

@@ -50,10 +50,8 @@ class LoadTestCommandTest extends CommandTestCase<LoadTestCommand> {
.put("clientId", "acme")
.put("successfulHostCreates", 1)
.put("successfulDomainCreates", 1)
.put("successfulContactCreates", 1)
.put("hostInfos", 1)
.put("domainInfos", 1)
.put("contactInfos", 1)
.put("runSeconds", 9200)
.build();
verify(connection)
@@ -69,10 +67,8 @@ class LoadTestCommandTest extends CommandTestCase<LoadTestCommand> {
"--client_id=NewRegistrar",
"--successful_host_creates=10",
"--successful_domain_creates=11",
"--successful_contact_creates=12",
"--host_infos=13",
"--domain_infos=14",
"--contact_infos=15",
"--run_seconds=16");
ImmutableMap<String, Object> params =
new ImmutableMap.Builder<String, Object>()
@@ -80,10 +76,8 @@ class LoadTestCommandTest extends CommandTestCase<LoadTestCommand> {
.put("clientId", "NewRegistrar")
.put("successfulHostCreates", 10)
.put("successfulDomainCreates", 11)
.put("successfulContactCreates", 12)
.put("hostInfos", 13)
.put("domainInfos", 14)
.put("contactInfos", 15)
.put("runSeconds", 16)
.build();
verify(connection)

View File

@@ -1,30 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<epp xmlns="urn:ietf:params:xml:ns:epp-1.0">
<command>
<create>
<contact:create
xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
<contact:id>@@RANDOM_CONTACT@@-@@CHANNEL_NUMBER@@</contact:id>
<contact:postalInfo type="int">
<contact:name>John Doe</contact:name>
<contact:org>Example, Inc.</contact:org>
<contact:addr>
<contact:street>111 Example Street</contact:street>
<contact:street></contact:street>
<contact:city>Los Angeles</contact:city>
<contact:sp>CA</contact:sp>
<contact:pc>90210</contact:pc>
<contact:cc>US</contact:cc>
</contact:addr>
</contact:postalInfo>
<contact:voice>+1.2020202022</contact:voice>
<contact:fax>+1.2022022022</contact:fax>
<contact:email>test@email.com</contact:email>
<contact:authInfo>
<contact:pw>somepassword</contact:pw>
</contact:authInfo>
</contact:create>
</create>
<clTRID>epp-client-contact-create-@@NOW@@-@@CHANNEL_NUMBER@@</clTRID>
</command>
</epp>

View File

@@ -9,9 +9,6 @@
<domain:ns>
<domain:hostObj>ns1.domain.com</domain:hostObj>
</domain:ns>
<domain:registrant>@@RANDOM_CONTACT@@-@@CHANNEL_NUMBER@@</domain:registrant>
<domain:contact type="admin">@@RANDOM_CONTACT@@-@@CHANNEL_NUMBER@@</domain:contact>
<domain:contact type="tech">@@RANDOM_CONTACT@@-@@CHANNEL_NUMBER@@</domain:contact>
<domain:authInfo>
<domain:pw>somepassword</domain:pw>
</domain:authInfo>