[Refactor] Move graphqloptions to its own class (#6496)

Signed-off-by: Gabriel-Trintinalia <gabriel.trintinalia@consensys.net>
pull/6500/head
Gabriel-Trintinalia 10 months ago committed by GitHub
parent 8972d6707c
commit bc36d2c4c2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 70
      besu/src/main/java/org/hyperledger/besu/cli/BesuCommand.java
  2. 112
      besu/src/main/java/org/hyperledger/besu/cli/options/stable/GraphQlOptions.java
  3. 65
      besu/src/test/java/org/hyperledger/besu/cli/BesuCommandTest.java
  4. 93
      besu/src/test/java/org/hyperledger/besu/cli/options/GraphQlOptionsTest.java

@ -24,7 +24,6 @@ import static org.hyperledger.besu.cli.config.NetworkName.MAINNET;
import static org.hyperledger.besu.cli.util.CommandLineUtils.DEPENDENCY_WARNING_MSG;
import static org.hyperledger.besu.cli.util.CommandLineUtils.isOptionSet;
import static org.hyperledger.besu.controller.BesuController.DATABASE_PATH;
import static org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration.DEFAULT_GRAPHQL_HTTP_PORT;
import static org.hyperledger.besu.ethereum.api.jsonrpc.JsonRpcConfiguration.DEFAULT_ENGINE_JSON_RPC_PORT;
import static org.hyperledger.besu.ethereum.api.jsonrpc.authentication.EngineAuthService.EPHEMERAL_JWT_FILE;
import static org.hyperledger.besu.metrics.BesuMetricCategory.DEFAULT_METRIC_CATEGORIES;
@ -44,7 +43,6 @@ import org.hyperledger.besu.cli.config.NetworkName;
import org.hyperledger.besu.cli.config.ProfileName;
import org.hyperledger.besu.cli.converter.MetricCategoryConverter;
import org.hyperledger.besu.cli.converter.PercentageConverter;
import org.hyperledger.besu.cli.custom.CorsAllowedOriginsProperty;
import org.hyperledger.besu.cli.custom.JsonRPCAllowlistHostsProperty;
import org.hyperledger.besu.cli.error.BesuExecutionExceptionHandler;
import org.hyperledger.besu.cli.error.BesuParameterExceptionHandler;
@ -52,6 +50,7 @@ import org.hyperledger.besu.cli.options.MiningOptions;
import org.hyperledger.besu.cli.options.TransactionPoolOptions;
import org.hyperledger.besu.cli.options.stable.DataStorageOptions;
import org.hyperledger.besu.cli.options.stable.EthstatsOptions;
import org.hyperledger.besu.cli.options.stable.GraphQlOptions;
import org.hyperledger.besu.cli.options.stable.JsonRpcHttpOptions;
import org.hyperledger.besu.cli.options.stable.LoggingLevelOption;
import org.hyperledger.besu.cli.options.stable.NodePrivateKeyFileOption;
@ -557,35 +556,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
private final Path kzgTrustedSetupFile = null;
@CommandLine.ArgGroup(validate = false, heading = "@|bold GraphQL Options|@%n")
GraphQlOptionGroup graphQlOptionGroup = new GraphQlOptionGroup();
static class GraphQlOptionGroup {
@Option(
names = {"--graphql-http-enabled"},
description = "Set to start the GraphQL HTTP service (default: ${DEFAULT-VALUE})")
private final Boolean isGraphQLHttpEnabled = false;
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
@Option(
names = {"--graphql-http-host"},
paramLabel = MANDATORY_HOST_FORMAT_HELP,
description = "Host for GraphQL HTTP to listen on (default: ${DEFAULT-VALUE})",
arity = "1")
private String graphQLHttpHost;
@Option(
names = {"--graphql-http-port"},
paramLabel = MANDATORY_PORT_FORMAT_HELP,
description = "Port for GraphQL HTTP to listen on (default: ${DEFAULT-VALUE})",
arity = "1")
private final Integer graphQLHttpPort = DEFAULT_GRAPHQL_HTTP_PORT;
@Option(
names = {"--graphql-http-cors-origins"},
description = "Comma separated origin domain URLs for CORS validation (default: none)")
protected final CorsAllowedOriginsProperty graphQLHttpCorsAllowedOrigins =
new CorsAllowedOriginsProperty();
}
GraphQlOptions graphQlOptions = new GraphQlOptions();
// Engine JSON-PRC Options
@CommandLine.ArgGroup(validate = false, heading = "@|bold Engine JSON-RPC Options|@%n")
@ -1511,6 +1482,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
validatePostMergeCheckpointBlockRequirements();
validateTransactionPoolOptions();
validateDataStorageOptions();
validateGraphQlOptions();
p2pTLSConfigOptions.checkP2PTLSOptionsDependencies(logger, commandLine);
pkiBlockCreationOptions.checkPkiBlockCreationOptionsDependencies(logger, commandLine);
}
@ -1556,6 +1528,10 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
}
}
private void validateGraphQlOptions() {
graphQlOptions.validate(logger, commandLine);
}
@SuppressWarnings("ConstantConditions")
private void validateNatParams() {
if (!(natMethod.equals(NatMethod.AUTO) || natMethod.equals(NatMethod.KUBERNETES))
@ -1750,7 +1726,11 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
engineRPCOptionGroup.engineRpcPort, engineRPCOptionGroup.engineHostsAllowlist);
}
p2pTLSConfiguration = p2pTLSConfigOptions.p2pTLSConfiguration(commandLine);
graphQLConfiguration = graphQLConfiguration();
graphQLConfiguration =
graphQlOptions.graphQLConfiguration(
hostsAllowlist,
p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress(),
unstableRPCOptions.getHttpTimeoutSec());
webSocketConfiguration =
rpcWebsocketOptions.webSocketConfiguration(
hostsAllowlist,
@ -1902,28 +1882,6 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
return txSValidatorService.map(PluginTransactionValidatorService::get).orElse(null);
}
private GraphQLConfiguration graphQLConfiguration() {
CommandLineUtils.checkOptionDependencies(
logger,
commandLine,
"--graphql-http-enabled",
!graphQlOptionGroup.isGraphQLHttpEnabled,
asList("--graphql-http-cors-origins", "--graphql-http-host", "--graphql-http-port"));
final GraphQLConfiguration graphQLConfiguration = GraphQLConfiguration.createDefault();
graphQLConfiguration.setEnabled(graphQlOptionGroup.isGraphQLHttpEnabled);
graphQLConfiguration.setHost(
Strings.isNullOrEmpty(graphQlOptionGroup.graphQLHttpHost)
? p2PDiscoveryOptionGroup.autoDiscoverDefaultIP().getHostAddress()
: graphQlOptionGroup.graphQLHttpHost);
graphQLConfiguration.setPort(graphQlOptionGroup.graphQLHttpPort);
graphQLConfiguration.setHostsAllowlist(hostsAllowlist);
graphQLConfiguration.setCorsAllowedDomains(graphQlOptionGroup.graphQLHttpCorsAllowedOrigins);
graphQLConfiguration.setHttpTimeoutSec(unstableRPCOptions.getHttpTimeoutSec());
return graphQLConfiguration;
}
private JsonRpcConfiguration createEngineJsonRpcConfiguration(
final Integer engineListenPort, final List<String> allowCallsFrom) {
jsonRpcHttpOptions.checkDependencies(logger, commandLine);
@ -2633,9 +2591,7 @@ public class BesuCommand implements DefaultCommandValues, Runnable {
addPortIfEnabled(
effectivePorts, p2PDiscoveryOptionGroup.p2pPort, p2PDiscoveryOptionGroup.p2pEnabled);
addPortIfEnabled(
effectivePorts,
graphQlOptionGroup.graphQLHttpPort,
graphQlOptionGroup.isGraphQLHttpEnabled);
effectivePorts, graphQlOptions.getGraphQLHttpPort(), graphQlOptions.isGraphQLHttpEnabled());
addPortIfEnabled(
effectivePorts, jsonRpcHttpOptions.getRpcHttpPort(), jsonRpcHttpOptions.isRpcHttpEnabled());
addPortIfEnabled(

@ -0,0 +1,112 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.cli.options.stable;
import static java.util.Arrays.asList;
import static org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration.DEFAULT_GRAPHQL_HTTP_PORT;
import org.hyperledger.besu.cli.DefaultCommandValues;
import org.hyperledger.besu.cli.custom.CorsAllowedOriginsProperty;
import org.hyperledger.besu.cli.util.CommandLineUtils;
import org.hyperledger.besu.ethereum.api.graphql.GraphQLConfiguration;
import java.util.List;
import com.google.common.base.Strings;
import org.slf4j.Logger;
import picocli.CommandLine;
/** Handles configuration options for the GraphQL HTTP service in Besu. */
public class GraphQlOptions {
@CommandLine.Option(
names = {"--graphql-http-enabled"},
description = "Set to start the GraphQL HTTP service (default: ${DEFAULT-VALUE})")
private final Boolean isGraphQLHttpEnabled = false;
@SuppressWarnings({"FieldCanBeFinal", "FieldMayBeFinal"}) // PicoCLI requires non-final Strings.
@CommandLine.Option(
names = {"--graphql-http-host"},
paramLabel = DefaultCommandValues.MANDATORY_HOST_FORMAT_HELP,
description = "Host for GraphQL HTTP to listen on (default: ${DEFAULT-VALUE})",
arity = "1")
private String graphQLHttpHost;
@CommandLine.Option(
names = {"--graphql-http-port"},
paramLabel = DefaultCommandValues.MANDATORY_PORT_FORMAT_HELP,
description = "Port for GraphQL HTTP to listen on (default: ${DEFAULT-VALUE})",
arity = "1")
private final Integer graphQLHttpPort = DEFAULT_GRAPHQL_HTTP_PORT;
@CommandLine.Option(
names = {"--graphql-http-cors-origins"},
description = "Comma separated origin domain URLs for CORS validation (default: none)")
private final CorsAllowedOriginsProperty graphQLHttpCorsAllowedOrigins =
new CorsAllowedOriginsProperty();
/**
* Validates the GraphQL HTTP options.
*
* @param logger Logger instance
* @param commandLine CommandLine instance
*/
public void validate(final Logger logger, final CommandLine commandLine) {
CommandLineUtils.checkOptionDependencies(
logger,
commandLine,
"--graphql-http-enabled",
!isGraphQLHttpEnabled,
asList("--graphql-http-cors-origins", "--graphql-http-host", "--graphql-http-port"));
}
/**
* Creates a GraphQLConfiguration based on the provided options.
*
* @param hostsAllowlist List of hosts allowed
* @param defaultHostAddress Default host address
* @param timoutSec Timeout in seconds
* @return A GraphQLConfiguration instance
*/
public GraphQLConfiguration graphQLConfiguration(
final List<String> hostsAllowlist, final String defaultHostAddress, final Long timoutSec) {
final GraphQLConfiguration graphQLConfiguration = GraphQLConfiguration.createDefault();
graphQLConfiguration.setEnabled(isGraphQLHttpEnabled);
graphQLConfiguration.setHost(
Strings.isNullOrEmpty(graphQLHttpHost) ? defaultHostAddress : graphQLHttpHost);
graphQLConfiguration.setPort(graphQLHttpPort);
graphQLConfiguration.setHostsAllowlist(hostsAllowlist);
graphQLConfiguration.setCorsAllowedDomains(graphQLHttpCorsAllowedOrigins);
graphQLConfiguration.setHttpTimeoutSec(timoutSec);
return graphQLConfiguration;
}
/**
* Checks if GraphQL over HTTP is enabled.
*
* @return true if enabled, false otherwise
*/
public Boolean isGraphQLHttpEnabled() {
return isGraphQLHttpEnabled;
}
/**
* Returns the port for GraphQL over HTTP.
*
* @return The port number
*/
public Integer getGraphQLHttpPort() {
return graphQLHttpPort;
}
}

@ -1594,19 +1594,6 @@ public class BesuCommandTest extends CommandTestAbstract {
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void graphQLHttpEnabledPropertyMustBeUsed() {
parseCommand("--graphql-http-enabled");
verify(mockRunnerBuilder).graphQLConfiguration(graphQLConfigArgumentCaptor.capture());
verify(mockRunnerBuilder).build();
assertThat(graphQLConfigArgumentCaptor.getValue().isEnabled()).isTrue();
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void rpcApisSupportsEngine() {
parseCommand("--rpc-http-api", "ENGINE", "--rpc-http-enabled");
@ -1736,58 +1723,6 @@ public class BesuCommandTest extends CommandTestAbstract {
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void graphQLHttpHostAndPortOptionsMustBeUsed() {
final String host = "1.2.3.4";
final int port = 1234;
parseCommand(
"--graphql-http-enabled",
"--graphql-http-host",
host,
"--graphql-http-port",
String.valueOf(port));
verify(mockRunnerBuilder).graphQLConfiguration(graphQLConfigArgumentCaptor.capture());
verify(mockRunnerBuilder).build();
assertThat(graphQLConfigArgumentCaptor.getValue().getHost()).isEqualTo(host);
assertThat(graphQLConfigArgumentCaptor.getValue().getPort()).isEqualTo(port);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void graphQLHttpHostMayBeLocalhost() {
final String host = "localhost";
parseCommand("--graphql-http-enabled", "--graphql-http-host", host);
verify(mockRunnerBuilder).graphQLConfiguration(graphQLConfigArgumentCaptor.capture());
verify(mockRunnerBuilder).build();
assertThat(graphQLConfigArgumentCaptor.getValue().getHost()).isEqualTo(host);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void graphQLHttpHostMayBeIPv6() {
final String host = "2600:DB8::8545";
parseCommand("--graphql-http-enabled", "--graphql-http-host", host);
verify(mockRunnerBuilder).graphQLConfiguration(graphQLConfigArgumentCaptor.capture());
verify(mockRunnerBuilder).build();
assertThat(graphQLConfigArgumentCaptor.getValue().getHost()).isEqualTo(host);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
/** test deprecated CLI option * */
@Deprecated
@Test

@ -0,0 +1,93 @@
/*
* Copyright Hyperledger Besu Contributors.
*
* 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.
*
* SPDX-License-Identifier: Apache-2.0
*/
package org.hyperledger.besu.cli.options;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.verify;
import org.hyperledger.besu.cli.CommandTestAbstract;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
@ExtendWith(MockitoExtension.class)
public class GraphQlOptionsTest extends CommandTestAbstract {
@Test
public void graphQLHttpEnabledPropertyMustBeUsed() {
parseCommand("--graphql-http-enabled");
verify(mockRunnerBuilder).graphQLConfiguration(graphQLConfigArgumentCaptor.capture());
verify(mockRunnerBuilder).build();
assertThat(graphQLConfigArgumentCaptor.getValue().isEnabled()).isTrue();
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void graphQLHttpHostAndPortOptionsMustBeUsed() {
final String host = "1.2.3.4";
final int port = 1234;
parseCommand(
"--graphql-http-enabled",
"--graphql-http-host",
host,
"--graphql-http-port",
String.valueOf(port));
verify(mockRunnerBuilder).graphQLConfiguration(graphQLConfigArgumentCaptor.capture());
verify(mockRunnerBuilder).build();
assertThat(graphQLConfigArgumentCaptor.getValue().getHost()).isEqualTo(host);
assertThat(graphQLConfigArgumentCaptor.getValue().getPort()).isEqualTo(port);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void graphQLHttpHostMayBeLocalhost() {
final String host = "localhost";
parseCommand("--graphql-http-enabled", "--graphql-http-host", host);
verify(mockRunnerBuilder).graphQLConfiguration(graphQLConfigArgumentCaptor.capture());
verify(mockRunnerBuilder).build();
assertThat(graphQLConfigArgumentCaptor.getValue().getHost()).isEqualTo(host);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
@Test
public void graphQLHttpHostMayBeIPv6() {
final String host = "2600:DB8::8545";
parseCommand("--graphql-http-enabled", "--graphql-http-host", host);
verify(mockRunnerBuilder).graphQLConfiguration(graphQLConfigArgumentCaptor.capture());
verify(mockRunnerBuilder).build();
assertThat(graphQLConfigArgumentCaptor.getValue().getHost()).isEqualTo(host);
assertThat(commandOutput.toString(UTF_8)).isEmpty();
assertThat(commandErrorOutput.toString(UTF_8)).isEmpty();
}
}
Loading…
Cancel
Save