From 2293be4079da135a181ee1490670993e44038123 Mon Sep 17 00:00:00 2001 From: mcilwain Date: Thu, 17 Mar 2016 15:50:11 -0700 Subject: [PATCH] Automatically create mailing lists for registrars This improves one of our gTech processes so they no longer have to remember to create Google Groups for a registrar after creating that registrar. The ConfirmingCommand.verify() method is renamed to be more general purpose, so that it can do anything that follows naturally after a successful execution, such as creating Google Groups groups. Minor refactoring is done around RegistryToolEnvironment handling for tests to make it more bullet-proof and general case. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=117494277 --- .../registry/tools/AllocateDomainCommand.java | 2 +- .../registry/tools/ConfirmingCommand.java | 9 ++- .../tools/CreateRegistrarCommand.java | 45 ++++++++++- .../tools/CreateRegistrarGroupsCommand.java | 9 +++ .../registry/tools/SetupOteCommand.java | 1 + .../tools/CreateRegistrarCommandTest.java | 74 +++++++++++++++++++ 6 files changed, 135 insertions(+), 5 deletions(-) diff --git a/java/com/google/domain/registry/tools/AllocateDomainCommand.java b/java/com/google/domain/registry/tools/AllocateDomainCommand.java index 8d641ea76..0663d49fb 100644 --- a/java/com/google/domain/registry/tools/AllocateDomainCommand.java +++ b/java/com/google/domain/registry/tools/AllocateDomainCommand.java @@ -68,7 +68,7 @@ final class AllocateDomainCommand extends MutatingEppToolCommand { private final List> applicationKeys = new ArrayList<>(); @Override - protected String verify() throws Exception { + protected String postExecute() throws Exception { StringBuilder builder = new StringBuilder(); // Check to see that we allocated everything. return builder.append(ofy().transactNewReadOnly(new Work() { diff --git a/java/com/google/domain/registry/tools/ConfirmingCommand.java b/java/com/google/domain/registry/tools/ConfirmingCommand.java index 26f7350e3..29f605f9c 100644 --- a/java/com/google/domain/registry/tools/ConfirmingCommand.java +++ b/java/com/google/domain/registry/tools/ConfirmingCommand.java @@ -34,7 +34,7 @@ public abstract class ConfirmingCommand implements Command { printLineIfNotEmpty(prompt()); if (force || promptForYes("Perform this command?")) { System.out.println(execute()); - printLineIfNotEmpty(verify()); + printLineIfNotEmpty(postExecute()); } else { System.out.println("Command aborted."); } @@ -57,8 +57,11 @@ public abstract class ConfirmingCommand implements Command { /** Perform the command and return a result description. */ protected abstract String execute() throws Exception; - /** Verify result and/or perform any post-execution steps, and return optional description. */ - protected String verify() throws Exception { + /** + * Perform any post-execution steps (e.g. verifying the result), and return a description String + * to be printed if non-empty. + */ + protected String postExecute() throws Exception { return ""; } } diff --git a/java/com/google/domain/registry/tools/CreateRegistrarCommand.java b/java/com/google/domain/registry/tools/CreateRegistrarCommand.java index 432901e73..083b6f37c 100644 --- a/java/com/google/domain/registry/tools/CreateRegistrarCommand.java +++ b/java/com/google/domain/registry/tools/CreateRegistrarCommand.java @@ -19,16 +19,22 @@ import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; import static com.google.common.base.Strings.emptyToNull; import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.getOnlyElement; import static com.google.common.collect.Lists.newArrayList; import static com.google.domain.registry.model.registrar.Registrar.State.ACTIVE; +import static com.google.domain.registry.tools.RegistryToolEnvironment.PRODUCTION; +import static com.google.domain.registry.tools.RegistryToolEnvironment.SANDBOX; +import static com.google.domain.registry.tools.RegistryToolEnvironment.UNITTEST; import static com.google.domain.registry.util.RegistrarUtils.normalizeClientId; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Optional; import com.google.common.base.Predicate; +import com.google.common.collect.ImmutableSet; import com.google.domain.registry.model.registrar.Registrar; import com.google.domain.registry.tools.Command.GtechCommand; +import com.beust.jcommander.Parameter; import com.beust.jcommander.Parameters; import java.util.List; @@ -37,12 +43,29 @@ import javax.annotation.Nullable; /** Command to create a Registrar. */ @Parameters(separators = " =", commandDescription = "Create new registrar account(s)") -final class CreateRegistrarCommand extends CreateOrUpdateRegistrarCommand implements GtechCommand { +final class CreateRegistrarCommand extends CreateOrUpdateRegistrarCommand + implements GtechCommand, ServerSideCommand { + + private static final ImmutableSet ENVIRONMENTS_ALLOWING_GROUP_CREATION = + ImmutableSet.of(PRODUCTION, SANDBOX, UNITTEST); // Allows test cases to be cleaner. @VisibleForTesting static boolean requireAddress = true; + @Parameter( + names = "--create_groups", + description = "Whether the Google Groups for this registrar should be created", + arity = 1) + boolean createGoogleGroups = true; + + private Connection connection; + + @Override + public void setConnection(Connection connection) { + this.connection = connection; + } + @Override protected void initRegistrarCommand() throws Exception { checkArgument(mainParameters.size() == 1, "Must specify exactly one client identifier."); @@ -85,4 +108,24 @@ final class CreateRegistrarCommand extends CreateOrUpdateRegistrarCommand implem } return null; } + + @Override + protected String postExecute() throws Exception { + if (!createGoogleGroups) { + return ""; + } + // Allow prod and sandbox because they actually have Groups, and UNITTEST for testing. + if (!ENVIRONMENTS_ALLOWING_GROUP_CREATION.contains(RegistryToolEnvironment.get())) { + return "\nSkipping registrar groups creation because only production and sandbox support it."; + } + try { + // We know it is safe to use the only main parameter here because initRegistrarCommand has + // already verified that there is only one, and getOldRegistrar has already verified that a + // registrar with this clientIdentifier doesn't already exist. + CreateRegistrarGroupsCommand.executeOnServer(connection, getOnlyElement(mainParameters)); + } catch (Exception e) { + return "\nRegistrar created, but groups creation failed with error:\n" + e; + } + return "\nRegistrar groups created successfully."; + } } diff --git a/java/com/google/domain/registry/tools/CreateRegistrarGroupsCommand.java b/java/com/google/domain/registry/tools/CreateRegistrarGroupsCommand.java index 552787d73..1ec838a7f 100644 --- a/java/com/google/domain/registry/tools/CreateRegistrarGroupsCommand.java +++ b/java/com/google/domain/registry/tools/CreateRegistrarGroupsCommand.java @@ -73,6 +73,15 @@ public class CreateRegistrarGroupsCommand extends ConfirmingCommand }}))); } + /** Calls the server endpoint to create groups for the specified registrar client id. */ + static void executeOnServer(Connection connection, String clientIdentifier) throws IOException { + connection.send( + CreateGroupsAction.PATH, + ImmutableMap.of(CreateGroupsAction.CLIENT_ID_PARAM, clientIdentifier), + MediaType.PLAIN_TEXT_UTF_8, + new byte[0]); + } + @Override protected String execute() throws IOException { for (Registrar registrar : registrars) { diff --git a/java/com/google/domain/registry/tools/SetupOteCommand.java b/java/com/google/domain/registry/tools/SetupOteCommand.java index 63532a234..17509c015 100644 --- a/java/com/google/domain/registry/tools/SetupOteCommand.java +++ b/java/com/google/domain/registry/tools/SetupOteCommand.java @@ -117,6 +117,7 @@ final class SetupOteCommand extends ConfirmingCommand implements RemoteApiComman private void createRegistrar(String registrarName, String password, String tld) throws Exception { CreateRegistrarCommand command = new CreateRegistrarCommand(); command.mainParameters = ImmutableList.of(registrarName); + command.createGoogleGroups = false; // Don't create Google Groups for OT&E registrars. command.allowedTlds = ImmutableList.of(tld); command.registrarName = registrarName; command.registrarType = Registrar.Type.OTE; diff --git a/javatests/com/google/domain/registry/tools/CreateRegistrarCommandTest.java b/javatests/com/google/domain/registry/tools/CreateRegistrarCommandTest.java index b8d843e91..a652b4e28 100644 --- a/javatests/com/google/domain/registry/tools/CreateRegistrarCommandTest.java +++ b/javatests/com/google/domain/registry/tools/CreateRegistrarCommandTest.java @@ -21,23 +21,38 @@ import static com.google.domain.registry.testing.CertificateSamples.SAMPLE_CERT_ import static com.google.domain.registry.testing.DatastoreHelper.createTlds; import static com.google.domain.registry.testing.DatastoreHelper.persistResource; import static org.joda.time.DateTimeZone.UTC; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.verifyZeroInteractions; +import static org.mockito.Mockito.when; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.Range; +import com.google.common.net.MediaType; import com.google.domain.registry.model.registrar.Registrar; import com.google.domain.registry.testing.CertificateSamples; +import com.google.domain.registry.tools.ServerSideCommand.Connection; import com.beust.jcommander.ParameterException; import org.joda.time.DateTime; import org.junit.Before; import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; + +import java.io.IOException; /** Unit tests for {@link CreateRegistrarCommand}. */ public class CreateRegistrarCommandTest extends CommandTestCase { + @Mock + private Connection connection; + @Before public void init() { CreateRegistrarCommand.requireAddress = false; + command.setConnection(connection); } @Test @@ -70,6 +85,12 @@ public class CreateRegistrarCommandTest extends CommandTestCase