mirror of
https://github.com/google/nomulus.git
synced 2025-07-07 11:43:24 +02:00
Allow command to enqueue poll messages for multiple registrars (#1446)
* Allow command to enqueue poll messages for multiple registrars
This commit is contained in:
parent
0a31e6e71c
commit
a96db1f236
4 changed files with 137 additions and 23 deletions
|
@ -18,14 +18,21 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
import static google.registry.model.EppResourceUtils.loadByForeignKey;
|
||||||
import static google.registry.model.reporting.HistoryEntry.Type.SYNTHETIC;
|
import static google.registry.model.reporting.HistoryEntry.Type.SYNTHETIC;
|
||||||
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
import static google.registry.persistence.transaction.TransactionManagerFactory.tm;
|
||||||
|
import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
||||||
|
|
||||||
import com.beust.jcommander.Parameter;
|
import com.beust.jcommander.Parameter;
|
||||||
import com.beust.jcommander.Parameters;
|
import com.beust.jcommander.Parameters;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.Streams;
|
||||||
|
import google.registry.config.RegistryConfig.Config;
|
||||||
import google.registry.model.domain.DomainBase;
|
import google.registry.model.domain.DomainBase;
|
||||||
import google.registry.model.domain.DomainHistory;
|
import google.registry.model.domain.DomainHistory;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
|
import google.registry.model.registrar.Registrar;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tool to enqueue a poll message for a registrar.
|
* Tool to enqueue a poll message for a registrar.
|
||||||
|
@ -54,14 +61,26 @@ class EnqueuePollMessageCommand extends MutatingCommand {
|
||||||
String domainName;
|
String domainName;
|
||||||
|
|
||||||
@Parameter(
|
@Parameter(
|
||||||
names = {"-c", "--client"},
|
names = {"-c", "--clients"},
|
||||||
description =
|
description =
|
||||||
"Client identifier of the registrar to send the poll message to, if not the owning"
|
"Comma-delimited list of the client identifier(s) of the registrar(s) to send the poll"
|
||||||
+ " registrar of the domain")
|
+ " message to, if not the owning registrar of the domain")
|
||||||
String clientId;
|
List<String> clientIds;
|
||||||
|
|
||||||
|
@Parameter(
|
||||||
|
names = {"-a", "--all"},
|
||||||
|
description = "Whether to send the message to all real registrars",
|
||||||
|
arity = 1)
|
||||||
|
boolean sendToAll;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@Config("registryAdminClientId")
|
||||||
|
String registryAdminClientId;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final void init() {
|
protected final void init() {
|
||||||
|
checkArgument(
|
||||||
|
!sendToAll || isNullOrEmpty(clientIds), "Cannot specify both --all and --clients");
|
||||||
tm().transact(
|
tm().transact(
|
||||||
() -> {
|
() -> {
|
||||||
Optional<DomainBase> domainOpt =
|
Optional<DomainBase> domainOpt =
|
||||||
|
@ -69,27 +88,39 @@ class EnqueuePollMessageCommand extends MutatingCommand {
|
||||||
checkArgument(
|
checkArgument(
|
||||||
domainOpt.isPresent(), "Domain %s doesn't exist or isn't active", domainName);
|
domainOpt.isPresent(), "Domain %s doesn't exist or isn't active", domainName);
|
||||||
DomainBase domain = domainOpt.get();
|
DomainBase domain = domainOpt.get();
|
||||||
String registrarId =
|
ImmutableList<String> registrarIds;
|
||||||
Optional.ofNullable(clientId).orElse(domain.getCurrentSponsorRegistrarId());
|
if (sendToAll) {
|
||||||
|
registrarIds =
|
||||||
|
Streams.stream(Registrar.loadAllCached())
|
||||||
|
.filter(r -> r.isLive() && r.getType() == Registrar.Type.REAL)
|
||||||
|
.map(Registrar::getRegistrarId)
|
||||||
|
.collect(ImmutableList.toImmutableList());
|
||||||
|
} else if (!isNullOrEmpty(clientIds)) {
|
||||||
|
registrarIds = ImmutableList.copyOf(clientIds);
|
||||||
|
} else {
|
||||||
|
registrarIds = ImmutableList.of(domain.getCurrentSponsorRegistrarId());
|
||||||
|
}
|
||||||
HistoryEntry historyEntry =
|
HistoryEntry historyEntry =
|
||||||
new DomainHistory.Builder()
|
new DomainHistory.Builder()
|
||||||
.setDomain(domain)
|
.setDomain(domain)
|
||||||
.setType(SYNTHETIC)
|
.setType(SYNTHETIC)
|
||||||
.setBySuperuser(true)
|
.setBySuperuser(true)
|
||||||
.setReason("Manual enqueueing of poll message")
|
.setReason("Manual enqueueing of poll message: " + message)
|
||||||
.setModificationTime(tm().getTransactionTime())
|
.setModificationTime(tm().getTransactionTime())
|
||||||
.setRequestedByRegistrar(false)
|
.setRequestedByRegistrar(false)
|
||||||
.setRegistrarId(registrarId)
|
.setRegistrarId(registryAdminClientId)
|
||||||
.build();
|
|
||||||
PollMessage.OneTime pollMessage =
|
|
||||||
new PollMessage.OneTime.Builder()
|
|
||||||
.setRegistrarId(registrarId)
|
|
||||||
.setParent(historyEntry)
|
|
||||||
.setEventTime(tm().getTransactionTime())
|
|
||||||
.setMsg(message)
|
|
||||||
.build();
|
.build();
|
||||||
stageEntityChange(null, historyEntry);
|
stageEntityChange(null, historyEntry);
|
||||||
stageEntityChange(null, pollMessage);
|
for (String registrarId : registrarIds) {
|
||||||
|
stageEntityChange(
|
||||||
|
null,
|
||||||
|
new PollMessage.OneTime.Builder()
|
||||||
|
.setRegistrarId(registrarId)
|
||||||
|
.setParent(historyEntry)
|
||||||
|
.setEventTime(tm().getTransactionTime())
|
||||||
|
.setMsg(message)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -344,7 +344,7 @@ public class SyncRegistrarsSheetTest {
|
||||||
ImmutableMap<String, String> row = getOnlyElement(getOnlyElement(rowsCaptor.getAllValues()));
|
ImmutableMap<String, String> row = getOnlyElement(getOnlyElement(rowsCaptor.getAllValues()));
|
||||||
assertThat(row).containsEntry("clientIdentifier", "SomeRegistrar");
|
assertThat(row).containsEntry("clientIdentifier", "SomeRegistrar");
|
||||||
assertThat(row).containsEntry("registrarName", "Some Registrar");
|
assertThat(row).containsEntry("registrarName", "Some Registrar");
|
||||||
assertThat(row).containsEntry("state", "");
|
assertThat(row).containsEntry("state", "ACTIVE");
|
||||||
assertThat(row).containsEntry("ianaIdentifier", "8");
|
assertThat(row).containsEntry("ianaIdentifier", "8");
|
||||||
assertThat(row).containsEntry("billingIdentifier", "");
|
assertThat(row).containsEntry("billingIdentifier", "");
|
||||||
assertThat(row).containsEntry("primaryContacts", "");
|
assertThat(row).containsEntry("primaryContacts", "");
|
||||||
|
|
|
@ -96,6 +96,7 @@ import google.registry.model.index.ForeignKeyIndex;
|
||||||
import google.registry.model.poll.PollMessage;
|
import google.registry.model.poll.PollMessage;
|
||||||
import google.registry.model.pricing.StaticPremiumListPricingEngine;
|
import google.registry.model.pricing.StaticPremiumListPricingEngine;
|
||||||
import google.registry.model.registrar.Registrar;
|
import google.registry.model.registrar.Registrar;
|
||||||
|
import google.registry.model.registrar.Registrar.State;
|
||||||
import google.registry.model.registrar.RegistrarAddress;
|
import google.registry.model.registrar.RegistrarAddress;
|
||||||
import google.registry.model.reporting.HistoryEntry;
|
import google.registry.model.reporting.HistoryEntry;
|
||||||
import google.registry.model.reporting.HistoryEntryDao;
|
import google.registry.model.reporting.HistoryEntryDao;
|
||||||
|
@ -758,6 +759,7 @@ public class DatabaseHelper {
|
||||||
.setRegistrarId(registrarId)
|
.setRegistrarId(registrarId)
|
||||||
.setRegistrarName(registrarName)
|
.setRegistrarName(registrarName)
|
||||||
.setType(type)
|
.setType(type)
|
||||||
|
.setState(State.ACTIVE)
|
||||||
.setIanaIdentifier(ianaIdentifier)
|
.setIanaIdentifier(ianaIdentifier)
|
||||||
.setLocalizedAddress(
|
.setLocalizedAddress(
|
||||||
new RegistrarAddress.Builder()
|
new RegistrarAddress.Builder()
|
||||||
|
|
|
@ -20,6 +20,7 @@ import static google.registry.testing.DatabaseHelper.assertPollMessages;
|
||||||
import static google.registry.testing.DatabaseHelper.createTld;
|
import static google.registry.testing.DatabaseHelper.createTld;
|
||||||
import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType;
|
import static google.registry.testing.DatabaseHelper.getOnlyHistoryEntryOfType;
|
||||||
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
|
import static google.registry.testing.DatabaseHelper.persistActiveDomain;
|
||||||
|
import static google.registry.testing.DatabaseHelper.persistNewRegistrar;
|
||||||
import static google.registry.testing.HistoryEntrySubject.assertAboutHistoryEntries;
|
import static google.registry.testing.HistoryEntrySubject.assertAboutHistoryEntries;
|
||||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
|
@ -47,6 +48,8 @@ class EnqueuePollMessageCommandTest extends CommandTestCase<EnqueuePollMessageCo
|
||||||
createTld("tld");
|
createTld("tld");
|
||||||
inject.setStaticField(Ofy.class, "clock", fakeClock);
|
inject.setStaticField(Ofy.class, "clock", fakeClock);
|
||||||
domain = persistActiveDomain("example.tld");
|
domain = persistActiveDomain("example.tld");
|
||||||
|
persistNewRegistrar("AdminRegistrar");
|
||||||
|
command.registryAdminClientId = "AdminRegistrar";
|
||||||
fakeClock.advanceOneMilli();
|
fakeClock.advanceOneMilli();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,11 +62,11 @@ class EnqueuePollMessageCommandTest extends CommandTestCase<EnqueuePollMessageCo
|
||||||
.that(synthetic)
|
.that(synthetic)
|
||||||
.bySuperuser(true)
|
.bySuperuser(true)
|
||||||
.and()
|
.and()
|
||||||
.hasMetadataReason("Manual enqueueing of poll message")
|
.hasMetadataReason("Manual enqueueing of poll message: This domain is bad")
|
||||||
.and()
|
.and()
|
||||||
.hasNoXml()
|
.hasNoXml()
|
||||||
.and()
|
.and()
|
||||||
.hasRegistrarId("TheRegistrar")
|
.hasRegistrarId("AdminRegistrar")
|
||||||
.and()
|
.and()
|
||||||
.hasModificationTime(fakeClock.nowUtc())
|
.hasModificationTime(fakeClock.nowUtc())
|
||||||
.and()
|
.and()
|
||||||
|
@ -79,24 +82,35 @@ class EnqueuePollMessageCommandTest extends CommandTestCase<EnqueuePollMessageCo
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestOfyAndSql
|
@TestOfyAndSql
|
||||||
void testSuccess_specifyClientId() throws Exception {
|
void testSuccess_specifyClientIds() throws Exception {
|
||||||
|
persistNewRegistrar("foobaz");
|
||||||
runCommandForced(
|
runCommandForced(
|
||||||
"--domain=example.tld", "--message=This domain needs work", "--client=NewRegistrar");
|
"--domain=example.tld",
|
||||||
|
"--message=This domain needs work",
|
||||||
|
"--clients=TheRegistrar,NewRegistrar,foobaz");
|
||||||
|
|
||||||
HistoryEntry synthetic = getOnlyHistoryEntryOfType(domain, SYNTHETIC);
|
HistoryEntry synthetic = getOnlyHistoryEntryOfType(domain, SYNTHETIC);
|
||||||
assertAboutHistoryEntries()
|
assertAboutHistoryEntries()
|
||||||
.that(synthetic)
|
.that(synthetic)
|
||||||
.bySuperuser(true)
|
.bySuperuser(true)
|
||||||
.and()
|
.and()
|
||||||
.hasMetadataReason("Manual enqueueing of poll message")
|
.hasMetadataReason("Manual enqueueing of poll message: This domain needs work")
|
||||||
.and()
|
.and()
|
||||||
.hasNoXml()
|
.hasNoXml()
|
||||||
.and()
|
.and()
|
||||||
.hasRegistrarId("NewRegistrar")
|
.hasRegistrarId("AdminRegistrar")
|
||||||
.and()
|
.and()
|
||||||
.hasModificationTime(fakeClock.nowUtc())
|
.hasModificationTime(fakeClock.nowUtc())
|
||||||
.and()
|
.and()
|
||||||
.hasMetadataRequestedByRegistrar(false);
|
.hasMetadataRequestedByRegistrar(false);
|
||||||
|
assertPollMessages(
|
||||||
|
"TheRegistrar",
|
||||||
|
new PollMessage.OneTime.Builder()
|
||||||
|
.setParent(synthetic)
|
||||||
|
.setMsg("This domain needs work")
|
||||||
|
.setRegistrarId("TheRegistrar")
|
||||||
|
.setEventTime(fakeClock.nowUtc())
|
||||||
|
.build());
|
||||||
assertPollMessages(
|
assertPollMessages(
|
||||||
"NewRegistrar",
|
"NewRegistrar",
|
||||||
new PollMessage.OneTime.Builder()
|
new PollMessage.OneTime.Builder()
|
||||||
|
@ -105,6 +119,59 @@ class EnqueuePollMessageCommandTest extends CommandTestCase<EnqueuePollMessageCo
|
||||||
.setRegistrarId("NewRegistrar")
|
.setRegistrarId("NewRegistrar")
|
||||||
.setEventTime(fakeClock.nowUtc())
|
.setEventTime(fakeClock.nowUtc())
|
||||||
.build());
|
.build());
|
||||||
|
assertPollMessages(
|
||||||
|
"foobaz",
|
||||||
|
new PollMessage.OneTime.Builder()
|
||||||
|
.setParent(synthetic)
|
||||||
|
.setMsg("This domain needs work")
|
||||||
|
.setRegistrarId("foobaz")
|
||||||
|
.setEventTime(fakeClock.nowUtc())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testSuccess_sendToAllRegistrars() throws Exception {
|
||||||
|
persistNewRegistrar("foobaz");
|
||||||
|
runCommandForced("--domain=example.tld", "--message=This domain needs work", "--all=true");
|
||||||
|
|
||||||
|
HistoryEntry synthetic = getOnlyHistoryEntryOfType(domain, SYNTHETIC);
|
||||||
|
assertAboutHistoryEntries()
|
||||||
|
.that(synthetic)
|
||||||
|
.bySuperuser(true)
|
||||||
|
.and()
|
||||||
|
.hasMetadataReason("Manual enqueueing of poll message: This domain needs work")
|
||||||
|
.and()
|
||||||
|
.hasNoXml()
|
||||||
|
.and()
|
||||||
|
.hasRegistrarId("AdminRegistrar")
|
||||||
|
.and()
|
||||||
|
.hasModificationTime(fakeClock.nowUtc())
|
||||||
|
.and()
|
||||||
|
.hasMetadataRequestedByRegistrar(false);
|
||||||
|
assertPollMessages(
|
||||||
|
"TheRegistrar",
|
||||||
|
new PollMessage.OneTime.Builder()
|
||||||
|
.setParent(synthetic)
|
||||||
|
.setMsg("This domain needs work")
|
||||||
|
.setRegistrarId("TheRegistrar")
|
||||||
|
.setEventTime(fakeClock.nowUtc())
|
||||||
|
.build());
|
||||||
|
assertPollMessages(
|
||||||
|
"NewRegistrar",
|
||||||
|
new PollMessage.OneTime.Builder()
|
||||||
|
.setParent(synthetic)
|
||||||
|
.setMsg("This domain needs work")
|
||||||
|
.setRegistrarId("NewRegistrar")
|
||||||
|
.setEventTime(fakeClock.nowUtc())
|
||||||
|
.build());
|
||||||
|
assertPollMessages(
|
||||||
|
"foobaz",
|
||||||
|
new PollMessage.OneTime.Builder()
|
||||||
|
.setParent(synthetic)
|
||||||
|
.setMsg("This domain needs work")
|
||||||
|
.setRegistrarId("foobaz")
|
||||||
|
.setEventTime(fakeClock.nowUtc())
|
||||||
|
.build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestOfyAndSql
|
@TestOfyAndSql
|
||||||
|
@ -131,4 +198,18 @@ class EnqueuePollMessageCommandTest extends CommandTestCase<EnqueuePollMessageCo
|
||||||
assertThrows(ParameterException.class, () -> runCommandForced("--domain=example.tld"));
|
assertThrows(ParameterException.class, () -> runCommandForced("--domain=example.tld"));
|
||||||
assertThat(thrown).hasMessageThat().contains("The following option is required: -m, --message");
|
assertThat(thrown).hasMessageThat().contains("The following option is required: -m, --message");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestOfyAndSql
|
||||||
|
void testCantSpecifyClientIdsAndAll() {
|
||||||
|
IllegalArgumentException thrown =
|
||||||
|
assertThrows(
|
||||||
|
IllegalArgumentException.class,
|
||||||
|
() ->
|
||||||
|
runCommandForced(
|
||||||
|
"--domain=example.tld",
|
||||||
|
"--message=Domain is ended",
|
||||||
|
"--all=true",
|
||||||
|
"--clients=TheRegistrar"));
|
||||||
|
assertThat(thrown).hasMessageThat().isEqualTo("Cannot specify both --all and --clients");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue