Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

[PIE-1737] Simplify PantheonCommand run and parse methods. #1626

Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
170 changes: 108 additions & 62 deletions pantheon/src/main/java/tech/pegasys/pantheon/cli/PantheonCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,15 @@ void setBannedNodeIds(final List<String> values) {
arity = "1")
private final Integer pendingTxRetentionPeriod = PendingTransactions.DEFAULT_TX_RETENTION_HOURS;

private EthNetworkConfig ethNetworkConfig;
private JsonRpcConfiguration jsonRpcConfiguration;
private GraphQLConfiguration graphQLConfiguration;
private WebSocketConfiguration webSocketConfiguration;
private MetricsConfiguration metricsConfiguration;
private Optional<PermissioningConfiguration> permissioningConfiguration;
private Collection<EnodeURL> staticNodes;
private PantheonController<?> pantheonController;

// Inner class so we can get to loggingLevel.
public class PantheonExceptionHandler
extends CommandLine.AbstractHandler<List<Object>, PantheonExceptionHandler>
Expand Down Expand Up @@ -633,17 +642,36 @@ public void parse(
final PantheonExceptionHandler exceptionHandler,
final InputStream in,
final String... args) {
commandLine = new CommandLine(this).setCaseInsensitiveEnumValuesAllowed(true);
handleStandaloneCommand()
.addSubCommands(resultHandler, in)
.registerConverters()
.handleUnstableOptions()
.preparePlugins()
.parse(resultHandler, exceptionHandler, args);
}

commandLine = new CommandLine(this);

commandLine.setCaseInsensitiveEnumValuesAllowed(true);
@Override
public void run() {
try {
prepareLogging();
logger.info("Starting Pantheon version: {}", PantheonInfo.version());
checkOptions().configure().controller().startPlugins().startSynchronization();
} catch (final Exception e) {
throw new ParameterException(this.commandLine, e.getMessage(), e);
}
}

private PantheonCommand handleStandaloneCommand() {
standaloneCommands = new StandaloneCommand();

if (isFullInstantiation()) {
commandLine.addMixin("standaloneCommands", standaloneCommands);
}
return this;
}

