This is an automated email from the ASF dual-hosted git repository.
sk0x50 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/ignite-3.git
The following commit(s) were added to refs/heads/main by this push:
new e06ef7eaca IGNITE-18012 Added connect command to start CLI in REPL
mode. Fixes #1283
e06ef7eaca is described below
commit e06ef7eaca1453a8e189efdd1c5c20bf25d6ff51
Author: Vadim Pakhnushev <[email protected]>
AuthorDate: Wed Nov 16 22:00:24 2022 +0200
IGNITE-18012 Added connect command to start CLI in REPL mode. Fixes #1283
Signed-off-by: Slava Koptilin <[email protected]>
---
.../java/org/apache/ignite/internal/cli/Main.java | 51 ++++------------
.../apache/ignite/internal/cli/ReplManager.java | 70 ++++++++++++++++++++++
.../internal/cli/commands/TopLevelCliCommand.java | 2 +
.../cli/commands/TopLevelCliReplCommand.java | 4 +-
.../cli/commands/connect/ConnectCommand.java | 9 ++-
...ConnectCommand.java => ConnectReplCommand.java} | 4 +-
.../questions/ConnectToClusterQuestion.java | 3 +
.../cli/commands/UrlOptionsNegativeTest.java | 6 +-
8 files changed, 101 insertions(+), 48 deletions(-)
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/Main.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/Main.java
index 0e0d42b7c0..60e361da8e 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/Main.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/Main.java
@@ -27,22 +27,13 @@ import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
-import java.util.HashMap;
import java.util.logging.LogManager;
import java.util.stream.Collectors;
import org.apache.ignite.internal.cli.commands.TopLevelCliCommand;
-import org.apache.ignite.internal.cli.commands.TopLevelCliReplCommand;
-import
org.apache.ignite.internal.cli.commands.questions.ConnectToClusterQuestion;
import org.apache.ignite.internal.cli.config.ConfigDefaultValueProvider;
import org.apache.ignite.internal.cli.config.StateFolderProvider;
-import org.apache.ignite.internal.cli.core.call.CallExecutionPipeline;
-import org.apache.ignite.internal.cli.core.call.StringCallInput;
-import
org.apache.ignite.internal.cli.core.exception.handler.DefaultExceptionHandlers;
import
org.apache.ignite.internal.cli.core.exception.handler.PicocliExecutionExceptionHandler;
-import org.apache.ignite.internal.cli.core.repl.Repl;
-import org.apache.ignite.internal.cli.core.repl.SessionDefaultValueProvider;
import org.apache.ignite.internal.cli.core.repl.executor.ReplExecutorProvider;
-import org.apache.ignite.internal.cli.core.repl.prompt.PromptProvider;
import org.fusesource.jansi.AnsiConsole;
import picocli.CommandLine;
import picocli.CommandLine.Help.Ansi;
@@ -64,6 +55,7 @@ public class Main {
ApplicationContextBuilder builder =
ApplicationContext.builder(Environment.CLI).deduceEnvironment(false);
try (MicronautFactory micronautFactory = new
MicronautFactory(builder.start())) {
AnsiConsole.systemInstall();
+ initReplExecutor(micronautFactory);
if (args.length != 0 || !isatty()) { // do not enter REPL if input
or output is redirected
try {
exitCode = executeCommand(args, micronautFactory);
@@ -71,12 +63,10 @@ public class Main {
System.err.println("Error occurred during command
execution");
}
} else {
- try {
- enterRepl(micronautFactory);
- } catch (Exception e) {
- System.err.println("Error occurred during REPL
initialization");
- }
+ enterRepl(micronautFactory);
}
+ } catch (Exception e) {
+ System.err.println("Error occurred during initialization");
} finally {
AnsiConsole.systemUninstall();
}
@@ -87,37 +77,18 @@ public class Main {
return System.console() != null;
}
- private static void enterRepl(MicronautFactory micronautFactory) throws
Exception {
+ /** Needed for immediate REPL mode and for running a command which will
stay in REPL mode so we need to init it once. */
+ private static void initReplExecutor(MicronautFactory micronautFactory)
throws Exception {
ReplExecutorProvider replExecutorProvider =
micronautFactory.create(ReplExecutorProvider.class);
replExecutorProvider.injectFactory(micronautFactory);
- HashMap<String, String> aliases = new HashMap<>();
- aliases.put("zle", "widget");
- aliases.put("bindkey", "keymap");
-
- SessionDefaultValueProvider defaultValueProvider =
micronautFactory.create(SessionDefaultValueProvider.class);
+ }
+ private static void enterRepl(MicronautFactory micronautFactory) throws
Exception {
VersionProvider versionProvider =
micronautFactory.create(VersionProvider.class);
System.out.println(banner(versionProvider));
- ConnectToClusterQuestion question =
micronautFactory.create(ConnectToClusterQuestion.class);
-
- replExecutorProvider.get().execute(Repl.builder()
-
.withPromptProvider(micronautFactory.create(PromptProvider.class))
- .withAliases(aliases)
- .withCommandClass(TopLevelCliReplCommand.class)
- .withDefaultValueProvider(defaultValueProvider)
- .withCallExecutionPipelineProvider((executor,
exceptionHandlers, line) ->
- CallExecutionPipeline.builder(executor)
- .inputProvider(() -> new StringCallInput(line))
- .output(System.out)
- .errOutput(System.err)
- .exceptionHandlers(new
DefaultExceptionHandlers())
- .exceptionHandlers(exceptionHandlers)
- .build())
- .withOnStart(question::askQuestionOnReplStart)
- .withHistoryFileName("history")
- .withTailTipWidgets()
- .build());
+ ReplManager replManager = micronautFactory.create(ReplManager.class);
+ replManager.startReplMode();
}
private static int executeCommand(String[] args, MicronautFactory
micronautFactory) throws Exception {
@@ -127,7 +98,7 @@ public class Main {
return cmd.execute(args);
}
- private static final String[] BANNER = new String[]{
+ private static final String[] BANNER = {
"",
" @|red,bold #|@ ___
__",
" @|red,bold ###|@ / | ____ ____ _ _____
/ /_ ___",
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/ReplManager.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/ReplManager.java
new file mode 100644
index 0000000000..c7adf3984f
--- /dev/null
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/ReplManager.java
@@ -0,0 +1,70 @@
+/*
+ * 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.ignite.internal.cli;
+
+import jakarta.inject.Inject;
+import jakarta.inject.Singleton;
+import org.apache.ignite.internal.cli.commands.TopLevelCliReplCommand;
+import
org.apache.ignite.internal.cli.commands.questions.ConnectToClusterQuestion;
+import org.apache.ignite.internal.cli.core.call.CallExecutionPipeline;
+import org.apache.ignite.internal.cli.core.call.StringCallInput;
+import
org.apache.ignite.internal.cli.core.exception.handler.DefaultExceptionHandlers;
+import org.apache.ignite.internal.cli.core.repl.Repl;
+import org.apache.ignite.internal.cli.core.repl.SessionDefaultValueProvider;
+import org.apache.ignite.internal.cli.core.repl.executor.ReplExecutorProvider;
+import org.apache.ignite.internal.cli.core.repl.prompt.PromptProvider;
+
+/**
+ * Class which runs main REPL mode, it's used both when starting directly into
the REPL mode and from the `connect` command.
+ */
+@Singleton
+public class ReplManager {
+ @Inject
+ private ReplExecutorProvider replExecutorProvider;
+
+ @Inject
+ private PromptProvider promptProvider;
+
+ @Inject
+ private SessionDefaultValueProvider defaultValueProvider;
+
+ @Inject
+ private ConnectToClusterQuestion question;
+
+ /**
+ * Enters REPL mode.
+ */
+ public void startReplMode() {
+ replExecutorProvider.get().execute(Repl.builder()
+ .withPromptProvider(promptProvider)
+ .withCommandClass(TopLevelCliReplCommand.class)
+ .withDefaultValueProvider(defaultValueProvider)
+ .withCallExecutionPipelineProvider((executor,
exceptionHandlers, line) ->
+ CallExecutionPipeline.builder(executor)
+ .inputProvider(() -> new StringCallInput(line))
+ .output(System.out)
+ .errOutput(System.err)
+ .exceptionHandlers(new
DefaultExceptionHandlers())
+ .exceptionHandlers(exceptionHandlers)
+ .build())
+ .withOnStart(question::askQuestionOnReplStart)
+ .withHistoryFileName("history")
+ .withTailTipWidgets()
+ .build());
+ }
+}
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/TopLevelCliCommand.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/TopLevelCliCommand.java
index 3c9c0ed9da..444722a1c5 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/TopLevelCliCommand.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/TopLevelCliCommand.java
@@ -20,6 +20,7 @@ package org.apache.ignite.internal.cli.commands;
import org.apache.ignite.internal.cli.VersionProvider;
import org.apache.ignite.internal.cli.commands.cliconfig.CliCommand;
import org.apache.ignite.internal.cli.commands.cluster.ClusterCommand;
+import org.apache.ignite.internal.cli.commands.connect.ConnectCommand;
import org.apache.ignite.internal.cli.commands.node.NodeCommand;
import org.apache.ignite.internal.cli.commands.sql.SqlCommand;
import picocli.CommandLine;
@@ -39,6 +40,7 @@ import picocli.CommandLine.Option;
SqlCommand.class,
CommandLine.HelpCommand.class,
CliCommand.class,
+ ConnectCommand.class,
NodeCommand.class,
ClusterCommand.class
})
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/TopLevelCliReplCommand.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/TopLevelCliReplCommand.java
index 58b4b24ca3..0f801a1c49 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/TopLevelCliReplCommand.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/TopLevelCliReplCommand.java
@@ -19,7 +19,7 @@ package org.apache.ignite.internal.cli.commands;
import org.apache.ignite.internal.cli.commands.cliconfig.CliReplCommand;
import org.apache.ignite.internal.cli.commands.cluster.ClusterReplCommand;
-import org.apache.ignite.internal.cli.commands.connect.ConnectCommand;
+import org.apache.ignite.internal.cli.commands.connect.ConnectReplCommand;
import org.apache.ignite.internal.cli.commands.connect.DisconnectCommand;
import org.apache.ignite.internal.cli.commands.node.NodeReplCommand;
import org.apache.ignite.internal.cli.commands.sql.SqlReplCommand;
@@ -38,7 +38,7 @@ import picocli.shell.jline3.PicocliCommands;
CommandLine.HelpCommand.class,
VersionCommand.class,
CliReplCommand.class,
- ConnectCommand.class,
+ ConnectReplCommand.class,
DisconnectCommand.class,
NodeReplCommand.class,
ClusterReplCommand.class
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/connect/ConnectCommand.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/connect/ConnectCommand.java
index 4cac80d24c..9457086550 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/connect/ConnectCommand.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/connect/ConnectCommand.java
@@ -21,6 +21,7 @@ import static
org.apache.ignite.internal.cli.commands.OptionsConstants.CLUSTER_U
import static
org.apache.ignite.internal.cli.commands.OptionsConstants.NODE_URL_OR_NAME_DESC;
import jakarta.inject.Inject;
+import org.apache.ignite.internal.cli.ReplManager;
import org.apache.ignite.internal.cli.call.connect.ConnectCall;
import org.apache.ignite.internal.cli.call.connect.ConnectCallInput;
import org.apache.ignite.internal.cli.commands.BaseCommand;
@@ -42,15 +43,21 @@ public class ConnectCommand extends BaseCommand implements
Runnable {
@Inject
private ConnectCall connectCall;
+ @Inject
+ private ReplManager replManager;
+
/** {@inheritDoc} */
@Override
public void run() {
- CallExecutionPipeline.builder(connectCall)
+ int exitCode = CallExecutionPipeline.builder(connectCall)
.inputProvider(() -> new
ConnectCallInput(nodeNameOrUrl.stringUrl()))
.output(spec.commandLine().getOut())
.errOutput(spec.commandLine().getErr())
.verbose(verbose)
.build()
.runPipeline();
+ if (exitCode == 0) {
+ replManager.startReplMode();
+ }
}
}
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/connect/ConnectCommand.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/connect/ConnectReplCommand.java
similarity index 94%
copy from
modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/connect/ConnectCommand.java
copy to
modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/connect/ConnectReplCommand.java
index 4cac80d24c..6f73ea78b5 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/connect/ConnectCommand.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/connect/ConnectReplCommand.java
@@ -30,10 +30,10 @@ import picocli.CommandLine.Command;
import picocli.CommandLine.Parameters;
/**
- * Connects to the Ignite 3 node.
+ * Connects to the Ignite 3 node in REPL mode.
*/
@Command(name = "connect", description = "Connects to Ignite 3 node")
-public class ConnectCommand extends BaseCommand implements Runnable {
+public class ConnectReplCommand extends BaseCommand implements Runnable {
/** Node URL option. */
@Parameters(description = NODE_URL_OR_NAME_DESC, descriptionKey =
CLUSTER_URL_KEY)
diff --git
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/questions/ConnectToClusterQuestion.java
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/questions/ConnectToClusterQuestion.java
index d02a303bfb..b5743fa014 100644
---
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/questions/ConnectToClusterQuestion.java
+++
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/questions/ConnectToClusterQuestion.java
@@ -86,6 +86,9 @@ public class ConnectToClusterQuestion {
* Ask for connect to the cluster and suggest to save the last connected
URL as default.
*/
public void askQuestionOnReplStart() {
+ if (session.isConnectedToNode()) {
+ return;
+ }
String defaultUrl =
configManagerProvider.get().getCurrentProperty(ConfigConstants.CLUSTER_URL);
String lastConnectedUrl =
stateConfigProvider.get().getProperty(ConfigConstants.LAST_CONNECTED_URL);
QuestionUiComponent question;
diff --git
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/UrlOptionsNegativeTest.java
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/UrlOptionsNegativeTest.java
index 00511f4950..3bf8b67591 100644
---
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/UrlOptionsNegativeTest.java
+++
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/UrlOptionsNegativeTest.java
@@ -44,7 +44,7 @@ import
org.apache.ignite.internal.cli.commands.cluster.topology.LogicalTopologyC
import
org.apache.ignite.internal.cli.commands.cluster.topology.LogicalTopologyReplCommand;
import
org.apache.ignite.internal.cli.commands.cluster.topology.PhysicalTopologyCommand;
import
org.apache.ignite.internal.cli.commands.cluster.topology.PhysicalTopologyReplCommand;
-import org.apache.ignite.internal.cli.commands.connect.ConnectCommand;
+import org.apache.ignite.internal.cli.commands.connect.ConnectReplCommand;
import org.apache.ignite.internal.cli.commands.node.NodeNameOrUrl;
import
org.apache.ignite.internal.cli.commands.node.config.NodeConfigShowCommand;
import
org.apache.ignite.internal.cli.commands.node.config.NodeConfigShowReplCommand;
@@ -148,7 +148,7 @@ public class UrlOptionsNegativeTest {
arguments(LogicalTopologyReplCommand.class,
CLUSTER_URL_OPTION, List.of()),
arguments(PhysicalTopologyReplCommand.class,
CLUSTER_URL_OPTION, List.of()),
arguments(ClusterInitReplCommand.class, CLUSTER_URL_OPTION,
List.of("--cluster-name=cluster", "--meta-storage-node=test")),
- arguments(ConnectCommand.class, "", List.of())
+ arguments(ConnectReplCommand.class, "", List.of())
// TODO https://issues.apache.org/jira/browse/IGNITE-17102
// Arguments.arguments(ClusterShowReplCommand.class,
CLUSTER_URL_OPTION, List.of()),
);
@@ -268,7 +268,7 @@ public class UrlOptionsNegativeTest {
@Test
void testConnectCommandWithoutParametersWithEmptyConfig() {
configManagerProvider.configManager = new
IniConfigManager(TestConfigManagerHelper.createEmptyConfig());
- setUp(ConnectCommand.class);
+ setUp(ConnectReplCommand.class);
cmd.execute();
assertAll(