diff --git a/core/src/main/java/google/registry/model/registry/label/ReservedList.java b/core/src/main/java/google/registry/model/registry/label/ReservedList.java index 603bf852d..02244dac0 100644 --- a/core/src/main/java/google/registry/model/registry/label/ReservedList.java +++ b/core/src/main/java/google/registry/model/registry/label/ReservedList.java @@ -16,6 +16,7 @@ package google.registry.model.registry.label; import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Strings.isNullOrEmpty; import static com.google.common.collect.ImmutableSet.toImmutableSet; import static google.registry.config.RegistryConfig.getDomainLabelListCacheDuration; import static google.registry.model.registry.label.ReservationType.FULLY_BLOCKED; @@ -122,6 +123,12 @@ public final class ReservedList return new ReservedListEntry.Builder(clone(this)); } + @Override + public String toString() { + return String.format( + "%s,%s%s", label, reservationType, isNullOrEmpty(comment) ? "" : " # " + comment); + } + /** A builder for constructing {@link ReservedListEntry} objects, since they are immutable. */ private static class Builder extends DomainLabelEntry.Builder { diff --git a/core/src/main/java/google/registry/tools/GetReservedListCommand.java b/core/src/main/java/google/registry/tools/GetReservedListCommand.java new file mode 100644 index 000000000..ad810b960 --- /dev/null +++ b/core/src/main/java/google/registry/tools/GetReservedListCommand.java @@ -0,0 +1,52 @@ +// Copyright 2021 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.tools; + +import com.beust.jcommander.Parameter; +import com.beust.jcommander.Parameters; +import com.google.appengine.repackaged.com.google.common.collect.Streams; +import google.registry.model.registry.label.ReservedList.ReservedListEntry; +import google.registry.model.registry.label.ReservedListDualDatabaseDao; +import java.util.Comparator; +import java.util.stream.Collectors; + +/** Retrieves and prints one or more reserved lists. */ +@Parameters(separators = " =", commandDescription = "Show one or more reserved lists") +public class GetReservedListCommand implements CommandWithRemoteApi { + + @Parameter( + names = {"-n", "--name"}, + description = "The name of this reserved list", + required = true) + String reservedListName; + + @Override + public void run() throws Exception { + if (ReservedListDualDatabaseDao.getLatestRevision(reservedListName).isPresent()) { + System.out.printf( + "%s\n", + Streams.stream( + ReservedListDualDatabaseDao.getLatestRevision(reservedListName) + .get() + .getReservedListEntries() + .values()) + .sorted(Comparator.comparing(ReservedListEntry::getLabel)) + .map(ReservedListEntry::toString) + .collect(Collectors.joining("\n"))); + } else { + System.err.printf("No list found with name %s.%n", reservedListName); + } + } +} diff --git a/core/src/main/java/google/registry/tools/RegistryTool.java b/core/src/main/java/google/registry/tools/RegistryTool.java index 2b195742d..2835ed0a3 100644 --- a/core/src/main/java/google/registry/tools/RegistryTool.java +++ b/core/src/main/java/google/registry/tools/RegistryTool.java @@ -78,6 +78,7 @@ public final class RegistryTool { .put("get_operation_status", GetOperationStatusCommand.class) .put("get_premium_list", GetPremiumListCommand.class) .put("get_registrar", GetRegistrarCommand.class) + .put("get_reserved_list", GetReservedListCommand.class) .put("get_resource_by_key", GetResourceByKeyCommand.class) .put("get_routing_map", GetRoutingMapCommand.class) .put("get_schema", GetSchemaCommand.class) diff --git a/core/src/test/java/google/registry/tools/GetReservedListCommandTest.java b/core/src/test/java/google/registry/tools/GetReservedListCommandTest.java new file mode 100644 index 000000000..4a65561df --- /dev/null +++ b/core/src/test/java/google/registry/tools/GetReservedListCommandTest.java @@ -0,0 +1,59 @@ +// Copyright 2021 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.tools; + +import static google.registry.testing.DatabaseHelper.persistReservedList; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import com.beust.jcommander.ParameterException; +import google.registry.testing.DualDatabaseTest; +import google.registry.testing.TestOfyAndSql; +import org.junit.jupiter.api.BeforeEach; + +@DualDatabaseTest +public class GetReservedListCommandTest extends CommandTestCase { + + private static final String BASE_LIST_CONTENTS = + "atlanta,RESERVED_FOR_SPECIFIC_USE # comment\n" + + "boston,RESERVED_FOR_SPECIFIC_USE\n" + + "chicago,FULLY_BLOCKED # another comment\n" + + "dallas,RESERVED_FOR_SPECIFIC_USE # cool city\n" + + "elpaso,RESERVED_FOR_SPECIFIC_USE\n" + + "fairbanks,RESERVED_FOR_ANCHOR_TENANT # alaska\n" + + "greensboro,RESERVED_FOR_SPECIFIC_USE\n"; + + @BeforeEach + void beforeEach() { + persistReservedList("tld_reserved-terms", BASE_LIST_CONTENTS); + } + + @TestOfyAndSql + void testSuccess_list() throws Exception { + runCommand("-n=tld_reserved-terms"); + assertStdoutIs(BASE_LIST_CONTENTS); + } + + @TestOfyAndSql + void testFailure_nonexistent() throws Exception { + runCommand("-n=nonexistent"); + assertStdoutIs(""); + assertInStderr("No list found with name nonexistent.\n"); + } + + @TestOfyAndSql + void testFailure_noArgs() { + assertThrows(ParameterException.class, this::runCommand); + } +}