private PantheonCommand addSubCommands(
final AbstractParseResultHandler<List<Object>> resultHandler, final InputStream in) {
commandLine.addSubcommand(
BlocksSubCommand.COMMAND_NAME, new BlocksSubCommand(blockImporter, resultHandler.out()));
commandLine.addSubcommand(
Expand All @@ -655,21 +683,26 @@ public void parse(
RLPSubCommand.COMMAND_NAME, new RLPSubCommand(resultHandler.out(), in));
commandLine.addSubcommand(
OperatorSubCommand.COMMAND_NAME, new OperatorSubCommand(resultHandler.out()));
return this;
}

private PantheonCommand registerConverters() {
commandLine.registerConverter(Address.class, Address::fromHexStringStrict);
commandLine.registerConverter(BytesValue.class, BytesValue::fromHexString);
commandLine.registerConverter(Level.class, Level::valueOf);
commandLine.registerConverter(SyncMode.class, SyncMode::fromString);
commandLine.registerConverter(UInt256.class, (arg) -> UInt256.of(new BigInteger(arg)));
commandLine.registerConverter(Wei.class, (arg) -> Wei.of(Long.parseUnsignedLong(arg)));
commandLine.registerConverter(PositiveNumber.class, PositiveNumber::fromString);

final MetricCategoryConverter metricCategoryConverter = new MetricCategoryConverter();
metricCategoryConverter.addCategories(PantheonMetricCategory.class);
metricCategoryConverter.addCategories(StandardMetricCategory.class);
commandLine.registerConverter(MetricCategory.class, metricCategoryConverter);
return this;
}

// Add performance options
private PantheonCommand handleUnstableOptions() {
// Add unstable options
UnstableOptionsSubCommand.createUnstableOptions(
commandLine,
ImmutableMap.of(
Expand All @@ -681,29 +714,64 @@ public void parse(
ethereumWireConfigurationBuilder,
"TransactionPool",
transactionPoolConfigurationBuilder));
return this;
}

private PantheonCommand preparePlugins() {
pantheonPluginContext.addService(PicoCLIOptions.class, new PicoCLIOptionsImpl(commandLine));
pantheonPluginContext.registerPlugins(pluginsDir());
return this;
}

private PantheonCommand parse(
final AbstractParseResultHandler<List<Object>> resultHandler,
final PantheonExceptionHandler exceptionHandler,
final String... args) {
// Create a handler that will search for a config file option and use it for
// default values
// and eventually it will run regular parsing of the remaining options.
final ConfigOptionSearchAndRunHandler configParsingHandler =
new ConfigOptionSearchAndRunHandler(
resultHandler, exceptionHandler, CONFIG_FILE_OPTION_NAME, environment, isDocker);
commandLine.parseWithHandlers(configParsingHandler, exceptionHandler, args);
return this;
}

@Override
public void run() {
private PantheonCommand startSynchronization() {
synchronize(
pantheonController,
p2pEnabled,
peerDiscoveryEnabled,
ethNetworkConfig,
maxPeers,
p2pHost,
p2pPort,
graphQLConfiguration,
jsonRpcConfiguration,
webSocketConfiguration,
metricsConfiguration,
permissioningConfiguration,
staticNodes);
return this;
}

private PantheonCommand startPlugins() {
pantheonPluginContext.addService(
PantheonEvents.class,
new PantheonEventsImpl((pantheonController.getProtocolManager().getBlockBroadcaster())));
pantheonPluginContext.startPlugins();
return this;
}

private void prepareLogging() {
// set log level per CLI flags
if (logLevel != null) {
System.out.println("Setting logging level to " + logLevel.name());
Configurator.setAllLevels("", logLevel);
}
}

logger.info("Starting Pantheon version: {}", PantheonInfo.version());

private PantheonCommand checkOptions() {
// Check that P2P options are able to work or send an error
checkOptionDependencies(
logger,
Expand Down Expand Up @@ -739,59 +807,32 @@ public void run() {
"Unable to mine without a valid coinbase. Either disable mining (remove --miner-enabled)"
+ "or specify the beneficiary of mining (via --miner-coinbase <Address>)");
}
return this;
}

final EthNetworkConfig ethNetworkConfig = updateNetworkConfig(getNetwork());
try {
final JsonRpcConfiguration jsonRpcConfiguration = jsonRpcConfiguration();
final GraphQLConfiguration graphQLConfiguration = graphQLConfiguration();
final WebSocketConfiguration webSocketConfiguration = webSocketConfiguration();
final Optional<PermissioningConfiguration> permissioningConfiguration =
permissioningConfiguration();

final Collection<EnodeURL> staticNodes = loadStaticNodes();
logger.info("Connecting to {} static nodes.", staticNodes.size());
logger.trace("Static Nodes = {}", staticNodes);

final List<URI> enodeURIs =
ethNetworkConfig.getBootNodes().stream()
.map(EnodeURL::toURI)
.collect(Collectors.toList());
permissioningConfiguration
.flatMap(PermissioningConfiguration::getLocalConfig)
.ifPresent(p -> ensureAllNodesAreInWhitelist(enodeURIs, p));

permissioningConfiguration
.flatMap(PermissioningConfiguration::getLocalConfig)
.ifPresent(
p ->
ensureAllNodesAreInWhitelist(
staticNodes.stream().map(EnodeURL::toURI).collect(Collectors.toList()), p));

final PantheonController<?> pantheonController = buildController();
final MetricsConfiguration metricsConfiguration = metricsConfiguration();

pantheonPluginContext.addService(
PantheonEvents.class,
new PantheonEventsImpl((pantheonController.getProtocolManager().getBlockBroadcaster())));
pantheonPluginContext.startPlugins();

synchronize(
pantheonController,
p2pEnabled,
peerDiscoveryEnabled,
ethNetworkConfig,
maxPeers,
p2pHost,
p2pPort,
graphQLConfiguration,
jsonRpcConfiguration,
webSocketConfiguration,
metricsConfiguration,
permissioningConfiguration,
staticNodes);
} catch (final Exception e) {
throw new ParameterException(this.commandLine, e.getMessage(), e);
}
private PantheonCommand configure() throws Exception {
ethNetworkConfig = updateNetworkConfig(getNetwork());
jsonRpcConfiguration = jsonRpcConfiguration();
graphQLConfiguration = graphQLConfiguration();
webSocketConfiguration = webSocketConfiguration();
permissioningConfiguration = permissioningConfiguration();
staticNodes = loadStaticNodes();
logger.info("Connecting to {} static nodes.", staticNodes.size());
logger.trace("Static Nodes = {}", staticNodes);
final List<URI> enodeURIs =
ethNetworkConfig.getBootNodes().stream().map(EnodeURL::toURI).collect(Collectors.toList());
permissioningConfiguration
.flatMap(PermissioningConfiguration::getLocalConfig)
.ifPresent(p -> ensureAllNodesAreInWhitelist(enodeURIs, p));

permissioningConfiguration
.flatMap(PermissioningConfiguration::getLocalConfig)
.ifPresent(
p ->
ensureAllNodesAreInWhitelist(
staticNodes.stream().map(EnodeURL::toURI).collect(Collectors.toList()), p));
metricsConfiguration = metricsConfiguration();
return this;
}

private NetworkName getNetwork() {
Expand All @@ -811,6 +852,11 @@ private void ensureAllNodesAreInWhitelist(
}
}

private PantheonCommand controller() {
pantheonController = buildController();
return this;
}

PantheonController<?> buildController() {
try {
return controllerBuilderFactory
Expand Down