From ca41aca7bce71f45adc8d547184f037c7e37041e Mon Sep 17 00:00:00 2001 From: DaveTeng0 Date: Tue, 21 May 2024 14:50:01 -0700 Subject: [PATCH 1/9] RATIS-2095. Move common logic of ratis-shell to RaftUtils so that Ozone shell could share and use common logic --- ratis-shell/pom.xml | 8 + .../org/apache/ratis/shell/cli/RaftUtils.java | 165 +++++++++++++++++- .../apache/ratis/shell/cli/SecurityUtils.java | 63 +++++++ .../cli/sh/command/AbstractRatisCommand.java | 96 +++++----- .../shell/cli/sh/election/PauseCommand.java | 4 +- .../shell/cli/sh/election/ResumeCommand.java | 4 +- .../cli/sh/election/StepDownCommand.java | 4 +- .../cli/sh/election/TransferCommand.java | 6 +- .../shell/cli/sh/group/GroupListCommand.java | 6 +- .../ratis/shell/cli/sh/peer/AddCommand.java | 4 +- .../shell/cli/sh/peer/RemoveCommand.java | 4 +- .../shell/cli/sh/peer/SetPriorityCommand.java | 4 +- .../cli/sh/snapshot/TakeSnapshotCommand.java | 4 +- 13 files changed, 310 insertions(+), 62 deletions(-) create mode 100644 ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java diff --git a/ratis-shell/pom.xml b/ratis-shell/pom.xml index 78ab6679fd..5b06bca1a0 100644 --- a/ratis-shell/pom.xml +++ b/ratis-shell/pom.xml @@ -48,6 +48,14 @@ org.slf4j slf4j-simple + + org.apache.ratis + ratis-grpc + + + org.apache.ratis + ratis-netty + diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java index 1239fc56c4..73c1f2a5cb 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java @@ -19,21 +19,35 @@ import org.apache.ratis.client.RaftClient; import org.apache.ratis.client.RaftClientConfigKeys; +import org.apache.ratis.conf.Parameters; import org.apache.ratis.conf.RaftProperties; -import org.apache.ratis.protocol.RaftGroup; -import org.apache.ratis.protocol.RaftPeerId; +import org.apache.ratis.grpc.GrpcConfigKeys; +import org.apache.ratis.grpc.GrpcTlsConfig; +import org.apache.ratis.netty.NettyConfigKeys; +import org.apache.ratis.protocol.*; +import org.apache.ratis.protocol.exceptions.RaftException; import org.apache.ratis.retry.ExponentialBackoffRetry; +import org.apache.ratis.rpc.RpcType; +import org.apache.ratis.rpc.SupportedRpcType; import org.apache.ratis.util.TimeDuration; +import org.apache.ratis.util.function.CheckedFunction; +import java.io.IOException; +import java.io.PrintStream; import java.net.InetSocketAddress; -import java.util.Properties; +import java.util.*; import java.util.concurrent.TimeUnit; +import java.util.function.*; +import java.util.stream.Collectors; /** * Helper class for raft operations. */ public final class RaftUtils { + public static final RaftGroupId DEFAULT_RAFT_GROUP_ID = RaftGroupId.randomId(); + + private RaftUtils() { // prevent instantiation } @@ -65,6 +79,18 @@ public static RaftPeerId getPeerId(String host, int port) { * @return return a raft client */ public static RaftClient createClient(RaftGroup raftGroup) { + return createClient(raftGroup, null, null); + } + + + /** + * Create a raft client to communicate to ratis server. + * @param raftGroup the raft group + * @param rpcType the rpcType + * @param tlsConfig the tlsConfig + * @return return a raft client + */ + public static RaftClient createClient(RaftGroup raftGroup, RpcType rpcType, GrpcTlsConfig tlsConfig) { RaftProperties properties = new RaftProperties(); RaftClientConfigKeys.Rpc.setRequestTimeout(properties, TimeDuration.valueOf(15, TimeUnit.SECONDS)); @@ -84,6 +110,139 @@ public static RaftClient createClient(RaftGroup raftGroup) { .setRaftGroup(raftGroup) .setProperties(properties) .setRetryPolicy(retryPolicy) + .setParameters(setClientTlsConf(rpcType, tlsConfig)) .build(); } + + /** + * Execute a given function with input parameter from the members of a list. + * + * @param list the input parameters + * @param function the function to be executed + * @param parameter type + * @param return value type + * @param the exception type thrown by the given function. + * @return the value returned by the given function. + */ + public static K runFunction(Collection list, CheckedFunction function) { + for (T t : list) { + try { + K ret = function.apply(t); + if (ret != null) { + return ret; + } + } catch (Throwable e) { + e.printStackTrace(); + } + } + return null; + } + + + public static List buildRaftPeersFromStr(String peers) { + List addresses = new ArrayList<>(); + String[] peersArray = peers.split(","); + for (String peer : peersArray) { + addresses.add(parseInetSocketAddress(peer)); + } + + return addresses.stream() + .map(addr -> RaftPeer.newBuilder() + .setId(RaftUtils.getPeerId(addr)) + .setAddress(addr) + .build() + ).collect(Collectors.toList()); + } + + public static RaftGroupId buildRaftGroupIdFromStr(String groupId) { + return (groupId != null && !groupId.equals("")) ? RaftGroupId.valueOf(UUID.fromString(groupId)) + : DEFAULT_RAFT_GROUP_ID; + } + + public static RaftGroupId retrieveRemoteGroupId(RaftGroupId raftGroupIdFromConfig, + List peers, + RaftClient client, PrintStream printStream) throws IOException { + RaftGroupId remoteGroupId; + if (raftGroupIdFromConfig != DEFAULT_RAFT_GROUP_ID) { + return raftGroupIdFromConfig; + } else { + final List groupIds = runFunction(peers, + p -> client.getGroupManagementApi((p.getId())).list().getGroupIds()); + + if (groupIds == null) { + printStream.println("Failed to get group ID from " + peers); + throw new IOException("Failed to get group ID from " + peers); + } else if (groupIds.size() == 1) { + remoteGroupId = groupIds.get(0); + } else { + printStream.println("There are more than one groups, you should specific one. " + groupIds); + throw new IOException("There are more than one groups, you should specific one. " + groupIds); + } + } + + return remoteGroupId; + } + + public static GroupInfoReply retrieveGroupInfoByGroupId(RaftGroupId remoteGroupId, List peers, RaftClient client, PrintStream printStream) + throws IOException { + GroupInfoReply groupInfoReply = runFunction(peers, p -> client.getGroupManagementApi((p.getId())).info(remoteGroupId)); + processReply(groupInfoReply, + printStream::println, "Failed to get group info for group id " + remoteGroupId.getUuid() + " from " + peers); + return groupInfoReply; + } + + public static void processReply(RaftClientReply reply, Consumer printer, String message) throws IOException { + processReplyInternal(reply, () -> printer.accept(message)); + } + + private static void processReplyInternal(RaftClientReply reply, Runnable printer) throws IOException { + if (reply == null || !reply.isSuccess()) { + final RaftException e = Optional.ofNullable(reply) + .map(RaftClientReply::getException) + .orElseGet(() -> new RaftException("Reply: " + reply)); + printer.run(); + throw new IOException(e.getMessage(), e); + } + } + + public static InetSocketAddress parseInetSocketAddress(String address) { + try { + final String[] hostPortPair = address.split(":"); + if (hostPortPair.length < 2) { + throw new IllegalArgumentException("Unexpected address format ."); + } + return new InetSocketAddress(hostPortPair[0], Integer.parseInt(hostPortPair[1])); + } catch (Exception e) { + throw new IllegalArgumentException("Failed to parse the server address parameter \"" + address + "\".", e); + } + } + + public static Parameters setClientTlsConf(RpcType rpcType, + GrpcTlsConfig tlsConfig) { + // TODO: GRPC TLS only for now, netty/hadoop RPC TLS support later. + if (tlsConfig != null && rpcType == SupportedRpcType.GRPC) { + Parameters parameters = new Parameters(); + setAdminTlsConf(parameters, tlsConfig); + setClientTlsConf(parameters, tlsConfig); + return parameters; + } + return null; + } + + private static void setAdminTlsConf(Parameters parameters, + GrpcTlsConfig tlsConfig) { + if (tlsConfig != null) { + GrpcConfigKeys.Admin.setTlsConf(parameters, tlsConfig); + } + } + + private static void setClientTlsConf(Parameters parameters, + GrpcTlsConfig tlsConfig) { + if (tlsConfig != null) { + GrpcConfigKeys.Client.setTlsConf(parameters, tlsConfig); + NettyConfigKeys.DataStream.Client.setTlsConf(parameters, tlsConfig); + } + } + + } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java new file mode 100644 index 0000000000..14150ffe6c --- /dev/null +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java @@ -0,0 +1,63 @@ +package org.apache.ratis.shell.cli; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.net.ssl.TrustManager; +import javax.net.ssl.TrustManagerFactory; +import javax.net.ssl.X509TrustManager; +import java.io.*; +import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.Arrays; +import java.util.Optional; +import java.util.function.Supplier; + +public class SecurityUtils { + static Logger LOG = LoggerFactory.getLogger(SecurityUtils.class); + + public static KeyStore getTrustStore() + throws Exception { + X509Certificate[] certificate = getCertificate("ssl/ca.crt"); + + // build trustStore + KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); + trustStore.load(null, null); + + for (X509Certificate cert: certificate) { + trustStore.setCertificateEntry(cert.getSerialNumber().toString(), cert); + } + return trustStore; + } + + public static X509TrustManager getTrustManager(KeyStore keyStore) throws Exception{ + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( + TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(keyStore); + TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); + if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { + throw new IllegalStateException("Unexpected default trust managers:" + + Arrays.toString(trustManagers)); + } + return (X509TrustManager) trustManagers[0]; + } + + static X509Certificate[] getCertificate(String certPath) + throws CertificateException, IOException { + // Read certificates + X509Certificate[] certificate = new X509Certificate[1]; + CertificateFactory fact = CertificateFactory.getInstance("X.509"); + try (InputStream is = Files.newInputStream(Paths.get(certPath))) { + certificate[0] = (X509Certificate) fact.generateCertificate(is); + } + return certificate; + } + +} diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java index 1888c0e0ea..022fa25b52 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java @@ -20,33 +20,48 @@ import org.apache.commons.cli.Option; import org.apache.ratis.protocol.*; import org.apache.ratis.protocol.exceptions.RaftException; +import org.apache.ratis.rpc.SupportedRpcType; import org.apache.ratis.shell.cli.RaftUtils; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; import org.apache.ratis.client.RaftClient; +import org.apache.ratis.grpc.GrpcTlsConfig; import org.apache.ratis.proto.RaftProtos.RaftConfigurationProto; import org.apache.ratis.proto.RaftProtos.FollowerInfoProto; import org.apache.ratis.proto.RaftProtos.RaftPeerProto; import org.apache.ratis.proto.RaftProtos.RaftPeerRole; import org.apache.ratis.proto.RaftProtos.RoleInfoProto; +import org.apache.ratis.shell.cli.SecurityUtils; import org.apache.ratis.util.ProtoUtils; import org.apache.ratis.util.function.CheckedFunction; +import javax.net.ssl.TrustManager; import java.io.IOException; +import java.io.PrintStream; import java.net.InetSocketAddress; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.cert.CertificateException; import java.util.*; import java.util.function.BiConsumer; import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; +import static org.apache.ratis.shell.cli.RaftUtils.*; +import static org.apache.ratis.shell.cli.RaftUtils.retrieveGroupInfoByGroupId; + /** * The base class for the ratis shell which need to connect to server. */ public abstract class AbstractRatisCommand extends AbstractCommand { public static final String PEER_OPTION_NAME = "peers"; public static final String GROUPID_OPTION_NAME = "groupid"; - public static final RaftGroupId DEFAULT_RAFT_GROUP_ID = RaftGroupId.randomId(); + public static final String TLS_ENABLED_OPTION_NAME = "t"; + private PrintStream printStream; + + /** * Execute a given function with input parameter from the members of a list. @@ -77,52 +92,22 @@ public static K run(Collection list, CheckedFunct protected AbstractRatisCommand(Context context) { super(context); + this.printStream = getPrintStream(); } @Override public int run(CommandLine cl) throws IOException { - List addresses = new ArrayList<>(); - String peersStr = cl.getOptionValue(PEER_OPTION_NAME); - String[] peersArray = peersStr.split(","); - for (String peer : peersArray) { - addresses.add(parseInetSocketAddress(peer)); - } - final RaftGroupId raftGroupIdFromConfig = cl.hasOption(GROUPID_OPTION_NAME)? - RaftGroupId.valueOf(UUID.fromString(cl.getOptionValue(GROUPID_OPTION_NAME))) - : DEFAULT_RAFT_GROUP_ID; - - List peers = addresses.stream() - .map(addr -> RaftPeer.newBuilder() - .setId(RaftUtils.getPeerId(addr)) - .setAddress(addr) - .build() - ).collect(Collectors.toList()); + List peers = buildRaftPeersFromStr(cl.getOptionValue(PEER_OPTION_NAME)); + RaftGroupId raftGroupIdFromConfig = buildRaftGroupIdFromStr(cl.getOptionValue(GROUPID_OPTION_NAME)); raftGroup = RaftGroup.valueOf(raftGroupIdFromConfig, peers); - try (final RaftClient client = RaftUtils.createClient(raftGroup)) { - final RaftGroupId remoteGroupId; - if (raftGroupIdFromConfig != DEFAULT_RAFT_GROUP_ID) { - remoteGroupId = raftGroupIdFromConfig; - } else { - final List groupIds = run(peers, - p -> client.getGroupManagementApi((p.getId())).list().getGroupIds()); - - if (groupIds == null) { - println("Failed to get group ID from " + peers); - return -1; - } else if (groupIds.size() == 1) { - remoteGroupId = groupIds.get(0); - } else { - println("There are more than one groups, you should specific one. " + groupIds); - return -2; - } - } - groupInfoReply = run(peers, p -> client.getGroupManagementApi((p.getId())).info(remoteGroupId)); - processReply(groupInfoReply, - () -> "Failed to get group info for group id " + remoteGroupId.getUuid() + " from " + peers); + try (final RaftClient client = getRaftClient(cl.hasOption(TLS_ENABLED_OPTION_NAME))) { + RaftGroupId remoteGroupId = retrieveRemoteGroupId(raftGroupIdFromConfig, peers, client, printStream);; + groupInfoReply = retrieveGroupInfoByGroupId(remoteGroupId, peers, client, printStream); raftGroup = groupInfoReply.getGroup(); } + return 0; } @@ -167,16 +152,16 @@ protected RaftPeerProto getLeader(RoleInfoProto roleInfo) { return followerInfo.getLeaderInfo().getId(); } - protected void processReply(RaftClientReply reply, Supplier messageSupplier) throws IOException { - if (reply == null || !reply.isSuccess()) { - final RaftException e = Optional.ofNullable(reply) - .map(RaftClientReply::getException) - .orElseGet(() -> new RaftException("Reply: " + reply)); - final String message = messageSupplier.get(); - printf("%s. Error: %s%n", message, e); - throw new IOException(message, e); - } - } +// protected void processReply(RaftClientReply reply, Supplier messageSupplier) throws IOException { +// if (reply == null || !reply.isSuccess()) { +// final RaftException e = Optional.ofNullable(reply) +// .map(RaftClientReply::getException) +// .orElseGet(() -> new RaftException("Reply: " + reply)); +// final String message = messageSupplier.get(); +// printf(printStream, "%s. Error: %s%n", message, e); +// throw new IOException(message, e); +// } +// } protected List getIds(String[] optionValues, BiConsumer consumer) { if (optionValues == null) { @@ -207,4 +192,19 @@ protected Stream getPeerStream(RaftPeerRole role) { .stream() .filter(targets::contains); } + + private RaftClient getRaftClient(boolean tlsEnabled) throws + IOException { + GrpcTlsConfig tlsConfig = null; + if (tlsEnabled) { + try { + TrustManager trustManager = SecurityUtils.getTrustManager(SecurityUtils.getTrustStore()); + tlsConfig = new GrpcTlsConfig(null, trustManager, false); + } catch (Exception e) { + throw new IOException("Failed to get TrustManager: " + e.getCause()); + } + } + return RaftUtils.createClient(raftGroup, SupportedRpcType.GRPC, tlsConfig); + } + } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/PauseCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/PauseCommand.java index 4ea2969bac..80e7bae254 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/PauseCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/PauseCommand.java @@ -30,6 +30,8 @@ import java.io.IOException; +import static org.apache.ratis.shell.cli.RaftUtils.processReply; + /** * Command for pause leader election on specific server */ @@ -63,7 +65,7 @@ public int run(CommandLine cl) throws IOException { } try(final RaftClient raftClient = RaftUtils.createClient(getRaftGroup())) { RaftClientReply reply = raftClient.getLeaderElectionManagementApi(peerId).pause(); - processReply(reply, () -> String.format("Failed to pause leader election on peer %s", strAddr)); + processReply(reply, this::println, String.format("Failed to pause leader election on peer %s", strAddr)); printf(String.format("Successful pause leader election on peer %s", strAddr)); } return 0; diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/ResumeCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/ResumeCommand.java index 4b4dc225a0..9eb92cae40 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/ResumeCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/ResumeCommand.java @@ -30,6 +30,8 @@ import java.io.IOException; +import static org.apache.ratis.shell.cli.RaftUtils.processReply; + /** * Command for resuming leader election on specific server */ @@ -63,7 +65,7 @@ public int run(CommandLine cl) throws IOException { } try(final RaftClient raftClient = RaftUtils.createClient(getRaftGroup())) { RaftClientReply reply = raftClient.getLeaderElectionManagementApi(peerId).resume(); - processReply(reply, () -> String.format("Failed to resume leader election on peer %s", strAddr)); + processReply(reply, this::println, String.format("Failed to resume leader election on peer %s", strAddr)); printf(String.format("Successful pause leader election on peer %s", strAddr)); } return 0; diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/StepDownCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/StepDownCommand.java index 911a2bb26a..54398f86be 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/StepDownCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/StepDownCommand.java @@ -27,6 +27,8 @@ import java.io.IOException; +import static org.apache.ratis.shell.cli.RaftUtils.processReply; + /** * Command for stepping down ratis leader server. */ @@ -51,7 +53,7 @@ public int run(CommandLine cl) throws IOException { try (RaftClient client = RaftUtils.createClient(getRaftGroup())) { RaftPeerId leaderId = RaftPeerId.valueOf(getLeader(getGroupInfoReply().getRoleInfoProto()).getId()); final RaftClientReply transferLeadershipReply = client.admin().transferLeadership(null, leaderId, 60_000); - processReply(transferLeadershipReply, () -> "Failed to step down leader"); + processReply(transferLeadershipReply, this::println, "Failed to step down leader"); } catch (Throwable t) { printf("caught an error when executing step down leader: %s%n", t.getMessage()); return -1; diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/TransferCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/TransferCommand.java index c71d7f89f6..2567427bcc 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/TransferCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/TransferCommand.java @@ -36,6 +36,8 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +import static org.apache.ratis.shell.cli.RaftUtils.processReply; + /** * Command for transferring the ratis leader to specific server. */ @@ -98,7 +100,7 @@ private boolean tryTransfer(RaftClient client, RaftPeer newLeader, int highestPr } RaftClientReply transferLeadershipReply = client.admin().transferLeadership(newLeader.getId(), timeout.toLong(TimeUnit.MILLISECONDS)); - processReply(transferLeadershipReply, () -> "election failed"); + processReply(transferLeadershipReply, this::println,"election failed"); } catch (TransferLeadershipException tle) { if (tle.getMessage().contains("it does not has highest priority")) { return false; @@ -116,7 +118,7 @@ private void setPriority(RaftClient client, RaftPeer target, int priority) throw .collect(Collectors.toList()); final List listeners = getPeerStream(RaftPeerRole.LISTENER).collect(Collectors.toList()); RaftClientReply reply = client.admin().setConfiguration(peers, listeners); - processReply(reply, () -> "Failed to set master priorities"); + processReply(reply, this::println, "Failed to set master priorities"); } @Override diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupListCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupListCommand.java index 5bbd1939ad..1d3ef2ec2a 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupListCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupListCommand.java @@ -31,6 +31,8 @@ import java.io.IOException; import java.net.InetSocketAddress; +import static org.apache.ratis.shell.cli.RaftUtils.processReply; + /** * Command for querying the group information of a ratis server. */ @@ -71,8 +73,8 @@ public int run(CommandLine cl) throws IOException { try(final RaftClient raftClient = RaftUtils.createClient(getRaftGroup())) { GroupListReply reply = raftClient.getGroupManagementApi(peerId).list(); - processReply(reply, () -> String.format("Failed to get group information of peerId %s (server %s)", - peerId, address)); + processReply(reply, this::println, String.format("Failed to get group information of peerId %s (server %s)", + peerId.toString(), address)); printf(String.format("The peerId %s (server %s) is in %d groups, and the groupIds is: %s", peerId, address, reply.getGroupIds().size(), reply.getGroupIds())); } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/AddCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/AddCommand.java index 3c65bb12de..35a6612326 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/AddCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/AddCommand.java @@ -38,6 +38,8 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import static org.apache.ratis.shell.cli.RaftUtils.processReply; + /** * Command for add ratis server. */ @@ -93,7 +95,7 @@ public int run(CommandLine cl) throws IOException { System.out.println("New peer list: " + peers); System.out.println("New listener list: " + listeners); RaftClientReply reply = client.admin().setConfiguration(peers, listeners); - processReply(reply, () -> "Failed to change raft peer"); + processReply(reply, this::println, "Failed to change raft peer"); } return 0; } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/RemoveCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/RemoveCommand.java index 5918516070..8c578ffb48 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/RemoveCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/RemoveCommand.java @@ -34,6 +34,8 @@ import java.util.List; import java.util.stream.Collectors; +import static org.apache.ratis.shell.cli.RaftUtils.processReply; + /** * Command for remove ratis server. */ @@ -74,7 +76,7 @@ public int run(CommandLine cl) throws IOException { System.out.println("New peer list: " + peers); System.out.println("New listener list: " + listeners); final RaftClientReply reply = client.admin().setConfiguration(peers, listeners); - processReply(reply, () -> "Failed to change raft peer"); + processReply(reply, this::println, "Failed to change raft peer"); } return 0; } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/SetPriorityCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/SetPriorityCommand.java index 01e81f3c34..624c6e9d8d 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/SetPriorityCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/SetPriorityCommand.java @@ -34,6 +34,8 @@ import java.util.Map; import java.util.stream.Collectors; +import static org.apache.ratis.shell.cli.RaftUtils.processReply; + public class SetPriorityCommand extends AbstractRatisCommand { public static final String PEER_WITH_NEW_PRIORITY_OPTION_NAME = "addressPriority"; @@ -72,7 +74,7 @@ public int run(CommandLine cl) throws IOException { final List listeners = getPeerStream(RaftPeerRole.LISTENER).collect(Collectors.toList()); RaftClientReply reply = client.admin().setConfiguration(peers, listeners); - processReply(reply, () -> "Failed to set master priorities "); + processReply(reply, this::println, "Failed to set master priorities "); } return 0; } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java index 10bac34975..c005dae780 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java @@ -29,6 +29,8 @@ import java.io.IOException; +import static org.apache.ratis.shell.cli.RaftUtils.processReply; + /** * Command for make a ratis server take snapshot. */ @@ -65,7 +67,7 @@ public int run(CommandLine cl) throws IOException { peerId = null; } RaftClientReply reply = raftClient.getSnapshotManagementApi(peerId).create(timeout); - processReply(reply, () -> String.format("Failed to take snapshot of peerId %s", peerId)); + processReply(reply, this::println, String.format("Failed to take snapshot of peerId %s", peerId.toString())); printf(String.format("Successful take snapshot on peerId %s, the latest snapshot index is %d", peerId, reply.getLogIndex())); } From cfd4cf313deff7a7536e78953aa807b8d701fe24 Mon Sep 17 00:00:00 2001 From: DaveTeng0 Date: Tue, 21 May 2024 15:53:30 -0700 Subject: [PATCH 2/9] fix import --- .../org/apache/ratis/shell/cli/RaftUtils.java | 17 ++++++--- .../apache/ratis/shell/cli/SecurityUtils.java | 8 ++--- .../cli/sh/command/AbstractRatisCommand.java | 35 +++++++------------ .../cli/sh/election/TransferCommand.java | 2 +- 4 files changed, 29 insertions(+), 33 deletions(-) diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java index 73c1f2a5cb..8385b749d7 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java @@ -24,7 +24,12 @@ import org.apache.ratis.grpc.GrpcConfigKeys; import org.apache.ratis.grpc.GrpcTlsConfig; import org.apache.ratis.netty.NettyConfigKeys; -import org.apache.ratis.protocol.*; +import org.apache.ratis.protocol.GroupInfoReply; +import org.apache.ratis.protocol.RaftClientReply; +import org.apache.ratis.protocol.RaftGroup; +import org.apache.ratis.protocol.RaftGroupId; +import org.apache.ratis.protocol.RaftPeer; +import org.apache.ratis.protocol.RaftPeerId; import org.apache.ratis.protocol.exceptions.RaftException; import org.apache.ratis.retry.ExponentialBackoffRetry; import org.apache.ratis.rpc.RpcType; @@ -35,10 +40,15 @@ import java.io.IOException; import java.io.PrintStream; import java.net.InetSocketAddress; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; import java.util.concurrent.TimeUnit; -import java.util.function.*; +import java.util.function.Consumer; +import java.util.List; +import java.util.Optional; +import java.util.Properties; import java.util.stream.Collectors; +import java.util.UUID; /** * Helper class for raft operations. @@ -47,7 +57,6 @@ public final class RaftUtils { public static final RaftGroupId DEFAULT_RAFT_GROUP_ID = RaftGroupId.randomId(); - private RaftUtils() { // prevent instantiation } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java index 14150ffe6c..22e5f600e0 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java @@ -6,19 +6,15 @@ import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; -import java.io.*; -import java.net.URL; +import java.io.InputStream; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Arrays; -import java.util.Optional; -import java.util.function.Supplier; public class SecurityUtils { static Logger LOG = LoggerFactory.getLogger(SecurityUtils.class); diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java index 022fa25b52..5f6283c5b3 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java @@ -18,8 +18,11 @@ package org.apache.ratis.shell.cli.sh.command; import org.apache.commons.cli.Option; -import org.apache.ratis.protocol.*; -import org.apache.ratis.protocol.exceptions.RaftException; +import org.apache.ratis.protocol.RaftGroup; +import org.apache.ratis.protocol.RaftGroupId; +import org.apache.ratis.protocol.RaftPeer; +import org.apache.ratis.protocol.RaftPeerId; +import org.apache.ratis.protocol.GroupInfoReply; import org.apache.ratis.rpc.SupportedRpcType; import org.apache.ratis.shell.cli.RaftUtils; import org.apache.commons.cli.CommandLine; @@ -39,18 +42,19 @@ import java.io.IOException; import java.io.PrintStream; import java.net.InetSocketAddress; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Set; import java.util.function.BiConsumer; -import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.apache.ratis.shell.cli.RaftUtils.*; +import static org.apache.ratis.shell.cli.RaftUtils.buildRaftGroupIdFromStr; +import static org.apache.ratis.shell.cli.RaftUtils.buildRaftPeersFromStr; import static org.apache.ratis.shell.cli.RaftUtils.retrieveGroupInfoByGroupId; +import static org.apache.ratis.shell.cli.RaftUtils.retrieveRemoteGroupId; /** * The base class for the ratis shell which need to connect to server. @@ -61,8 +65,6 @@ public abstract class AbstractRatisCommand extends AbstractCommand { public static final String TLS_ENABLED_OPTION_NAME = "t"; private PrintStream printStream; - - /** * Execute a given function with input parameter from the members of a list. * @@ -152,17 +154,6 @@ protected RaftPeerProto getLeader(RoleInfoProto roleInfo) { return followerInfo.getLeaderInfo().getId(); } -// protected void processReply(RaftClientReply reply, Supplier messageSupplier) throws IOException { -// if (reply == null || !reply.isSuccess()) { -// final RaftException e = Optional.ofNullable(reply) -// .map(RaftClientReply::getException) -// .orElseGet(() -> new RaftException("Reply: " + reply)); -// final String message = messageSupplier.get(); -// printf(printStream, "%s. Error: %s%n", message, e); -// throw new IOException(message, e); -// } -// } - protected List getIds(String[] optionValues, BiConsumer consumer) { if (optionValues == null) { return Collections.emptyList(); diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/TransferCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/TransferCommand.java index 2567427bcc..d63a137d5a 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/TransferCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/TransferCommand.java @@ -100,7 +100,7 @@ private boolean tryTransfer(RaftClient client, RaftPeer newLeader, int highestPr } RaftClientReply transferLeadershipReply = client.admin().transferLeadership(newLeader.getId(), timeout.toLong(TimeUnit.MILLISECONDS)); - processReply(transferLeadershipReply, this::println,"election failed"); + processReply(transferLeadershipReply, this::println, "election failed"); } catch (TransferLeadershipException tle) { if (tle.getMessage().contains("it does not has highest priority")) { return false; From eae5ae0fd61f860a9c2e3982f7edac463818b208 Mon Sep 17 00:00:00 2001 From: DaveTeng0 Date: Wed, 22 May 2024 10:32:47 -0700 Subject: [PATCH 3/9] fix license, findbug of dereference, line length --- .../org/apache/ratis/shell/cli/RaftUtils.java | 6 ++++-- .../apache/ratis/shell/cli/SecurityUtils.java | 21 ++++++++++++++++++- .../cli/sh/command/AbstractRatisCommand.java | 3 +-- .../cli/sh/snapshot/TakeSnapshotCommand.java | 2 +- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java index 8385b749d7..00ce42dd6a 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java @@ -192,9 +192,11 @@ public static RaftGroupId retrieveRemoteGroupId(RaftGroupId raftGroupIdFromConfi return remoteGroupId; } - public static GroupInfoReply retrieveGroupInfoByGroupId(RaftGroupId remoteGroupId, List peers, RaftClient client, PrintStream printStream) + public static GroupInfoReply retrieveGroupInfoByGroupId(RaftGroupId remoteGroupId, List peers, + RaftClient client, PrintStream printStream) throws IOException { - GroupInfoReply groupInfoReply = runFunction(peers, p -> client.getGroupManagementApi((p.getId())).info(remoteGroupId)); + GroupInfoReply groupInfoReply = runFunction(peers, + p -> client.getGroupManagementApi((p.getId())).info(remoteGroupId)); processReply(groupInfoReply, printStream::println, "Failed to get group info for group id " + remoteGroupId.getUuid() + " from " + peers); return groupInfoReply; diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java index 22e5f600e0..ec70076bf1 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java @@ -1,3 +1,20 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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 org.apache.ratis.shell.cli; import org.slf4j.Logger; @@ -17,7 +34,9 @@ import java.util.Arrays; public class SecurityUtils { - static Logger LOG = LoggerFactory.getLogger(SecurityUtils.class); + private SecurityUtils() { + // prevent instantiation + } public static KeyStore getTrustStore() throws Exception { diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java index 5f6283c5b3..d9334b5092 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java @@ -99,13 +99,12 @@ protected AbstractRatisCommand(Context context) { @Override public int run(CommandLine cl) throws IOException { - List peers = buildRaftPeersFromStr(cl.getOptionValue(PEER_OPTION_NAME)); RaftGroupId raftGroupIdFromConfig = buildRaftGroupIdFromStr(cl.getOptionValue(GROUPID_OPTION_NAME)); raftGroup = RaftGroup.valueOf(raftGroupIdFromConfig, peers); try (final RaftClient client = getRaftClient(cl.hasOption(TLS_ENABLED_OPTION_NAME))) { - RaftGroupId remoteGroupId = retrieveRemoteGroupId(raftGroupIdFromConfig, peers, client, printStream);; + RaftGroupId remoteGroupId = retrieveRemoteGroupId(raftGroupIdFromConfig, peers, client, printStream); groupInfoReply = retrieveGroupInfoByGroupId(remoteGroupId, peers, client, printStream); raftGroup = groupInfoReply.getGroup(); } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java index c005dae780..10b23e8492 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java @@ -67,7 +67,7 @@ public int run(CommandLine cl) throws IOException { peerId = null; } RaftClientReply reply = raftClient.getSnapshotManagementApi(peerId).create(timeout); - processReply(reply, this::println, String.format("Failed to take snapshot of peerId %s", peerId.toString())); + processReply(reply, this::println, String.format("Failed to take snapshot of peerId %s", peerId != null ? peerId.toString() : null)); printf(String.format("Successful take snapshot on peerId %s, the latest snapshot index is %d", peerId, reply.getLogIndex())); } From 19abc56a4eb5301c39c73787a15935562d5fac94 Mon Sep 17 00:00:00 2001 From: DaveTeng0 Date: Wed, 22 May 2024 10:49:01 -0700 Subject: [PATCH 4/9] fix checkstyle --- .../main/java/org/apache/ratis/shell/cli/SecurityUtils.java | 5 +---- .../ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java | 3 ++- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java index ec70076bf1..ac5178cbfb 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java @@ -17,9 +17,6 @@ */ package org.apache.ratis.shell.cli; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import javax.net.ssl.TrustManager; import javax.net.ssl.TrustManagerFactory; import javax.net.ssl.X509TrustManager; @@ -33,7 +30,7 @@ import java.security.cert.X509Certificate; import java.util.Arrays; -public class SecurityUtils { +public final class SecurityUtils { private SecurityUtils() { // prevent instantiation } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java index 10b23e8492..2ff0136e7f 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java @@ -67,7 +67,8 @@ public int run(CommandLine cl) throws IOException { peerId = null; } RaftClientReply reply = raftClient.getSnapshotManagementApi(peerId).create(timeout); - processReply(reply, this::println, String.format("Failed to take snapshot of peerId %s", peerId != null ? peerId.toString() : null)); + processReply(reply, this::println, String.format("Failed to take snapshot of peerId %s", + peerId != null ? peerId.toString() : null)); printf(String.format("Successful take snapshot on peerId %s, the latest snapshot index is %d", peerId, reply.getLogIndex())); } From 17d2e43e82d86607f2d6dea76ad5265261f75d7a Mon Sep 17 00:00:00 2001 From: DaveTeng0 Date: Wed, 22 May 2024 14:29:19 -0700 Subject: [PATCH 5/9] pass path of certificate as command option to ratis shell --- .../java/org/apache/ratis/shell/cli/SecurityUtils.java | 4 ++-- .../ratis/shell/cli/sh/command/AbstractRatisCommand.java | 9 ++++++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java index ac5178cbfb..a55264ac1a 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java @@ -35,9 +35,9 @@ private SecurityUtils() { // prevent instantiation } - public static KeyStore getTrustStore() + public static KeyStore getTrustStore(String crtPath) throws Exception { - X509Certificate[] certificate = getCertificate("ssl/ca.crt"); + X509Certificate[] certificate = getCertificate(crtPath); // build trustStore KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java index d9334b5092..1156d69b9c 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java @@ -63,6 +63,7 @@ public abstract class AbstractRatisCommand extends AbstractCommand { public static final String PEER_OPTION_NAME = "peers"; public static final String GROUPID_OPTION_NAME = "groupid"; public static final String TLS_ENABLED_OPTION_NAME = "t"; + public static final String CERT_PATH_OPTION_NAME = "certPath"; private PrintStream printStream; /** @@ -103,7 +104,8 @@ public int run(CommandLine cl) throws IOException { RaftGroupId raftGroupIdFromConfig = buildRaftGroupIdFromStr(cl.getOptionValue(GROUPID_OPTION_NAME)); raftGroup = RaftGroup.valueOf(raftGroupIdFromConfig, peers); - try (final RaftClient client = getRaftClient(cl.hasOption(TLS_ENABLED_OPTION_NAME))) { + try (final RaftClient client = getRaftClient(cl.hasOption(TLS_ENABLED_OPTION_NAME) && + cl.hasOption(CERT_PATH_OPTION_NAME), cl.getOptionValue(CERT_PATH_OPTION_NAME))) { RaftGroupId remoteGroupId = retrieveRemoteGroupId(raftGroupIdFromConfig, peers, client, printStream); groupInfoReply = retrieveGroupInfoByGroupId(remoteGroupId, peers, client, printStream); raftGroup = groupInfoReply.getGroup(); @@ -183,12 +185,12 @@ protected Stream getPeerStream(RaftPeerRole role) { .filter(targets::contains); } - private RaftClient getRaftClient(boolean tlsEnabled) throws + private RaftClient getRaftClient(boolean tlsEnabled, String crtPath) throws IOException { GrpcTlsConfig tlsConfig = null; if (tlsEnabled) { try { - TrustManager trustManager = SecurityUtils.getTrustManager(SecurityUtils.getTrustStore()); + TrustManager trustManager = SecurityUtils.getTrustManager(SecurityUtils.getTrustStore(crtPath)); tlsConfig = new GrpcTlsConfig(null, trustManager, false); } catch (Exception e) { throw new IOException("Failed to get TrustManager: " + e.getCause()); @@ -197,4 +199,5 @@ private RaftClient getRaftClient(boolean tlsEnabled) throws return RaftUtils.createClient(raftGroup, SupportedRpcType.GRPC, tlsConfig); } + } From a3b4463f677e90393b38083805a3d3562e97d155 Mon Sep 17 00:00:00 2001 From: DaveTeng0 Date: Tue, 28 May 2024 11:21:05 -0700 Subject: [PATCH 6/9] remove securityUtil class, revert changes from subcommands of AbstractRatisCommand to use original processReply method of AbstractRatisCommand --- ratis-shell/pom.xml | 8 -- .../apache/ratis/shell/cli/SecurityUtils.java | 75 ------------------- .../cli/sh/command/AbstractRatisCommand.java | 36 +++------ .../shell/cli/sh/election/PauseCommand.java | 4 +- .../shell/cli/sh/election/ResumeCommand.java | 4 +- .../cli/sh/election/StepDownCommand.java | 4 +- .../cli/sh/election/TransferCommand.java | 6 +- .../shell/cli/sh/group/GroupListCommand.java | 4 +- .../ratis/shell/cli/sh/peer/AddCommand.java | 4 +- .../shell/cli/sh/peer/RemoveCommand.java | 4 +- .../shell/cli/sh/peer/SetPriorityCommand.java | 4 +- .../cli/sh/snapshot/TakeSnapshotCommand.java | 4 +- 12 files changed, 19 insertions(+), 138 deletions(-) delete mode 100644 ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java diff --git a/ratis-shell/pom.xml b/ratis-shell/pom.xml index 5b06bca1a0..78ab6679fd 100644 --- a/ratis-shell/pom.xml +++ b/ratis-shell/pom.xml @@ -48,14 +48,6 @@ org.slf4j slf4j-simple - - org.apache.ratis - ratis-grpc - - - org.apache.ratis - ratis-netty - diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java deleted file mode 100644 index a55264ac1a..0000000000 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/SecurityUtils.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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 org.apache.ratis.shell.cli; - -import javax.net.ssl.TrustManager; -import javax.net.ssl.TrustManagerFactory; -import javax.net.ssl.X509TrustManager; -import java.io.InputStream; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.security.KeyStore; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.Arrays; - -public final class SecurityUtils { - private SecurityUtils() { - // prevent instantiation - } - - public static KeyStore getTrustStore(String crtPath) - throws Exception { - X509Certificate[] certificate = getCertificate(crtPath); - - // build trustStore - KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType()); - trustStore.load(null, null); - - for (X509Certificate cert: certificate) { - trustStore.setCertificateEntry(cert.getSerialNumber().toString(), cert); - } - return trustStore; - } - - public static X509TrustManager getTrustManager(KeyStore keyStore) throws Exception{ - TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance( - TrustManagerFactory.getDefaultAlgorithm()); - trustManagerFactory.init(keyStore); - TrustManager[] trustManagers = trustManagerFactory.getTrustManagers(); - if (trustManagers.length != 1 || !(trustManagers[0] instanceof X509TrustManager)) { - throw new IllegalStateException("Unexpected default trust managers:" - + Arrays.toString(trustManagers)); - } - return (X509TrustManager) trustManagers[0]; - } - - static X509Certificate[] getCertificate(String certPath) - throws CertificateException, IOException { - // Read certificates - X509Certificate[] certificate = new X509Certificate[1]; - CertificateFactory fact = CertificateFactory.getInstance("X.509"); - try (InputStream is = Files.newInputStream(Paths.get(certPath))) { - certificate[0] = (X509Certificate) fact.generateCertificate(is); - } - return certificate; - } - -} diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java index 1156d69b9c..fce7f53a83 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java @@ -18,27 +18,24 @@ package org.apache.ratis.shell.cli.sh.command; import org.apache.commons.cli.Option; +import org.apache.ratis.protocol.RaftClientReply; import org.apache.ratis.protocol.RaftGroup; import org.apache.ratis.protocol.RaftGroupId; import org.apache.ratis.protocol.RaftPeer; import org.apache.ratis.protocol.RaftPeerId; import org.apache.ratis.protocol.GroupInfoReply; -import org.apache.ratis.rpc.SupportedRpcType; import org.apache.ratis.shell.cli.RaftUtils; import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.Options; import org.apache.ratis.client.RaftClient; -import org.apache.ratis.grpc.GrpcTlsConfig; import org.apache.ratis.proto.RaftProtos.RaftConfigurationProto; import org.apache.ratis.proto.RaftProtos.FollowerInfoProto; import org.apache.ratis.proto.RaftProtos.RaftPeerProto; import org.apache.ratis.proto.RaftProtos.RaftPeerRole; import org.apache.ratis.proto.RaftProtos.RoleInfoProto; -import org.apache.ratis.shell.cli.SecurityUtils; import org.apache.ratis.util.ProtoUtils; import org.apache.ratis.util.function.CheckedFunction; -import javax.net.ssl.TrustManager; import java.io.IOException; import java.io.PrintStream; import java.net.InetSocketAddress; @@ -48,6 +45,7 @@ import java.util.List; import java.util.Set; import java.util.function.BiConsumer; +import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -62,9 +60,6 @@ public abstract class AbstractRatisCommand extends AbstractCommand { public static final String PEER_OPTION_NAME = "peers"; public static final String GROUPID_OPTION_NAME = "groupid"; - public static final String TLS_ENABLED_OPTION_NAME = "t"; - public static final String CERT_PATH_OPTION_NAME = "certPath"; - private PrintStream printStream; /** * Execute a given function with input parameter from the members of a list. @@ -95,7 +90,6 @@ public static K run(Collection list, CheckedFunct protected AbstractRatisCommand(Context context) { super(context); - this.printStream = getPrintStream(); } @Override @@ -103,14 +97,12 @@ public int run(CommandLine cl) throws IOException { List peers = buildRaftPeersFromStr(cl.getOptionValue(PEER_OPTION_NAME)); RaftGroupId raftGroupIdFromConfig = buildRaftGroupIdFromStr(cl.getOptionValue(GROUPID_OPTION_NAME)); raftGroup = RaftGroup.valueOf(raftGroupIdFromConfig, peers); - - try (final RaftClient client = getRaftClient(cl.hasOption(TLS_ENABLED_OPTION_NAME) && - cl.hasOption(CERT_PATH_OPTION_NAME), cl.getOptionValue(CERT_PATH_OPTION_NAME))) { + PrintStream printStream = getPrintStream(); + try (final RaftClient client = RaftUtils.createClient(raftGroup)) { RaftGroupId remoteGroupId = retrieveRemoteGroupId(raftGroupIdFromConfig, peers, client, printStream); groupInfoReply = retrieveGroupInfoByGroupId(remoteGroupId, peers, client, printStream); raftGroup = groupInfoReply.getGroup(); } - return 0; } @@ -155,6 +147,11 @@ protected RaftPeerProto getLeader(RoleInfoProto roleInfo) { return followerInfo.getLeaderInfo().getId(); } + protected void processReply(RaftClientReply reply, Supplier messageSupplier) throws IOException { + RaftUtils.processReply(reply, + getPrintStream()::println, messageSupplier.get()); + } + protected List getIds(String[] optionValues, BiConsumer consumer) { if (optionValues == null) { return Collections.emptyList(); @@ -185,19 +182,4 @@ protected Stream getPeerStream(RaftPeerRole role) { .filter(targets::contains); } - private RaftClient getRaftClient(boolean tlsEnabled, String crtPath) throws - IOException { - GrpcTlsConfig tlsConfig = null; - if (tlsEnabled) { - try { - TrustManager trustManager = SecurityUtils.getTrustManager(SecurityUtils.getTrustStore(crtPath)); - tlsConfig = new GrpcTlsConfig(null, trustManager, false); - } catch (Exception e) { - throw new IOException("Failed to get TrustManager: " + e.getCause()); - } - } - return RaftUtils.createClient(raftGroup, SupportedRpcType.GRPC, tlsConfig); - } - - } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/PauseCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/PauseCommand.java index 80e7bae254..4ea2969bac 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/PauseCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/PauseCommand.java @@ -30,8 +30,6 @@ import java.io.IOException; -import static org.apache.ratis.shell.cli.RaftUtils.processReply; - /** * Command for pause leader election on specific server */ @@ -65,7 +63,7 @@ public int run(CommandLine cl) throws IOException { } try(final RaftClient raftClient = RaftUtils.createClient(getRaftGroup())) { RaftClientReply reply = raftClient.getLeaderElectionManagementApi(peerId).pause(); - processReply(reply, this::println, String.format("Failed to pause leader election on peer %s", strAddr)); + processReply(reply, () -> String.format("Failed to pause leader election on peer %s", strAddr)); printf(String.format("Successful pause leader election on peer %s", strAddr)); } return 0; diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/ResumeCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/ResumeCommand.java index 9eb92cae40..4b4dc225a0 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/ResumeCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/ResumeCommand.java @@ -30,8 +30,6 @@ import java.io.IOException; -import static org.apache.ratis.shell.cli.RaftUtils.processReply; - /** * Command for resuming leader election on specific server */ @@ -65,7 +63,7 @@ public int run(CommandLine cl) throws IOException { } try(final RaftClient raftClient = RaftUtils.createClient(getRaftGroup())) { RaftClientReply reply = raftClient.getLeaderElectionManagementApi(peerId).resume(); - processReply(reply, this::println, String.format("Failed to resume leader election on peer %s", strAddr)); + processReply(reply, () -> String.format("Failed to resume leader election on peer %s", strAddr)); printf(String.format("Successful pause leader election on peer %s", strAddr)); } return 0; diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/StepDownCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/StepDownCommand.java index 54398f86be..911a2bb26a 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/StepDownCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/StepDownCommand.java @@ -27,8 +27,6 @@ import java.io.IOException; -import static org.apache.ratis.shell.cli.RaftUtils.processReply; - /** * Command for stepping down ratis leader server. */ @@ -53,7 +51,7 @@ public int run(CommandLine cl) throws IOException { try (RaftClient client = RaftUtils.createClient(getRaftGroup())) { RaftPeerId leaderId = RaftPeerId.valueOf(getLeader(getGroupInfoReply().getRoleInfoProto()).getId()); final RaftClientReply transferLeadershipReply = client.admin().transferLeadership(null, leaderId, 60_000); - processReply(transferLeadershipReply, this::println, "Failed to step down leader"); + processReply(transferLeadershipReply, () -> "Failed to step down leader"); } catch (Throwable t) { printf("caught an error when executing step down leader: %s%n", t.getMessage()); return -1; diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/TransferCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/TransferCommand.java index d63a137d5a..c71d7f89f6 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/TransferCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/election/TransferCommand.java @@ -36,8 +36,6 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; -import static org.apache.ratis.shell.cli.RaftUtils.processReply; - /** * Command for transferring the ratis leader to specific server. */ @@ -100,7 +98,7 @@ private boolean tryTransfer(RaftClient client, RaftPeer newLeader, int highestPr } RaftClientReply transferLeadershipReply = client.admin().transferLeadership(newLeader.getId(), timeout.toLong(TimeUnit.MILLISECONDS)); - processReply(transferLeadershipReply, this::println, "election failed"); + processReply(transferLeadershipReply, () -> "election failed"); } catch (TransferLeadershipException tle) { if (tle.getMessage().contains("it does not has highest priority")) { return false; @@ -118,7 +116,7 @@ private void setPriority(RaftClient client, RaftPeer target, int priority) throw .collect(Collectors.toList()); final List listeners = getPeerStream(RaftPeerRole.LISTENER).collect(Collectors.toList()); RaftClientReply reply = client.admin().setConfiguration(peers, listeners); - processReply(reply, this::println, "Failed to set master priorities"); + processReply(reply, () -> "Failed to set master priorities"); } @Override diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupListCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupListCommand.java index 1d3ef2ec2a..85f1755028 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupListCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupListCommand.java @@ -31,8 +31,6 @@ import java.io.IOException; import java.net.InetSocketAddress; -import static org.apache.ratis.shell.cli.RaftUtils.processReply; - /** * Command for querying the group information of a ratis server. */ @@ -73,7 +71,7 @@ public int run(CommandLine cl) throws IOException { try(final RaftClient raftClient = RaftUtils.createClient(getRaftGroup())) { GroupListReply reply = raftClient.getGroupManagementApi(peerId).list(); - processReply(reply, this::println, String.format("Failed to get group information of peerId %s (server %s)", + processReply(reply, () -> String.format("Failed to get group information of peerId %s (server %s)", peerId.toString(), address)); printf(String.format("The peerId %s (server %s) is in %d groups, and the groupIds is: %s", peerId, address, reply.getGroupIds().size(), reply.getGroupIds())); diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/AddCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/AddCommand.java index 35a6612326..3c65bb12de 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/AddCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/AddCommand.java @@ -38,8 +38,6 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import static org.apache.ratis.shell.cli.RaftUtils.processReply; - /** * Command for add ratis server. */ @@ -95,7 +93,7 @@ public int run(CommandLine cl) throws IOException { System.out.println("New peer list: " + peers); System.out.println("New listener list: " + listeners); RaftClientReply reply = client.admin().setConfiguration(peers, listeners); - processReply(reply, this::println, "Failed to change raft peer"); + processReply(reply, () -> "Failed to change raft peer"); } return 0; } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/RemoveCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/RemoveCommand.java index 8c578ffb48..5918516070 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/RemoveCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/RemoveCommand.java @@ -34,8 +34,6 @@ import java.util.List; import java.util.stream.Collectors; -import static org.apache.ratis.shell.cli.RaftUtils.processReply; - /** * Command for remove ratis server. */ @@ -76,7 +74,7 @@ public int run(CommandLine cl) throws IOException { System.out.println("New peer list: " + peers); System.out.println("New listener list: " + listeners); final RaftClientReply reply = client.admin().setConfiguration(peers, listeners); - processReply(reply, this::println, "Failed to change raft peer"); + processReply(reply, () -> "Failed to change raft peer"); } return 0; } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/SetPriorityCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/SetPriorityCommand.java index 624c6e9d8d..01e81f3c34 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/SetPriorityCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/peer/SetPriorityCommand.java @@ -34,8 +34,6 @@ import java.util.Map; import java.util.stream.Collectors; -import static org.apache.ratis.shell.cli.RaftUtils.processReply; - public class SetPriorityCommand extends AbstractRatisCommand { public static final String PEER_WITH_NEW_PRIORITY_OPTION_NAME = "addressPriority"; @@ -74,7 +72,7 @@ public int run(CommandLine cl) throws IOException { final List listeners = getPeerStream(RaftPeerRole.LISTENER).collect(Collectors.toList()); RaftClientReply reply = client.admin().setConfiguration(peers, listeners); - processReply(reply, this::println, "Failed to set master priorities "); + processReply(reply, () -> "Failed to set master priorities "); } return 0; } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java index 2ff0136e7f..8b11f55d0a 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java @@ -29,8 +29,6 @@ import java.io.IOException; -import static org.apache.ratis.shell.cli.RaftUtils.processReply; - /** * Command for make a ratis server take snapshot. */ @@ -67,7 +65,7 @@ public int run(CommandLine cl) throws IOException { peerId = null; } RaftClientReply reply = raftClient.getSnapshotManagementApi(peerId).create(timeout); - processReply(reply, this::println, String.format("Failed to take snapshot of peerId %s", + processReply(reply, () -> String.format("Failed to take snapshot of peerId %s", peerId != null ? peerId.toString() : null)); printf(String.format("Successful take snapshot on peerId %s, the latest snapshot index is %d", peerId, reply.getLogIndex())); From d4cd16182a46f0e235f28eada02e96fbbcf1f629 Mon Sep 17 00:00:00 2001 From: DaveTeng0 Date: Tue, 28 May 2024 11:53:05 -0700 Subject: [PATCH 7/9] move ratis client with TlsConf to a different PR --- .../org/apache/ratis/shell/cli/RaftUtils.java | 48 +------------------ .../cli/sh/command/AbstractRatisCommand.java | 3 +- .../shell/cli/sh/group/GroupListCommand.java | 2 +- .../cli/sh/snapshot/TakeSnapshotCommand.java | 3 +- 4 files changed, 4 insertions(+), 52 deletions(-) diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java index 00ce42dd6a..090ed289d2 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java @@ -19,11 +19,7 @@ import org.apache.ratis.client.RaftClient; import org.apache.ratis.client.RaftClientConfigKeys; -import org.apache.ratis.conf.Parameters; import org.apache.ratis.conf.RaftProperties; -import org.apache.ratis.grpc.GrpcConfigKeys; -import org.apache.ratis.grpc.GrpcTlsConfig; -import org.apache.ratis.netty.NettyConfigKeys; import org.apache.ratis.protocol.GroupInfoReply; import org.apache.ratis.protocol.RaftClientReply; import org.apache.ratis.protocol.RaftGroup; @@ -32,8 +28,6 @@ import org.apache.ratis.protocol.RaftPeerId; import org.apache.ratis.protocol.exceptions.RaftException; import org.apache.ratis.retry.ExponentialBackoffRetry; -import org.apache.ratis.rpc.RpcType; -import org.apache.ratis.rpc.SupportedRpcType; import org.apache.ratis.util.TimeDuration; import org.apache.ratis.util.function.CheckedFunction; @@ -88,18 +82,6 @@ public static RaftPeerId getPeerId(String host, int port) { * @return return a raft client */ public static RaftClient createClient(RaftGroup raftGroup) { - return createClient(raftGroup, null, null); - } - - - /** - * Create a raft client to communicate to ratis server. - * @param raftGroup the raft group - * @param rpcType the rpcType - * @param tlsConfig the tlsConfig - * @return return a raft client - */ - public static RaftClient createClient(RaftGroup raftGroup, RpcType rpcType, GrpcTlsConfig tlsConfig) { RaftProperties properties = new RaftProperties(); RaftClientConfigKeys.Rpc.setRequestTimeout(properties, TimeDuration.valueOf(15, TimeUnit.SECONDS)); @@ -119,10 +101,10 @@ public static RaftClient createClient(RaftGroup raftGroup, RpcType rpcType, Grpc .setRaftGroup(raftGroup) .setProperties(properties) .setRetryPolicy(retryPolicy) - .setParameters(setClientTlsConf(rpcType, tlsConfig)) .build(); } + /** * Execute a given function with input parameter from the members of a list. * @@ -228,32 +210,4 @@ public static InetSocketAddress parseInetSocketAddress(String address) { } } - public static Parameters setClientTlsConf(RpcType rpcType, - GrpcTlsConfig tlsConfig) { - // TODO: GRPC TLS only for now, netty/hadoop RPC TLS support later. - if (tlsConfig != null && rpcType == SupportedRpcType.GRPC) { - Parameters parameters = new Parameters(); - setAdminTlsConf(parameters, tlsConfig); - setClientTlsConf(parameters, tlsConfig); - return parameters; - } - return null; - } - - private static void setAdminTlsConf(Parameters parameters, - GrpcTlsConfig tlsConfig) { - if (tlsConfig != null) { - GrpcConfigKeys.Admin.setTlsConf(parameters, tlsConfig); - } - } - - private static void setClientTlsConf(Parameters parameters, - GrpcTlsConfig tlsConfig) { - if (tlsConfig != null) { - GrpcConfigKeys.Client.setTlsConf(parameters, tlsConfig); - NettyConfigKeys.DataStream.Client.setTlsConf(parameters, tlsConfig); - } - } - - } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java index fce7f53a83..13b3e4a1fa 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java @@ -99,7 +99,7 @@ public int run(CommandLine cl) throws IOException { raftGroup = RaftGroup.valueOf(raftGroupIdFromConfig, peers); PrintStream printStream = getPrintStream(); try (final RaftClient client = RaftUtils.createClient(raftGroup)) { - RaftGroupId remoteGroupId = retrieveRemoteGroupId(raftGroupIdFromConfig, peers, client, printStream); + final RaftGroupId remoteGroupId = retrieveRemoteGroupId(raftGroupIdFromConfig, peers, client, printStream); groupInfoReply = retrieveGroupInfoByGroupId(remoteGroupId, peers, client, printStream); raftGroup = groupInfoReply.getGroup(); } @@ -181,5 +181,4 @@ protected Stream getPeerStream(RaftPeerRole role) { .stream() .filter(targets::contains); } - } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupListCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupListCommand.java index 85f1755028..5bbd1939ad 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupListCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/group/GroupListCommand.java @@ -72,7 +72,7 @@ public int run(CommandLine cl) throws IOException { try(final RaftClient raftClient = RaftUtils.createClient(getRaftGroup())) { GroupListReply reply = raftClient.getGroupManagementApi(peerId).list(); processReply(reply, () -> String.format("Failed to get group information of peerId %s (server %s)", - peerId.toString(), address)); + peerId, address)); printf(String.format("The peerId %s (server %s) is in %d groups, and the groupIds is: %s", peerId, address, reply.getGroupIds().size(), reply.getGroupIds())); } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java index 8b11f55d0a..10bac34975 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/snapshot/TakeSnapshotCommand.java @@ -65,8 +65,7 @@ public int run(CommandLine cl) throws IOException { peerId = null; } RaftClientReply reply = raftClient.getSnapshotManagementApi(peerId).create(timeout); - processReply(reply, () -> String.format("Failed to take snapshot of peerId %s", - peerId != null ? peerId.toString() : null)); + processReply(reply, () -> String.format("Failed to take snapshot of peerId %s", peerId)); printf(String.format("Successful take snapshot on peerId %s, the latest snapshot index is %d", peerId, reply.getLogIndex())); } From b943e2a8c7b8cb21707423de853f4d2db66b21f0 Mon Sep 17 00:00:00 2001 From: DaveTeng0 Date: Tue, 11 Jun 2024 12:46:20 -0700 Subject: [PATCH 8/9] Improve code readability and maintainability --- .../org/apache/ratis/shell/cli/RaftUtils.java | 71 +++++++++---------- .../cli/sh/command/AbstractRatisCommand.java | 3 +- 2 files changed, 35 insertions(+), 39 deletions(-) diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java index 090ed289d2..0c75a76913 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java @@ -41,6 +41,7 @@ import java.util.List; import java.util.Optional; import java.util.Properties; +import java.util.function.Supplier; import java.util.stream.Collectors; import java.util.UUID; @@ -104,21 +105,21 @@ public static RaftClient createClient(RaftGroup raftGroup) { .build(); } - /** - * Execute a given function with input parameter from the members of a list. + * Apply the given function to the given parameter a list. * - * @param list the input parameters - * @param function the function to be executed - * @param parameter type - * @param return value type - * @param the exception type thrown by the given function. - * @return the value returned by the given function. + * @param list the input parameter list + * @param function the function to be applied + * @param parameter type + * @param return value type + * @param the exception type thrown by the given function. + * @return the first non-null value returned by the given function applied to the given list. */ - public static K runFunction(Collection list, CheckedFunction function) { - for (T t : list) { + private static RETURN applyFunctionReturnFirstNonNull( + Collection list, CheckedFunction function) { + for (PARAMETER parameter : list) { try { - K ret = function.apply(t); + RETURN ret = function.apply(parameter); if (ret != null) { return ret; } @@ -129,7 +130,6 @@ public static K runFunction(Collection list, Chec return null; } - public static List buildRaftPeersFromStr(String peers) { List addresses = new ArrayList<>(); String[] peersArray = peers.split(","); @@ -146,54 +146,51 @@ public static List buildRaftPeersFromStr(String peers) { } public static RaftGroupId buildRaftGroupIdFromStr(String groupId) { - return (groupId != null && !groupId.equals("")) ? RaftGroupId.valueOf(UUID.fromString(groupId)) + return groupId.isEmpty() ? RaftGroupId.valueOf(UUID.fromString(groupId)) : DEFAULT_RAFT_GROUP_ID; } public static RaftGroupId retrieveRemoteGroupId(RaftGroupId raftGroupIdFromConfig, List peers, RaftClient client, PrintStream printStream) throws IOException { - RaftGroupId remoteGroupId; - if (raftGroupIdFromConfig != DEFAULT_RAFT_GROUP_ID) { + if (!DEFAULT_RAFT_GROUP_ID .equals(raftGroupIdFromConfig)) { return raftGroupIdFromConfig; - } else { - final List groupIds = runFunction(peers, - p -> client.getGroupManagementApi((p.getId())).list().getGroupIds()); - - if (groupIds == null) { - printStream.println("Failed to get group ID from " + peers); - throw new IOException("Failed to get group ID from " + peers); - } else if (groupIds.size() == 1) { - remoteGroupId = groupIds.get(0); - } else { - printStream.println("There are more than one groups, you should specific one. " + groupIds); - throw new IOException("There are more than one groups, you should specific one. " + groupIds); - } } + final RaftGroupId remoteGroupId; + final List groupIds = applyFunctionReturnFirstNonNull(peers, + p -> client.getGroupManagementApi((p.getId())).list().getGroupIds()); + + if (groupIds == null) { + printStream.println("Failed to get group ID from " + peers); + throw new IOException("Failed to get group ID from " + peers); + } else if (groupIds.size() == 1) { + remoteGroupId = groupIds.get(0); + } else { + String message = "Unexpected multiple group IDs " + groupIds + + ". In such case, the target group ID must be specified."; + printStream.println(message); + throw new IOException(message); + } return remoteGroupId; } public static GroupInfoReply retrieveGroupInfoByGroupId(RaftGroupId remoteGroupId, List peers, RaftClient client, PrintStream printStream) throws IOException { - GroupInfoReply groupInfoReply = runFunction(peers, + GroupInfoReply groupInfoReply = applyFunctionReturnFirstNonNull(peers, p -> client.getGroupManagementApi((p.getId())).info(remoteGroupId)); - processReply(groupInfoReply, - printStream::println, "Failed to get group info for group id " + remoteGroupId.getUuid() + " from " + peers); + processReply(groupInfoReply, printStream::println, + () -> "Failed to get group info for group id " + remoteGroupId.getUuid() + " from " + peers); return groupInfoReply; } - public static void processReply(RaftClientReply reply, Consumer printer, String message) throws IOException { - processReplyInternal(reply, () -> printer.accept(message)); - } - - private static void processReplyInternal(RaftClientReply reply, Runnable printer) throws IOException { + public static void processReply(RaftClientReply reply, Consumer printer, Supplier message) throws IOException { if (reply == null || !reply.isSuccess()) { final RaftException e = Optional.ofNullable(reply) .map(RaftClientReply::getException) .orElseGet(() -> new RaftException("Reply: " + reply)); - printer.run(); + printer.accept(message.get()); throw new IOException(e.getMessage(), e); } } diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java index 13b3e4a1fa..9d132e9c4b 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java @@ -148,8 +148,7 @@ protected RaftPeerProto getLeader(RoleInfoProto roleInfo) { } protected void processReply(RaftClientReply reply, Supplier messageSupplier) throws IOException { - RaftUtils.processReply(reply, - getPrintStream()::println, messageSupplier.get()); + RaftUtils.processReply(reply, getPrintStream()::println, messageSupplier); } protected List getIds(String[] optionValues, BiConsumer consumer) { From 91a9d4c2ddf020d5dfc769eaf9bba75bf6a3e556 Mon Sep 17 00:00:00 2001 From: DaveTeng0 Date: Thu, 13 Jun 2024 10:58:57 -0700 Subject: [PATCH 9/9] removed unused method AbstractRatisCommand.run, fix checkstyle. --- .../org/apache/ratis/shell/cli/RaftUtils.java | 5 ++-- .../cli/sh/command/AbstractRatisCommand.java | 27 ------------------- 2 files changed, 3 insertions(+), 29 deletions(-) diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java index 0c75a76913..9c5d90e4bf 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/RaftUtils.java @@ -146,7 +146,7 @@ public static List buildRaftPeersFromStr(String peers) { } public static RaftGroupId buildRaftGroupIdFromStr(String groupId) { - return groupId.isEmpty() ? RaftGroupId.valueOf(UUID.fromString(groupId)) + return groupId != null && groupId.isEmpty() ? RaftGroupId.valueOf(UUID.fromString(groupId)) : DEFAULT_RAFT_GROUP_ID; } @@ -185,7 +185,8 @@ public static GroupInfoReply retrieveGroupInfoByGroupId(RaftGroupId remoteGroupI return groupInfoReply; } - public static void processReply(RaftClientReply reply, Consumer printer, Supplier message) throws IOException { + public static void processReply(RaftClientReply reply, Consumer printer, Supplier message) + throws IOException { if (reply == null || !reply.isSuccess()) { final RaftException e = Optional.ofNullable(reply) .map(RaftClientReply::getException) diff --git a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java index 9d132e9c4b..91bdc873b7 100644 --- a/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java +++ b/ratis-shell/src/main/java/org/apache/ratis/shell/cli/sh/command/AbstractRatisCommand.java @@ -34,13 +34,11 @@ import org.apache.ratis.proto.RaftProtos.RaftPeerRole; import org.apache.ratis.proto.RaftProtos.RoleInfoProto; import org.apache.ratis.util.ProtoUtils; -import org.apache.ratis.util.function.CheckedFunction; import java.io.IOException; import java.io.PrintStream; import java.net.InetSocketAddress; import java.util.ArrayList; -import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Set; @@ -60,31 +58,6 @@ public abstract class AbstractRatisCommand extends AbstractCommand { public static final String PEER_OPTION_NAME = "peers"; public static final String GROUPID_OPTION_NAME = "groupid"; - - /** - * Execute a given function with input parameter from the members of a list. - * - * @param list the input parameters - * @param function the function to be executed - * @param parameter type - * @param return value type - * @param the exception type thrown by the given function. - * @return the value returned by the given function. - */ - public static K run(Collection list, CheckedFunction function) { - for (T t : list) { - try { - K ret = function.apply(t); - if (ret != null) { - return ret; - } - } catch (Throwable e) { - e.printStackTrace(); - } - } - return null; - } - private RaftGroup raftGroup; private GroupInfoReply groupInfoReply;