mirror of
https://github.com/google/nomulus.git
synced 2025-06-12 15:34:47 +02:00
Resolved merge conflict
This commit is contained in:
commit
02c75ee37e
237 changed files with 4148 additions and 3993 deletions
|
@ -15,7 +15,6 @@
|
|||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Suppliers.memoize;
|
||||
import static com.google.common.net.HttpHeaders.X_REQUESTED_WITH;
|
||||
import static com.google.common.net.MediaType.JSON_UTF_8;
|
||||
import static google.registry.security.JsonHttp.JSON_SAFETY_PREFIX;
|
||||
|
@ -27,48 +26,55 @@ import com.google.api.client.http.HttpHeaders;
|
|||
import com.google.api.client.http.HttpRequest;
|
||||
import com.google.api.client.http.HttpRequestFactory;
|
||||
import com.google.api.client.http.HttpResponse;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.CharStreams;
|
||||
import com.google.common.net.HostAndPort;
|
||||
import com.google.common.net.MediaType;
|
||||
import com.google.re2j.Matcher;
|
||||
import com.google.re2j.Pattern;
|
||||
import google.registry.security.XsrfTokenManager;
|
||||
import google.registry.tools.CommandWithConnection.Connection;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.inject.Inject;
|
||||
import org.json.simple.JSONValue;
|
||||
|
||||
/** An http connection to the appengine server. */
|
||||
class AppEngineConnection implements Connection {
|
||||
/**
|
||||
* An http connection to an appengine server.
|
||||
*
|
||||
* <p>By default - connects to the TOOLS service. To create a Connection to another service, call
|
||||
* the {@link #withService} function.
|
||||
*/
|
||||
class AppEngineConnection {
|
||||
|
||||
/** Pattern to heuristically extract title tag contents in HTML responses. */
|
||||
private static final Pattern HTML_TITLE_TAG_PATTERN = Pattern.compile("<title>(.*?)</title>");
|
||||
|
||||
@Inject HttpRequestFactory requestFactory;
|
||||
@Inject AppEngineConnectionFlags flags;
|
||||
@Inject XsrfTokenManager xsrfTokenManager;
|
||||
private final Service service;
|
||||
|
||||
@Inject
|
||||
AppEngineConnection() {}
|
||||
AppEngineConnection() {
|
||||
service = Service.TOOLS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Memoized XSRF security token.
|
||||
*
|
||||
* <p>Computing this is expensive since it needs to load {@code ServerSecret} so do it once.
|
||||
*/
|
||||
private final Supplier<String> xsrfToken =
|
||||
memoize(() -> xsrfTokenManager.generateToken(getUserId()));
|
||||
private AppEngineConnection(Service service, HttpRequestFactory requestFactory) {
|
||||
this.service = service;
|
||||
this.requestFactory = requestFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void prefetchXsrfToken() {
|
||||
// Cause XSRF token to be fetched, and then stay resident in cache (since it's memoized).
|
||||
xsrfToken.get();
|
||||
enum Service {
|
||||
DEFAULT,
|
||||
TOOLS,
|
||||
BACKEND,
|
||||
PUBAPI
|
||||
}
|
||||
|
||||
/** Returns a copy of this connection that talks to a different service. */
|
||||
public AppEngineConnection withService(Service service) {
|
||||
return new AppEngineConnection(service, requestFactory);
|
||||
}
|
||||
|
||||
/** Returns the contents of the title tag in the given HTML, or null if not found. */
|
||||
|
@ -85,7 +91,8 @@ class AppEngineConnection implements Connection {
|
|||
private String internalSend(
|
||||
String endpoint, Map<String, ?> params, MediaType contentType, @Nullable byte[] payload)
|
||||
throws IOException {
|
||||
GenericUrl url = new GenericUrl(String.format("%s%s", getServerUrl(), endpoint));
|
||||
GenericUrl url = new GenericUrl(getServer());
|
||||
url.setRawPath(endpoint);
|
||||
url.putAll(params);
|
||||
HttpRequest request =
|
||||
(payload != null)
|
||||
|
@ -120,23 +127,20 @@ class AppEngineConnection implements Connection {
|
|||
}
|
||||
}
|
||||
|
||||
// TODO(b/111123862): Rename this to sendPostRequest()
|
||||
@Override
|
||||
public String send(String endpoint, Map<String, ?> params, MediaType contentType, byte[] payload)
|
||||
public String sendPostRequest(
|
||||
String endpoint, Map<String, ?> params, MediaType contentType, byte[] payload)
|
||||
throws IOException {
|
||||
return internalSend(endpoint, params, contentType, checkNotNull(payload, "payload"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String sendGetRequest(String endpoint, Map<String, ?> params) throws IOException {
|
||||
return internalSend(endpoint, params, MediaType.PLAIN_TEXT_UTF_8, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, Object> sendJson(String endpoint, Map<String, ?> object) throws IOException {
|
||||
String response =
|
||||
send(
|
||||
sendPostRequest(
|
||||
endpoint,
|
||||
ImmutableMap.of(),
|
||||
JSON_UTF_8,
|
||||
|
@ -144,22 +148,17 @@ class AppEngineConnection implements Connection {
|
|||
return (Map<String, Object>) JSONValue.parse(response.substring(JSON_SAFETY_PREFIX.length()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getServerUrl() {
|
||||
return (isLocalhost() ? "http://" : "https://") + getServer().toString();
|
||||
}
|
||||
|
||||
HostAndPort getServer() {
|
||||
return flags.getServer().withDefaultPort(443); // Default to HTTPS port if unspecified.
|
||||
}
|
||||
|
||||
boolean isLocalhost() {
|
||||
return flags.getServer().getHost().equals("localhost");
|
||||
}
|
||||
|
||||
private String getUserId() {
|
||||
return isLocalhost()
|
||||
? UserIdProvider.getTestUserId()
|
||||
: UserIdProvider.getProdUserId();
|
||||
public URL getServer() {
|
||||
switch (service) {
|
||||
case DEFAULT:
|
||||
return RegistryConfig.getDefaultServer();
|
||||
case TOOLS:
|
||||
return RegistryConfig.getToolsServer();
|
||||
case BACKEND:
|
||||
return RegistryConfig.getBackendServer();
|
||||
case PUBAPI:
|
||||
return RegistryConfig.getPubapiServer();
|
||||
}
|
||||
throw new IllegalStateException("Unknown service: " + service);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,63 +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.tools;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.net.HostAndPort;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.RegistryConfig;
|
||||
|
||||
/**
|
||||
* Class to contain the configuration flags for AppEngineConnection.
|
||||
*
|
||||
* <p>This is broken out into its own class to make it cleaner to extract these from the dagger
|
||||
* module, where these values are injected.
|
||||
*/
|
||||
@Parameters(separators = " =")
|
||||
class AppEngineConnectionFlags {
|
||||
|
||||
@Parameter(names = "--server", description = "HOST[:PORT] to which remote commands are sent.")
|
||||
private HostAndPort server = RegistryConfig.getServer();
|
||||
|
||||
/** Provided for testing. */
|
||||
@VisibleForTesting
|
||||
AppEngineConnectionFlags(HostAndPort server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
AppEngineConnectionFlags() {}
|
||||
|
||||
HostAndPort getServer() {
|
||||
return server;
|
||||
}
|
||||
|
||||
@Module
|
||||
static class FlagsModule {
|
||||
AppEngineConnectionFlags flags;
|
||||
|
||||
FlagsModule(AppEngineConnectionFlags flags) {
|
||||
this.flags = flags;
|
||||
}
|
||||
|
||||
@Provides
|
||||
AppEngineConnectionFlags provideAppEngineConnectionFlags() {
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -46,6 +46,7 @@ java_library(
|
|||
"//java/google/registry/export",
|
||||
"//java/google/registry/flows",
|
||||
"//java/google/registry/gcs",
|
||||
"//java/google/registry/keyring",
|
||||
"//java/google/registry/keyring/api",
|
||||
"//java/google/registry/keyring/kms",
|
||||
"//java/google/registry/loadtest",
|
||||
|
@ -69,7 +70,6 @@ java_library(
|
|||
"@com_google_api_client",
|
||||
"@com_google_apis_google_api_services_bigquery",
|
||||
"@com_google_apis_google_api_services_dns",
|
||||
"@com_google_apis_google_api_services_monitoring",
|
||||
"@com_google_appengine_api_1_0_sdk",
|
||||
"@com_google_appengine_remote_api",
|
||||
"@com_google_appengine_remote_api//:link",
|
||||
|
@ -81,8 +81,6 @@ java_library(
|
|||
"@com_google_guava",
|
||||
"@com_google_http_client",
|
||||
"@com_google_http_client_jackson2",
|
||||
"@com_google_monitoring_client_metrics",
|
||||
"@com_google_monitoring_client_stackdriver",
|
||||
"@com_google_oauth_client",
|
||||
"@com_google_oauth_client_java6",
|
||||
"@com_google_oauth_client_jetty",
|
||||
|
|
|
@ -14,30 +14,7 @@
|
|||
|
||||
package google.registry.tools;
|
||||
|
||||
import com.google.common.net.MediaType;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import javax.annotation.Nullable;
|
||||
|
||||
/** A command that can send HTTP requests to a backend module. */
|
||||
interface CommandWithConnection extends Command {
|
||||
|
||||
/** An http connection to AppEngine. */
|
||||
interface Connection {
|
||||
|
||||
void prefetchXsrfToken();
|
||||
|
||||
/** Send a POST request. TODO(mmuller): change to sendPostRequest() */
|
||||
String send(
|
||||
String endpoint, Map<String, ?> params, MediaType contentType, @Nullable byte[] payload)
|
||||
throws IOException;
|
||||
|
||||
String sendGetRequest(String endpoint, Map<String, ?> params) throws IOException;
|
||||
|
||||
Map<String, Object> sendJson(String endpoint, Map<String, ?> object) throws IOException;
|
||||
|
||||
String getServerUrl();
|
||||
}
|
||||
|
||||
void setConnection(Connection connection);
|
||||
void setConnection(AppEngineConnection connection);
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import com.beust.jcommander.Parameter;
|
|||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
import com.google.template.soy.data.SoyMapData;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.tools.soy.CreateAnchorTenantSoyInfo;
|
||||
import google.registry.util.StringGenerator;
|
||||
import javax.inject.Inject;
|
||||
|
@ -72,6 +73,7 @@ final class CreateAnchorTenantCommand extends MutatingEppToolCommand {
|
|||
private boolean fee;
|
||||
|
||||
@Inject
|
||||
@Config("base64StringGenerator")
|
||||
StringGenerator passwordGenerator;
|
||||
|
||||
@Override
|
||||
|
|
|
@ -20,6 +20,7 @@ import static com.google.common.base.Strings.isNullOrEmpty;
|
|||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.template.soy.data.SoyMapData;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.tools.params.PhoneNumberParameter;
|
||||
import google.registry.tools.soy.ContactCreateSoyInfo;
|
||||
import google.registry.util.StringGenerator;
|
||||
|
@ -103,6 +104,7 @@ final class CreateContactCommand extends MutatingEppToolCommand {
|
|||
private String password;
|
||||
|
||||
@Inject
|
||||
@Config("base64StringGenerator")
|
||||
StringGenerator passwordGenerator;
|
||||
|
||||
private static final int PASSWORD_LENGTH = 16;
|
||||
|
|
|
@ -23,6 +23,7 @@ import static org.joda.time.DateTimeZone.UTC;
|
|||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.template.soy.data.SoyMapData;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.pricing.PremiumPricingEngine.DomainPrices;
|
||||
import google.registry.tools.soy.DomainCreateSoyInfo;
|
||||
import google.registry.util.StringGenerator;
|
||||
|
@ -46,6 +47,7 @@ final class CreateDomainCommand extends CreateOrUpdateDomainCommand
|
|||
private boolean forcePremiums;
|
||||
|
||||
@Inject
|
||||
@Config("base64StringGenerator")
|
||||
StringGenerator passwordGenerator;
|
||||
|
||||
private static final int PASSWORD_LENGTH = 16;
|
||||
|
|
|
@ -57,11 +57,11 @@ abstract class CreateOrUpdatePremiumListCommand extends ConfirmingCommand
|
|||
required = true)
|
||||
Path inputFile;
|
||||
|
||||
protected Connection connection;
|
||||
protected AppEngineConnection connection;
|
||||
protected int inputLineCount;
|
||||
|
||||
@Override
|
||||
public void setConnection(Connection connection) {
|
||||
public void setConnection(AppEngineConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
|
@ -101,11 +101,9 @@ abstract class CreateOrUpdatePremiumListCommand extends ConfirmingCommand
|
|||
}
|
||||
|
||||
// Call the server and get the response data
|
||||
String response = connection.send(
|
||||
getCommandPath(),
|
||||
params.build(),
|
||||
MediaType.FORM_DATA,
|
||||
requestBody.getBytes(UTF_8));
|
||||
String response =
|
||||
connection.sendPostRequest(
|
||||
getCommandPath(), params.build(), MediaType.FORM_DATA, requestBody.getBytes(UTF_8));
|
||||
|
||||
return extractServerResponse(response);
|
||||
}
|
||||
|
|
|
@ -50,10 +50,10 @@ final class CreateRegistrarCommand extends CreateOrUpdateRegistrarCommand
|
|||
arity = 1)
|
||||
boolean createGoogleGroups = true;
|
||||
|
||||
private Connection connection;
|
||||
private AppEngineConnection connection;
|
||||
|
||||
@Override
|
||||
public void setConnection(Connection connection) {
|
||||
public void setConnection(AppEngineConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
|
|
|
@ -41,10 +41,10 @@ public class CreateRegistrarGroupsCommand extends ConfirmingCommand
|
|||
|
||||
private List<Registrar> registrars = new ArrayList<>();
|
||||
|
||||
private Connection connection;
|
||||
private AppEngineConnection connection;
|
||||
|
||||
@Override
|
||||
public void setConnection(Connection connection) {
|
||||
public void setConnection(AppEngineConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
|
@ -66,8 +66,8 @@ public class CreateRegistrarGroupsCommand extends ConfirmingCommand
|
|||
}
|
||||
|
||||
/** Calls the server endpoint to create groups for the specified registrar client id. */
|
||||
static void executeOnServer(Connection connection, String clientId) throws IOException {
|
||||
connection.send(
|
||||
static void executeOnServer(AppEngineConnection connection, String clientId) throws IOException {
|
||||
connection.sendPostRequest(
|
||||
CreateGroupsAction.PATH,
|
||||
ImmutableMap.of(CreateGroupsAction.CLIENT_ID_PARAM, clientId),
|
||||
MediaType.PLAIN_TEXT_UTF_8,
|
||||
|
@ -77,7 +77,7 @@ public class CreateRegistrarGroupsCommand extends ConfirmingCommand
|
|||
@Override
|
||||
protected String execute() throws IOException {
|
||||
for (Registrar registrar : registrars) {
|
||||
connection.send(
|
||||
connection.sendPostRequest(
|
||||
CreateGroupsAction.PATH,
|
||||
ImmutableMap.of(CreateGroupsAction.CLIENT_ID_PARAM, registrar.getClientId()),
|
||||
MediaType.PLAIN_TEXT_UTF_8,
|
||||
|
|
|
@ -22,11 +22,12 @@ import com.google.common.base.Joiner;
|
|||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.net.MediaType;
|
||||
import google.registry.tools.AppEngineConnection.Service;
|
||||
import java.util.List;
|
||||
|
||||
@Parameters(separators = " =", commandDescription = "Send an HTTP command to the nomulus server.")
|
||||
class CurlCommand implements CommandWithConnection {
|
||||
private Connection connection;
|
||||
private AppEngineConnection connection;
|
||||
|
||||
// HTTP Methods that are acceptable for use as values for --method.
|
||||
public enum Method {
|
||||
|
@ -62,8 +63,14 @@ class CurlCommand implements CommandWithConnection {
|
|||
+ "absent, a GET request is sent.")
|
||||
private List<String> data;
|
||||
|
||||
@Parameter(
|
||||
names = {"--service"},
|
||||
description = "Which service to connect to",
|
||||
required = true)
|
||||
private Service service;
|
||||
|
||||
@Override
|
||||
public void setConnection(Connection connection) {
|
||||
public void setConnection(AppEngineConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
|
@ -77,12 +84,14 @@ class CurlCommand implements CommandWithConnection {
|
|||
throw new IllegalArgumentException("You may not specify a body for a get method.");
|
||||
}
|
||||
|
||||
// TODO(b/112315418): Make it possible to address any backend.
|
||||
AppEngineConnection connectionToService = connection.withService(service);
|
||||
String response =
|
||||
(method == Method.GET)
|
||||
? connection.sendGetRequest(path, ImmutableMap.<String, String>of())
|
||||
: connection.send(
|
||||
path, ImmutableMap.<String, String>of(), mimeType,
|
||||
? connectionToService.sendGetRequest(path, ImmutableMap.<String, String>of())
|
||||
: connectionToService.sendPostRequest(
|
||||
path,
|
||||
ImmutableMap.<String, String>of(),
|
||||
mimeType,
|
||||
Joiner.on("&").join(data).getBytes(UTF_8));
|
||||
System.out.println(response);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import com.google.api.client.http.javanet.NetHttpTransport;
|
|||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
|
||||
|
@ -43,9 +44,8 @@ class DefaultRequestFactoryModule {
|
|||
@Provides
|
||||
@Named("default")
|
||||
public HttpRequestFactory provideHttpRequestFactory(
|
||||
AppEngineConnectionFlags connectionFlags,
|
||||
Provider<Credential> credentialProvider) {
|
||||
if (connectionFlags.getServer().getHost().equals("localhost")) {
|
||||
if (RegistryConfig.areServersLocal()) {
|
||||
return new NetHttpTransport()
|
||||
.createRequestFactory(
|
||||
request -> request
|
||||
|
|
107
java/google/registry/tools/DeleteAllocationTokensCommand.java
Normal file
107
java/google/registry/tools/DeleteAllocationTokensCommand.java
Normal file
|
@ -0,0 +1,107 @@
|
|||
// Copyright 2018 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 com.google.common.collect.ImmutableSet.toImmutableSet;
|
||||
import static com.google.common.collect.Iterables.partition;
|
||||
import static com.google.common.collect.Streams.stream;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.googlecode.objectify.Key;
|
||||
import com.googlecode.objectify.cmd.Query;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Command to delete unused {@link AllocationToken}s.
|
||||
*
|
||||
* <p>Allocation tokens that have been redeemed cannot be deleted. To delete a single allocation
|
||||
* token, specify the entire token as the prefix.
|
||||
*/
|
||||
@Parameters(
|
||||
separators = " =",
|
||||
commandDescription = "Deletes the unused AllocationTokens with a given prefix.")
|
||||
final class DeleteAllocationTokensCommand extends ConfirmingCommand
|
||||
implements CommandWithRemoteApi {
|
||||
|
||||
@Parameter(
|
||||
names = {"-p", "--prefix"},
|
||||
description = "Allocation token prefix; if blank, deletes all unused tokens",
|
||||
required = true)
|
||||
private String prefix;
|
||||
|
||||
@Parameter(
|
||||
names = {"--with_domains"},
|
||||
description = "Allow deletion of allocation tokens with specified domains; defaults to false")
|
||||
boolean withDomains;
|
||||
|
||||
@Parameter(
|
||||
names = {"--dry_run"},
|
||||
description = "Do not actually delete the tokens; defaults to false")
|
||||
boolean dryRun;
|
||||
|
||||
private static final int BATCH_SIZE = 20;
|
||||
private static final Joiner JOINER = Joiner.on(", ");
|
||||
|
||||
private ImmutableSet<Key<AllocationToken>> tokensToDelete;
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
Query<AllocationToken> query =
|
||||
ofy().load().type(AllocationToken.class).filter("redemptionHistoryEntry", null);
|
||||
tokensToDelete =
|
||||
query.keys().list().stream()
|
||||
.filter(key -> key.getName().startsWith(prefix))
|
||||
.collect(toImmutableSet());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String prompt() {
|
||||
return String.format(
|
||||
"Found %d unused tokens starting with '%s' to delete.", tokensToDelete.size(), prefix);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String execute() {
|
||||
long numDeleted =
|
||||
stream(partition(tokensToDelete, BATCH_SIZE))
|
||||
.mapToLong(batch -> ofy().transact(() -> deleteBatch(batch)))
|
||||
.sum();
|
||||
return String.format("Deleted %d tokens in total.", numDeleted);
|
||||
}
|
||||
|
||||
/** Deletes a (filtered) batch of AllocationTokens and returns how many were deleted. */
|
||||
private long deleteBatch(List<Key<AllocationToken>> batch) {
|
||||
// Load the tokens in the same transaction as they are deleted to verify they weren't redeemed
|
||||
// since the query ran. This also filters out per-domain tokens if they're not to be deleted.
|
||||
ImmutableSet<AllocationToken> tokensToDelete =
|
||||
ofy().load().keys(batch).values().stream()
|
||||
.filter(t -> withDomains || !t.getDomainName().isPresent())
|
||||
.filter(t -> !t.isRedeemed())
|
||||
.collect(toImmutableSet());
|
||||
if (!dryRun) {
|
||||
ofy().delete().entities(tokensToDelete);
|
||||
}
|
||||
System.out.printf(
|
||||
"%s tokens: %s\n",
|
||||
dryRun ? "Would delete" : "Deleted",
|
||||
JOINER.join(batch.stream().map(Key::getName).collect(toImmutableSet())));
|
||||
return tokensToDelete.size();
|
||||
}
|
||||
}
|
|
@ -59,7 +59,7 @@ abstract class EppToolCommand extends ConfirmingCommand
|
|||
|
||||
private List<XmlEppParameters> commands = new ArrayList<>();
|
||||
|
||||
private Connection connection;
|
||||
private AppEngineConnection connection;
|
||||
|
||||
static class XmlEppParameters {
|
||||
final String clientId;
|
||||
|
@ -95,7 +95,7 @@ abstract class EppToolCommand extends ConfirmingCommand
|
|||
}
|
||||
|
||||
@Override
|
||||
public void setConnection(Connection connection) {
|
||||
public void setConnection(AppEngineConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
|
@ -145,11 +145,13 @@ abstract class EppToolCommand extends ConfirmingCommand
|
|||
params.put("xml", URLEncoder.encode(command.xml, UTF_8.toString()));
|
||||
String requestBody =
|
||||
Joiner.on('&').withKeyValueSeparator("=").join(filterValues(params, Objects::nonNull));
|
||||
responses.add(nullToEmpty(connection.send(
|
||||
"/_dr/epptool",
|
||||
ImmutableMap.<String, String>of(),
|
||||
MediaType.FORM_DATA,
|
||||
requestBody.getBytes(UTF_8))));
|
||||
responses.add(
|
||||
nullToEmpty(
|
||||
connection.sendPostRequest(
|
||||
"/_dr/epptool",
|
||||
ImmutableMap.<String, String>of(),
|
||||
MediaType.FORM_DATA,
|
||||
requestBody.getBytes(UTF_8))));
|
||||
}
|
||||
return responses.build();
|
||||
}
|
||||
|
|
|
@ -20,10 +20,8 @@ import com.beust.jcommander.Parameter;
|
|||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.io.CharStreams;
|
||||
import com.google.common.io.Files;
|
||||
import google.registry.util.NonFinalForTesting;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
@ -40,14 +38,10 @@ final class ExecuteEppCommand extends MutatingEppToolCommand {
|
|||
required = true)
|
||||
String clientId;
|
||||
|
||||
@NonFinalForTesting
|
||||
private static InputStream stdin = System.in;
|
||||
|
||||
@Override
|
||||
protected void initMutatingEppToolCommand() throws IOException {
|
||||
if (mainParameters.isEmpty()) {
|
||||
addXmlCommand(
|
||||
clientId, CharStreams.toString(new InputStreamReader(stdin, UTF_8)));
|
||||
addXmlCommand(clientId, CharStreams.toString(new InputStreamReader(System.in, UTF_8)));
|
||||
} else {
|
||||
for (String command : mainParameters) {
|
||||
addXmlCommand(clientId, Files.asCharSource(new File(command), UTF_8).read());
|
||||
|
|
|
@ -31,6 +31,7 @@ import com.google.common.base.Splitter;
|
|||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.io.Files;
|
||||
import com.googlecode.objectify.Key;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.model.domain.token.AllocationToken;
|
||||
import google.registry.util.NonFinalForTesting;
|
||||
import google.registry.util.Retrier;
|
||||
|
@ -40,16 +41,15 @@ import java.io.IOException;
|
|||
import java.util.Collection;
|
||||
import java.util.Deque;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
|
||||
/** Command to generate and persist {@link AllocationToken}s. */
|
||||
@NonFinalForTesting
|
||||
@Parameters(
|
||||
separators = " =",
|
||||
commandDescription =
|
||||
"Generates and persists the given number of AllocationTokens, printing each token to stdout."
|
||||
)
|
||||
public class GenerateAllocationTokensCommand implements CommandWithRemoteApi {
|
||||
@NonFinalForTesting
|
||||
class GenerateAllocationTokensCommand implements CommandWithRemoteApi {
|
||||
|
||||
@Parameter(
|
||||
names = {"-p", "--prefix"},
|
||||
|
@ -80,7 +80,10 @@ public class GenerateAllocationTokensCommand implements CommandWithRemoteApi {
|
|||
description = "Do not actually persist the tokens; defaults to false")
|
||||
boolean dryRun;
|
||||
|
||||
@Inject @Named("base58StringGenerator") StringGenerator stringGenerator;
|
||||
@Inject
|
||||
@Config("base58StringGenerator")
|
||||
StringGenerator stringGenerator;
|
||||
|
||||
@Inject Retrier retrier;
|
||||
|
||||
private static final int BATCH_SIZE = 20;
|
||||
|
|
|
@ -22,7 +22,7 @@ import com.beust.jcommander.Parameter;
|
|||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import google.registry.model.domain.DomainResource;
|
||||
import google.registry.tmch.LordnTask;
|
||||
import google.registry.tmch.LordnTaskUtils;
|
||||
import google.registry.tools.params.PathParameter;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
@ -61,26 +61,28 @@ final class GenerateLordnCommand implements CommandWithRemoteApi {
|
|||
for (DomainResource domain : ofy().load().type(DomainResource.class).filter("tld", tld)) {
|
||||
String status = " ";
|
||||
if (domain.getLaunchNotice() == null && domain.getSmdId() != null) {
|
||||
sunriseCsv.add(LordnTask.getCsvLineForSunriseDomain(domain, domain.getCreationTime()));
|
||||
sunriseCsv.add(LordnTaskUtils.getCsvLineForSunriseDomain(domain, domain.getCreationTime()));
|
||||
status = "S";
|
||||
} else if (domain.getLaunchNotice() != null || domain.getSmdId() != null) {
|
||||
claimsCsv.add(LordnTask.getCsvLineForClaimsDomain(domain, domain.getCreationTime()));
|
||||
claimsCsv.add(LordnTaskUtils.getCsvLineForClaimsDomain(domain, domain.getCreationTime()));
|
||||
status = "C";
|
||||
}
|
||||
System.out.printf("%s[%s] ", domain.getFullyQualifiedDomainName(), status);
|
||||
}
|
||||
ImmutableList<String> claimsRows = claimsCsv.build();
|
||||
ImmutableList<String> claimsAll = new ImmutableList.Builder<String>()
|
||||
.add(String.format("1,%s,%d", now, claimsRows.size()))
|
||||
.add(LordnTask.COLUMNS_CLAIMS)
|
||||
.addAll(claimsRows)
|
||||
.build();
|
||||
ImmutableList<String> claimsAll =
|
||||
new ImmutableList.Builder<String>()
|
||||
.add(String.format("1,%s,%d", now, claimsRows.size()))
|
||||
.add(LordnTaskUtils.COLUMNS_CLAIMS)
|
||||
.addAll(claimsRows)
|
||||
.build();
|
||||
ImmutableList<String> sunriseRows = sunriseCsv.build();
|
||||
ImmutableList<String> sunriseAll = new ImmutableList.Builder<String>()
|
||||
.add(String.format("1,%s,%d", now.plusMillis(1), sunriseRows.size()))
|
||||
.add(LordnTask.COLUMNS_SUNRISE)
|
||||
.addAll(sunriseRows)
|
||||
.build();
|
||||
ImmutableList<String> sunriseAll =
|
||||
new ImmutableList.Builder<String>()
|
||||
.add(String.format("1,%s,%d", now.plusMillis(1), sunriseRows.size()))
|
||||
.add(LordnTaskUtils.COLUMNS_SUNRISE)
|
||||
.addAll(sunriseRows)
|
||||
.build();
|
||||
Files.write(claimsOutputPath, claimsAll, UTF_8);
|
||||
Files.write(sunriseOutputPath, sunriseAll, UTF_8);
|
||||
}
|
||||
|
|
|
@ -45,10 +45,10 @@ final class GenerateZoneFilesCommand implements CommandWithConnection, CommandWi
|
|||
validateWith = DateParameter.class)
|
||||
private DateTime exportDate = DateTime.now(UTC).minus(standardMinutes(2)).withTimeAtStartOfDay();
|
||||
|
||||
private Connection connection;
|
||||
private AppEngineConnection connection;
|
||||
|
||||
@Override
|
||||
public void setConnection(Connection connection) {
|
||||
public void setConnection(AppEngineConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
|
@ -59,10 +59,7 @@ final class GenerateZoneFilesCommand implements CommandWithConnection, CommandWi
|
|||
"tlds", mainParameters,
|
||||
"exportTime", exportDate.toString());
|
||||
Map<String, Object> response = connection.sendJson(GenerateZoneFilesAction.PATH, params);
|
||||
System.out.printf(
|
||||
"Job started at %s%s\n",
|
||||
connection.getServerUrl(),
|
||||
response.get("jobPath"));
|
||||
System.out.printf("Job started at %s %s\n", connection.getServer(), response.get("jobPath"));
|
||||
System.out.println("Output files:");
|
||||
@SuppressWarnings("unchecked")
|
||||
List<String> filenames = (List<String>) response.get("filenames");
|
||||
|
|
|
@ -15,11 +15,14 @@
|
|||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static google.registry.model.registry.Registries.getTldsOfType;
|
||||
import static google.registry.util.CollectionUtils.isNullOrEmpty;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.base.Joiner;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import google.registry.model.registry.Registry.TldType;
|
||||
import google.registry.tools.server.ListDomainsAction;
|
||||
import java.util.List;
|
||||
|
||||
|
@ -29,8 +32,7 @@ final class ListDomainsCommand extends ListObjectsCommand {
|
|||
|
||||
@Parameter(
|
||||
names = {"-t", "--tld", "--tlds"},
|
||||
description = "Comma-delimited list of top-level domain(s) to list second-level domains of.",
|
||||
required = true)
|
||||
description = "Comma-delimited list of TLDs to list domains on; defaults to all REAL TLDs.")
|
||||
private List<String> tlds;
|
||||
|
||||
@Parameter(
|
||||
|
@ -47,6 +49,10 @@ final class ListDomainsCommand extends ListObjectsCommand {
|
|||
/** Returns a map of parameters to be sent to the server (in addition to the usual ones). */
|
||||
@Override
|
||||
ImmutableMap<String, Object> getParameterMap() {
|
||||
// Default to all REAL TLDs if not specified.
|
||||
if (isNullOrEmpty(tlds)) {
|
||||
tlds = getTldsOfType(TldType.REAL).asList();
|
||||
}
|
||||
String tldsParam = Joiner.on(',').join(tlds);
|
||||
checkArgument(tldsParam.length() < 1024, "Total length of TLDs is too long for URL parameter");
|
||||
return ImmutableMap.of("tlds", tldsParam, "limit", maxDomains);
|
||||
|
|
|
@ -54,10 +54,10 @@ abstract class ListObjectsCommand implements CommandWithConnection, CommandWithR
|
|||
description = "Whether to print full field names in header row (as opposed to aliases)")
|
||||
private boolean fullFieldNames = false;
|
||||
|
||||
private Connection connection;
|
||||
private AppEngineConnection connection;
|
||||
|
||||
@Override
|
||||
public void setConnection(Connection connection) {
|
||||
public void setConnection(AppEngineConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
|
@ -83,11 +83,9 @@ abstract class ListObjectsCommand implements CommandWithConnection, CommandWithR
|
|||
}
|
||||
params.putAll(getParameterMap());
|
||||
// Call the server and get the response data.
|
||||
String response = connection.send(
|
||||
getCommandPath(),
|
||||
params.build(),
|
||||
MediaType.PLAIN_TEXT_UTF_8,
|
||||
new byte[0]);
|
||||
String response =
|
||||
connection.sendPostRequest(
|
||||
getCommandPath(), params.build(), MediaType.PLAIN_TEXT_UTF_8, new byte[0]);
|
||||
// Parse the returned JSON and make sure it's a map.
|
||||
Object obj = JSONValue.parse(response.substring(JSON_SAFETY_PREFIX.length()));
|
||||
if (!(obj instanceof Map<?, ?>)) {
|
||||
|
|
|
@ -77,10 +77,10 @@ class LoadTestCommand extends ConfirmingCommand
|
|||
description = "Time to run the load test in seconds.")
|
||||
int runSeconds = DEFAULT_RUN_SECONDS;
|
||||
|
||||
private Connection connection;
|
||||
private AppEngineConnection connection;
|
||||
|
||||
@Override
|
||||
public void setConnection(Connection connection) {
|
||||
public void setConnection(AppEngineConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
|
@ -127,10 +127,7 @@ class LoadTestCommand extends ConfirmingCommand
|
|||
.put("runSeconds", runSeconds)
|
||||
.build();
|
||||
|
||||
return connection.send(
|
||||
LoadTestAction.PATH,
|
||||
params,
|
||||
MediaType.PLAIN_TEXT_UTF_8,
|
||||
new byte[0]);
|
||||
return connection.sendPostRequest(
|
||||
LoadTestAction.PATH, params, MediaType.PLAIN_TEXT_UTF_8, new byte[0]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,53 +0,0 @@
|
|||
// Copyright 2018 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.google.api.client.googleapis.auth.oauth2.GoogleCredential;
|
||||
import com.google.api.services.monitoring.v3.Monitoring;
|
||||
import com.google.api.services.monitoring.v3.model.MonitoredResource;
|
||||
import com.google.monitoring.metrics.MetricWriter;
|
||||
import com.google.monitoring.metrics.stackdriver.StackdriverWriter;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.config.CredentialModule.DefaultCredential;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
|
||||
/** Dagger module for metrics on the client tool. */
|
||||
@Module
|
||||
public final class MetricToolModule {
|
||||
|
||||
@Provides
|
||||
static Monitoring provideMonitoring(
|
||||
@DefaultCredential GoogleCredential credential, @Config("projectId") String projectId) {
|
||||
return new Monitoring.Builder(
|
||||
credential.getTransport(), credential.getJsonFactory(), credential)
|
||||
.setApplicationName(projectId)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
static MetricWriter provideMetricWriter(
|
||||
Monitoring monitoringClient,
|
||||
@Config("projectId") String projectId,
|
||||
@Config("stackdriverMaxQps") int maxQps,
|
||||
@Config("stackdriverMaxPointsPerRequest") int maxPointsPerRequest) {
|
||||
return new StackdriverWriter(
|
||||
monitoringClient,
|
||||
projectId,
|
||||
new MonitoredResource().setType("global"),
|
||||
maxQps,
|
||||
maxPointsPerRequest);
|
||||
}
|
||||
}
|
|
@ -57,19 +57,19 @@ final class RegistrarContactCommand extends MutatingCommand {
|
|||
@Parameter(
|
||||
description = "Client identifier of the registrar account.",
|
||||
required = true)
|
||||
private List<String> mainParameters;
|
||||
List<String> mainParameters;
|
||||
|
||||
@Parameter(
|
||||
names = "--mode",
|
||||
description = "Type of operation you want to perform (LIST, CREATE, UPDATE, or DELETE).",
|
||||
required = true)
|
||||
private Mode mode;
|
||||
Mode mode;
|
||||
|
||||
@Nullable
|
||||
@Parameter(
|
||||
names = "--name",
|
||||
description = "Contact name.")
|
||||
private String name;
|
||||
String name;
|
||||
|
||||
@Nullable
|
||||
@Parameter(
|
||||
|
@ -82,7 +82,7 @@ final class RegistrarContactCommand extends MutatingCommand {
|
|||
@Parameter(
|
||||
names = "--email",
|
||||
description = "Contact email address.")
|
||||
private String email;
|
||||
String email;
|
||||
|
||||
@Nullable
|
||||
@Parameter(
|
||||
|
@ -105,7 +105,7 @@ final class RegistrarContactCommand extends MutatingCommand {
|
|||
names = "--allow_console_access",
|
||||
description = "Enable or disable access to the registrar console for this contact.",
|
||||
arity = 1)
|
||||
private Boolean allowConsoleAccess;
|
||||
Boolean allowConsoleAccess;
|
||||
|
||||
@Nullable
|
||||
@Parameter(
|
||||
|
@ -138,7 +138,7 @@ final class RegistrarContactCommand extends MutatingCommand {
|
|||
validateWith = PathParameter.OutputFile.class)
|
||||
private Path output = Paths.get("/dev/stdout");
|
||||
|
||||
private enum Mode { LIST, CREATE, UPDATE, DELETE }
|
||||
enum Mode { LIST, CREATE, UPDATE, DELETE }
|
||||
|
||||
private static final ImmutableSet<Mode> MODES_REQUIRING_CONTACT_SYNC =
|
||||
ImmutableSet.of(Mode.CREATE, Mode.UPDATE, Mode.DELETE);
|
||||
|
|
|
@ -26,19 +26,11 @@ import com.beust.jcommander.Parameter;
|
|||
import com.beust.jcommander.ParameterException;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.beust.jcommander.ParametersDelegate;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.monitoring.metrics.IncrementableMetric;
|
||||
import com.google.monitoring.metrics.LabelDescriptor;
|
||||
import com.google.monitoring.metrics.Metric;
|
||||
import com.google.monitoring.metrics.MetricPoint;
|
||||
import com.google.monitoring.metrics.MetricRegistryImpl;
|
||||
import com.google.monitoring.metrics.MetricWriter;
|
||||
import google.registry.config.RegistryConfig;
|
||||
import google.registry.model.ofy.ObjectifyService;
|
||||
import google.registry.tools.params.ParameterFactory;
|
||||
import java.io.IOException;
|
||||
import java.security.Security;
|
||||
import java.util.Map;
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider;
|
||||
|
@ -62,14 +54,6 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
|||
description = "Returns all command names.")
|
||||
private boolean showAllCommands;
|
||||
|
||||
@VisibleForTesting
|
||||
boolean uploadMetrics = true;
|
||||
|
||||
// Do not make this final - compile-time constant inlining may interfere with JCommander.
|
||||
@ParametersDelegate
|
||||
private AppEngineConnectionFlags appEngineConnectionFlags =
|
||||
new AppEngineConnectionFlags();
|
||||
|
||||
|
||||
// Do not make this final - compile-time constant inlining may interfere with JCommander.
|
||||
@ParametersDelegate
|
||||
|
@ -85,24 +69,6 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
|||
// "shell".
|
||||
private boolean isFirstUse = true;
|
||||
|
||||
private static final ImmutableSet<LabelDescriptor> LABEL_DESCRIPTORS_FOR_COMMANDS =
|
||||
ImmutableSet.of(
|
||||
LabelDescriptor.create("program", "The program used - e.g. nomulus or gtech_tool"),
|
||||
LabelDescriptor.create("environment", "The environment used - e.g. sandbox"),
|
||||
LabelDescriptor.create("command", "The command used"),
|
||||
LabelDescriptor.create("success", "Whether the command succeeded"),
|
||||
LabelDescriptor.create("shell", "Whether the command was called from the nomulus shell"));
|
||||
|
||||
private static final IncrementableMetric commandsCalledCount =
|
||||
MetricRegistryImpl.getDefault()
|
||||
.newIncrementableMetric(
|
||||
"/tools/commands_called",
|
||||
"Count of tool commands called",
|
||||
"count",
|
||||
LABEL_DESCRIPTORS_FOR_COMMANDS);
|
||||
|
||||
private MetricWriter metricWriter = null;
|
||||
|
||||
Map<String, ? extends Class<? extends Command>> commands;
|
||||
String programName;
|
||||
|
||||
|
@ -114,7 +80,6 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
|||
Security.addProvider(new BouncyCastleProvider());
|
||||
|
||||
component = DaggerRegistryToolComponent.builder()
|
||||
.flagsModule(new AppEngineConnectionFlags.FlagsModule(appEngineConnectionFlags))
|
||||
.build();
|
||||
}
|
||||
|
||||
|
@ -124,13 +89,9 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
|||
// http://www.angelikalanger.com/GenericsFAQ/FAQSections/TypeArguments.html#FAQ104
|
||||
@Override
|
||||
public void run(String[] args) throws Exception {
|
||||
boolean inShell = !isFirstUse;
|
||||
isFirstUse = false;
|
||||
|
||||
// Create the JCommander instance.
|
||||
// If we're in the shell, we don't want to update the RegistryCli's parameters (so we give a
|
||||
// dummy object to update)
|
||||
JCommander jcommander = new JCommander(inShell ? new Object() : this);
|
||||
JCommander jcommander = new JCommander(this);
|
||||
jcommander.addConverterFactory(new ParameterFactory());
|
||||
jcommander.setProgramName(programName);
|
||||
|
||||
|
@ -149,8 +110,8 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
|||
// Create the "help" and "shell" commands (these are special in that they don't have a default
|
||||
// constructor).
|
||||
jcommander.addCommand("help", new HelpCommand(jcommander));
|
||||
if (!inShell) {
|
||||
// If we aren't inside a shell, then we want to add the shell command.
|
||||
if (isFirstUse) {
|
||||
isFirstUse = false;
|
||||
ShellCommand shellCommand = new ShellCommand(this);
|
||||
// We have to build the completions based on the jcommander *before* we add the "shell"
|
||||
// command - to avoid completion for the "shell" command itself.
|
||||
|
@ -192,31 +153,17 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
|||
jcommander.getCommands().get(jcommander.getParsedCommand()).getObjects());
|
||||
loggingParams.configureLogging(); // Must be called after parameters are parsed.
|
||||
|
||||
boolean success = false;
|
||||
try {
|
||||
runCommand(command);
|
||||
success = true;
|
||||
} catch (AuthModule.LoginRequiredException ex) {
|
||||
System.err.println("===================================================================");
|
||||
System.err.println("You must login using 'nomulus login' prior to running this command.");
|
||||
System.err.println("===================================================================");
|
||||
} finally {
|
||||
commandsCalledCount.increment(
|
||||
programName,
|
||||
environment.toString(),
|
||||
command.getClass().getSimpleName(),
|
||||
String.valueOf(success),
|
||||
String.valueOf(inShell));
|
||||
exportMetrics();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
exportMetrics();
|
||||
if (metricWriter != null) {
|
||||
metricWriter = null;
|
||||
}
|
||||
if (installer != null) {
|
||||
installer.uninstall();
|
||||
installer = null;
|
||||
|
@ -233,14 +180,6 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
|||
|
||||
private void runCommand(Command command) throws Exception {
|
||||
injectReflectively(RegistryToolComponent.class, component, command);
|
||||
if (metricWriter == null && uploadMetrics) {
|
||||
try {
|
||||
metricWriter = component.metricWriter();
|
||||
} catch (Exception e) {
|
||||
System.err.format("Failed to get metricWriter. Got error:\n%s\n\n", e);
|
||||
uploadMetrics = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (command instanceof CommandWithConnection) {
|
||||
((CommandWithConnection) command).setConnection(getConnection());
|
||||
|
@ -253,7 +192,7 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
|||
RemoteApiOptions options = new RemoteApiOptions();
|
||||
options.server(
|
||||
getConnection().getServer().getHost(), getConnection().getServer().getPort());
|
||||
if (getConnection().isLocalhost()) {
|
||||
if (RegistryConfig.areServersLocal()) {
|
||||
// Use dev credentials for localhost.
|
||||
options.useDevelopmentServerCredential();
|
||||
} else {
|
||||
|
@ -272,25 +211,6 @@ final class RegistryCli implements AutoCloseable, CommandRunner {
|
|||
command.run();
|
||||
}
|
||||
|
||||
private void exportMetrics() {
|
||||
if (metricWriter == null) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
for (Metric<?> metric : MetricRegistryImpl.getDefault().getRegisteredMetrics()) {
|
||||
for (MetricPoint<?> point : metric.getTimestampedValues()) {
|
||||
metricWriter.write(point);
|
||||
}
|
||||
}
|
||||
metricWriter.flush();
|
||||
} catch (IOException e) {
|
||||
System.err.format("Failed to export metrics. Got error:\n%s\n\n", e);
|
||||
System.err.println("Maybe you need to login? Try calling:");
|
||||
System.err.println(" gcloud auth application-default login");
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setEnvironment(RegistryToolEnvironment environment) {
|
||||
this.environment = environment;
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ public final class RegistryTool {
|
|||
.put("create_sandbox_tld", CreateSandboxTldCommand.class)
|
||||
.put("create_tld", CreateTldCommand.class)
|
||||
.put("curl", CurlCommand.class)
|
||||
.put("delete_allocation_tokens", DeleteAllocationTokensCommand.class)
|
||||
.put("delete_domain", DeleteDomainCommand.class)
|
||||
.put("delete_host", DeleteHostCommand.class)
|
||||
.put("delete_premium_list", DeletePremiumListCommand.class)
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
package google.registry.tools;
|
||||
|
||||
import com.google.monitoring.metrics.MetricWriter;
|
||||
import dagger.Component;
|
||||
import google.registry.bigquery.BigqueryModule;
|
||||
import google.registry.config.CredentialModule;
|
||||
|
@ -22,17 +21,15 @@ import google.registry.config.RegistryConfig.ConfigModule;
|
|||
import google.registry.dns.writer.VoidDnsWriterModule;
|
||||
import google.registry.dns.writer.clouddns.CloudDnsWriterModule;
|
||||
import google.registry.dns.writer.dnsupdate.DnsUpdateWriterModule;
|
||||
import google.registry.keyring.KeyringModule;
|
||||
import google.registry.keyring.api.DummyKeyringModule;
|
||||
import google.registry.keyring.api.KeyModule;
|
||||
import google.registry.keyring.kms.KmsModule;
|
||||
import google.registry.rde.RdeModule;
|
||||
import google.registry.request.Modules.AppIdentityCredentialModule;
|
||||
import google.registry.request.Modules.DatastoreServiceModule;
|
||||
import google.registry.request.Modules.GoogleCredentialModule;
|
||||
import google.registry.request.Modules.Jackson2Module;
|
||||
import google.registry.request.Modules.NetHttpTransportModule;
|
||||
import google.registry.request.Modules.URLFetchServiceModule;
|
||||
import google.registry.request.Modules.UrlFetchTransportModule;
|
||||
import google.registry.request.Modules.UseAppIdentityCredentialForGoogleApisModule;
|
||||
import google.registry.request.Modules.UserServiceModule;
|
||||
import google.registry.util.AppEngineServiceUtilsImpl.AppEngineServiceUtilsModule;
|
||||
import google.registry.util.SystemClock.SystemClockModule;
|
||||
|
@ -49,37 +46,30 @@ import javax.inject.Singleton;
|
|||
@Singleton
|
||||
@Component(
|
||||
modules = {
|
||||
AppEngineConnectionFlags.FlagsModule.class,
|
||||
AppEngineServiceUtilsModule.class,
|
||||
// TODO(b/36866706): Find a way to replace this with a command-line friendly version
|
||||
AppIdentityCredentialModule.class,
|
||||
AuthModule.class,
|
||||
BigqueryModule.class,
|
||||
ConfigModule.class,
|
||||
CredentialModule.class,
|
||||
DatastoreServiceModule.class,
|
||||
google.registry.keyring.api.DummyKeyringModule.class,
|
||||
DummyKeyringModule.class,
|
||||
CloudDnsWriterModule.class,
|
||||
DefaultRequestFactoryModule.class,
|
||||
DefaultRequestFactoryModule.RequestFactoryModule.class,
|
||||
DnsUpdateWriterModule.class,
|
||||
GoogleCredentialModule.class,
|
||||
Jackson2Module.class,
|
||||
KeyModule.class,
|
||||
KeyringModule.class,
|
||||
KmsModule.class,
|
||||
NetHttpTransportModule.class,
|
||||
RdeModule.class,
|
||||
RegistryToolModule.class,
|
||||
SystemClockModule.class,
|
||||
SystemSleeperModule.class,
|
||||
URLFetchServiceModule.class,
|
||||
UrlFetchTransportModule.class,
|
||||
// TODO(b/36866706): Find a way to replace this with a command-line friendly version
|
||||
UseAppIdentityCredentialForGoogleApisModule.class,
|
||||
UserServiceModule.class,
|
||||
VoidDnsWriterModule.class,
|
||||
WhoisModule.class,
|
||||
MetricToolModule.class,
|
||||
})
|
||||
interface RegistryToolComponent {
|
||||
void inject(CheckDomainClaimsCommand command);
|
||||
|
@ -118,6 +108,4 @@ interface RegistryToolComponent {
|
|||
void inject(WhoisQueryCommand command);
|
||||
|
||||
AppEngineConnection appEngineConnection();
|
||||
|
||||
MetricWriter metricWriter();
|
||||
}
|
||||
|
|
|
@ -1,67 +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.tools;
|
||||
|
||||
import dagger.Binds;
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
import google.registry.util.RandomStringGenerator;
|
||||
import google.registry.util.StringGenerator;
|
||||
import google.registry.util.StringGenerator.Alphabets;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.ProviderException;
|
||||
import java.security.SecureRandom;
|
||||
import javax.inject.Named;
|
||||
|
||||
/** Dagger module for Registry Tool. */
|
||||
@Module
|
||||
abstract class RegistryToolModule {
|
||||
|
||||
@Provides
|
||||
static RegistryToolEnvironment provideRegistryToolEnvironment() {
|
||||
return RegistryToolEnvironment.get();
|
||||
}
|
||||
|
||||
@Binds
|
||||
abstract StringGenerator provideStringGenerator(RandomStringGenerator stringGenerator);
|
||||
|
||||
@Provides
|
||||
static SecureRandom provideSecureRandom() {
|
||||
try {
|
||||
return SecureRandom.getInstance("NativePRNG");
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
throw new ProviderException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named("alphabetBase64")
|
||||
static String provideAlphabetBase64() {
|
||||
return Alphabets.BASE_64;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named("alphabetBase58")
|
||||
static String provideAlphabetBase58() {
|
||||
return Alphabets.BASE_58;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Named("base58StringGenerator")
|
||||
static StringGenerator provideBase58StringGenerator(
|
||||
@Named("alphabetBase58") String alphabet, SecureRandom random) {
|
||||
return new RandomStringGenerator(alphabet, random);
|
||||
}
|
||||
}
|
|
@ -15,15 +15,21 @@
|
|||
package google.registry.tools;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static google.registry.model.ofy.ObjectifyService.ofy;
|
||||
import static google.registry.tools.CommandUtilities.promptForYes;
|
||||
import static google.registry.util.X509Utils.loadCertificate;
|
||||
|
||||
import com.beust.jcommander.Parameter;
|
||||
import com.beust.jcommander.Parameters;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSortedMap;
|
||||
import com.google.re2j.Pattern;
|
||||
import google.registry.config.RegistryConfig.Config;
|
||||
import google.registry.config.RegistryEnvironment;
|
||||
import google.registry.model.common.GaeUserIdConverter;
|
||||
import google.registry.model.registrar.Registrar;
|
||||
import google.registry.model.registry.Registry.TldState;
|
||||
import google.registry.tools.params.PathParameter;
|
||||
|
@ -53,6 +59,10 @@ final class SetupOteCommand extends ConfirmingCommand implements CommandWithRemo
|
|||
private static final Duration SHORT_REDEMPTION_GRACE_PERIOD = Duration.standardMinutes(10);
|
||||
private static final Duration SHORT_PENDING_DELETE_LENGTH = Duration.standardMinutes(5);
|
||||
|
||||
// Whether to prompt the user on command failures. Set to false for testing of these failures.
|
||||
@VisibleForTesting
|
||||
static boolean interactive = true;
|
||||
|
||||
private static final ImmutableSortedMap<DateTime, Money> EAP_FEE_SCHEDULE =
|
||||
ImmutableSortedMap.of(
|
||||
new DateTime(0),
|
||||
|
@ -87,6 +97,14 @@ final class SetupOteCommand extends ConfirmingCommand implements CommandWithRemo
|
|||
)
|
||||
private List<String> ipWhitelist = new ArrayList<>();
|
||||
|
||||
@Parameter(
|
||||
names = {"--email"},
|
||||
description =
|
||||
"the registrar's account to use for console access. "
|
||||
+ "Must be on the registry's G-Suite domain.",
|
||||
required = true)
|
||||
private String email;
|
||||
|
||||
@Parameter(
|
||||
names = {"-c", "--certfile"},
|
||||
description = "full path to cert file in PEM format (best if on local storage)",
|
||||
|
@ -122,7 +140,9 @@ final class SetupOteCommand extends ConfirmingCommand implements CommandWithRemo
|
|||
)
|
||||
private boolean eapOnly = false;
|
||||
|
||||
@Inject StringGenerator passwordGenerator;
|
||||
@Inject
|
||||
@Config("base64StringGenerator")
|
||||
StringGenerator passwordGenerator;
|
||||
|
||||
/**
|
||||
* Long registrar names are truncated and then have an incrementing digit appended at the end so
|
||||
|
@ -130,6 +150,21 @@ final class SetupOteCommand extends ConfirmingCommand implements CommandWithRemo
|
|||
*/
|
||||
private int roidSuffixCounter = 0;
|
||||
|
||||
/** Runs a command, clearing the cache before and prompting the user on failures. */
|
||||
private void runCommand(Command command) {
|
||||
ofy().clearSessionCache();
|
||||
try {
|
||||
command.run();
|
||||
} catch (Exception e) {
|
||||
System.err.format("Command failed with error %s\n", e);
|
||||
if (interactive && promptForYes("Continue to next command?")) {
|
||||
return;
|
||||
}
|
||||
Throwables.throwIfUnchecked(e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Constructs and runs a CreateTldCommand. */
|
||||
private void createTld(
|
||||
String tldName,
|
||||
|
@ -137,8 +172,7 @@ final class SetupOteCommand extends ConfirmingCommand implements CommandWithRemo
|
|||
Duration addGracePeriod,
|
||||
Duration redemptionGracePeriod,
|
||||
Duration pendingDeleteLength,
|
||||
boolean isEarlyAccess)
|
||||
throws Exception {
|
||||
boolean isEarlyAccess) {
|
||||
CreateTldCommand command = new CreateTldCommand();
|
||||
command.addGracePeriod = addGracePeriod;
|
||||
command.dnsWriters = dnsWriters;
|
||||
|
@ -158,11 +192,11 @@ final class SetupOteCommand extends ConfirmingCommand implements CommandWithRemo
|
|||
if (isEarlyAccess) {
|
||||
command.eapFeeSchedule = EAP_FEE_SCHEDULE;
|
||||
}
|
||||
command.run();
|
||||
runCommand(command);
|
||||
}
|
||||
|
||||
/** Constructs and runs a CreateRegistrarCommand */
|
||||
private void createRegistrar(String registrarName, String password, String tld) throws Exception {
|
||||
private void createRegistrar(String registrarName, String password, String tld) {
|
||||
CreateRegistrarCommand command = new CreateRegistrarCommand();
|
||||
command.mainParameters = ImmutableList.of(registrarName);
|
||||
command.createGoogleGroups = false; // Don't create Google Groups for OT&E registrars.
|
||||
|
@ -183,7 +217,19 @@ final class SetupOteCommand extends ConfirmingCommand implements CommandWithRemo
|
|||
command.phone = Optional.of("+1.2125550100");
|
||||
command.icannReferralEmail = "nightmare@registrar.test";
|
||||
command.force = force;
|
||||
command.run();
|
||||
runCommand(command);
|
||||
}
|
||||
|
||||
/** Constructs and runs a RegistrarContactCommand */
|
||||
private void createRegistrarContact(String registrarName) {
|
||||
RegistrarContactCommand command = new RegistrarContactCommand();
|
||||
command.mainParameters = ImmutableList.of(registrarName);
|
||||
command.mode = RegistrarContactCommand.Mode.CREATE;
|
||||
command.name = email;
|
||||
command.email = email;
|
||||
command.allowConsoleAccess = true;
|
||||
command.force = force;
|
||||
runCommand(command);
|
||||
}
|
||||
|
||||
/** Run any pre-execute command checks */
|
||||
|
@ -193,6 +239,14 @@ final class SetupOteCommand extends ConfirmingCommand implements CommandWithRemo
|
|||
REGISTRAR_PATTERN.matcher(registrar).matches(),
|
||||
"Registrar name is invalid (see usage text for requirements).");
|
||||
|
||||
// Make sure the email is "correct" - as in it's a valid email we can convert to gaeId
|
||||
// There's no need to look at the result - it'll be converted again inside
|
||||
// RegistrarContactCommand.
|
||||
checkNotNull(
|
||||
GaeUserIdConverter.convertEmailAddressToGaeUserId(email),
|
||||
"Email address %s is not associated with any GAE ID",
|
||||
email);
|
||||
|
||||
boolean warned = false;
|
||||
if (RegistryEnvironment.get() != RegistryEnvironment.SANDBOX
|
||||
&& RegistryEnvironment.get() != RegistryEnvironment.UNITTEST) {
|
||||
|
@ -227,7 +281,9 @@ final class SetupOteCommand extends ConfirmingCommand implements CommandWithRemo
|
|||
return "Creating TLD:\n"
|
||||
+ " " + registrar + "-eap\n"
|
||||
+ "Creating registrar:\n"
|
||||
+ " " + registrar + "-5 (access to TLD " + registrar + "-eap)";
|
||||
+ " " + registrar + "-5 (access to TLD " + registrar + "-eap)\n"
|
||||
+ "Giving contact access to this registrar:\n"
|
||||
+ " " + email;
|
||||
} else {
|
||||
return "Creating TLDs:\n"
|
||||
+ " " + registrar + "-sunrise\n"
|
||||
|
@ -239,7 +295,9 @@ final class SetupOteCommand extends ConfirmingCommand implements CommandWithRemo
|
|||
+ " " + registrar + "-2 (access to TLD " + registrar + "-landrush)\n"
|
||||
+ " " + registrar + "-3 (access to TLD " + registrar + "-ga)\n"
|
||||
+ " " + registrar + "-4 (access to TLD " + registrar + "-ga)\n"
|
||||
+ " " + registrar + "-5 (access to TLD " + registrar + "-eap)";
|
||||
+ " " + registrar + "-5 (access to TLD " + registrar + "-eap)\n"
|
||||
+ "Giving contact access to these registrars:\n"
|
||||
+ " " + email;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,6 +355,7 @@ final class SetupOteCommand extends ConfirmingCommand implements CommandWithRemo
|
|||
|
||||
for (List<String> r : registrars) {
|
||||
createRegistrar(r.get(0), r.get(1), r.get(2));
|
||||
createRegistrarContact(r.get(0));
|
||||
}
|
||||
|
||||
StringBuilder output = new StringBuilder();
|
||||
|
|
|
@ -145,6 +145,80 @@ public class ShellCommand implements Command {
|
|||
return this;
|
||||
}
|
||||
|
||||
private static class OutputEncapsulator {
|
||||
private PrintStream orgStdout;
|
||||
private PrintStream orgStderr;
|
||||
|
||||
private EncapsulatingOutputStream encapsulatedOutputStream = null;
|
||||
private EncapsulatingOutputStream encapsulatedErrorStream = null;
|
||||
|
||||
private Exception error;
|
||||
|
||||
private OutputEncapsulator() {
|
||||
orgStdout = System.out;
|
||||
orgStderr = System.err;
|
||||
encapsulatedOutputStream = new EncapsulatingOutputStream(System.out, "out: ");
|
||||
encapsulatedErrorStream = new EncapsulatingOutputStream(System.out, "err: ");
|
||||
System.setOut(new PrintStream(encapsulatedOutputStream));
|
||||
System.setErr(new PrintStream(encapsulatedErrorStream));
|
||||
}
|
||||
|
||||
void setError(Exception e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
private void restoreOriginalStreams() {
|
||||
try {
|
||||
encapsulatedOutputStream.dumpLastLine();
|
||||
encapsulatedErrorStream.dumpLastLine();
|
||||
System.setOut(orgStdout);
|
||||
System.setErr(orgStderr);
|
||||
if (error != null) {
|
||||
emitFailure(error);
|
||||
} else {
|
||||
emitSuccess();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a success command separator.
|
||||
*
|
||||
* <p>Dumps the last line of output prior to doing this.
|
||||
*/
|
||||
private void emitSuccess() {
|
||||
System.out.println(SUCCESS);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a failure message obtained from the throwable.
|
||||
*
|
||||
* <p>Dumps the last line of output prior to doing this.
|
||||
*/
|
||||
private void emitFailure(Throwable e) {
|
||||
System.out.println(
|
||||
FAILURE
|
||||
+ e.getClass().getName()
|
||||
+ " "
|
||||
+ e.getMessage().replace("\\", "\\\\").replace("\n", "\\n"));
|
||||
}
|
||||
|
||||
/** Run "func" with output encapsulation. */
|
||||
static void run(CommandRunner runner, String[] args) {
|
||||
OutputEncapsulator encapsulator = new OutputEncapsulator();
|
||||
try {
|
||||
runner.run(args);
|
||||
} catch (Exception e) {
|
||||
encapsulator.setError(e);
|
||||
} finally {
|
||||
encapsulator.restoreOriginalStreams();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Run the shell until the user presses "Ctrl-D". */
|
||||
@Override
|
||||
public void run() {
|
||||
|
@ -154,23 +228,6 @@ public class ShellCommand implements Command {
|
|||
String line;
|
||||
DateTime lastTime = clock.nowUtc();
|
||||
while ((line = getLine()) != null) {
|
||||
PrintStream orgStdout = null;
|
||||
PrintStream orgStderr = null;
|
||||
EncapsulatingOutputStream encapsulatedOutputStream = null;
|
||||
EncapsulatingOutputStream encapsulatedErrorStream = null;
|
||||
|
||||
|
||||
// Wrap standard output and error if requested. We have to do so here in run because the flags
|
||||
// haven't been processed in the constructor.
|
||||
if (encapsulateOutput) {
|
||||
orgStdout = System.out;
|
||||
orgStderr = System.err;
|
||||
encapsulatedOutputStream = new EncapsulatingOutputStream(System.out, "out: ");
|
||||
encapsulatedErrorStream = new EncapsulatingOutputStream(System.out, "err: ");
|
||||
System.setOut(new PrintStream(encapsulatedOutputStream));
|
||||
System.setErr(new PrintStream(encapsulatedErrorStream));
|
||||
}
|
||||
|
||||
// Make sure we're not idle for too long. Only relevant when we're "extra careful"
|
||||
if (!dontExitOnIdle
|
||||
&& beExtraCareful
|
||||
|
@ -184,28 +241,17 @@ public class ShellCommand implements Command {
|
|||
if (lineArgs.length == 0) {
|
||||
continue;
|
||||
}
|
||||
Exception lastError = null;
|
||||
try {
|
||||
System.out.println("Barf!!!");
|
||||
runner.run(lineArgs);
|
||||
} catch (Exception e) {
|
||||
lastError = e;
|
||||
System.err.println("Got an exception:\n" + e);
|
||||
}
|
||||
try {
|
||||
if (encapsulatedOutputStream != null) {
|
||||
encapsulatedOutputStream.dumpLastLine();
|
||||
encapsulatedErrorStream.dumpLastLine();
|
||||
System.setOut(orgStdout);
|
||||
System.setErr(orgStderr);
|
||||
if (lastError == null) {
|
||||
emitSuccess();
|
||||
} else {
|
||||
emitFailure(lastError);
|
||||
}
|
||||
|
||||
// Wrap standard output and error if requested. We have to do so here in run because the flags
|
||||
// haven't been processed in the constructor.
|
||||
if (encapsulateOutput) {
|
||||
OutputEncapsulator.run(runner, lineArgs);
|
||||
} else {
|
||||
try {
|
||||
runner.run(lineArgs);
|
||||
} catch (Exception e) {
|
||||
System.err.println("Got an exception:\n" + e);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
if (!encapsulateOutput) {
|
||||
|
@ -244,29 +290,6 @@ public class ShellCommand implements Command {
|
|||
return resultBuilder.build().toArray(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a success command separator.
|
||||
*
|
||||
* <p>Dumps the last line of output prior to doing this.
|
||||
*/
|
||||
private void emitSuccess() {
|
||||
System.out.println(SUCCESS);
|
||||
System.out.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a failure message obtained from the throwable.
|
||||
*
|
||||
* <p>Dumps the last line of output prior to doing this.
|
||||
*/
|
||||
private void emitFailure(Throwable e) {
|
||||
System.out.println(
|
||||
FAILURE
|
||||
+ e.getClass().getName()
|
||||
+ " "
|
||||
+ e.getMessage().replace("\\", "\\\\").replace("\n", "\\n"));
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static class JCommanderCompletor implements Completor {
|
||||
|
||||
|
|
|
@ -57,10 +57,10 @@ final class VerifyOteCommand implements CommandWithConnection, CommandWithRemote
|
|||
description = "Only show a summary of information")
|
||||
private boolean summarize;
|
||||
|
||||
private Connection connection;
|
||||
private AppEngineConnection connection;
|
||||
|
||||
@Override
|
||||
public void setConnection(Connection connection) {
|
||||
public void setConnection(AppEngineConnection connection) {
|
||||
this.connection = connection;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,4 @@ handlers = java.util.logging.ConsoleHandler
|
|||
.level = INFO
|
||||
com.google.wrappers.base.GoogleInit.level = WARNING
|
||||
com.google.monitoring.metrics.MetricRegistryImpl.level = WARNING
|
||||
com.google.monitoring.metrics.MetricReporter.level = WARNING
|
||||
com.google.monitoring.metrics.MetricExporter.level = WARNING
|
||||
com.google.monitoring.metrics.stackdriver.StackdriverWriter.level = WARNING
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue