You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ignite.apache.org by ib...@apache.org on 2022/12/30 11:01:53 UTC

[ignite-3] branch main updated: IGNITE-18222: Implement the rest of dynamic completors (#1472)

This is an automated email from the ASF dual-hosted git repository.

ibessonov 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 93cdd4c36d IGNITE-18222: Implement the rest of dynamic completors (#1472)
93cdd4c36d is described below

commit 93cdd4c36d68ff7dfccf4468531a6a7431243d0a
Author: Ivan Gagarkin <ga...@gmail.com>
AuthorDate: Fri Dec 30 15:01:47 2022 +0400

    IGNITE-18222: Implement the rest of dynamic completors (#1472)
---
 ...liCommandTestNotInitializedIntegrationBase.java |   2 +-
 .../{NodeNameTest.java => ItNodeNameTest.java}     |  36 +++++--
 .../commands/questions/ItConnectToClusterTest.java |   4 +
 .../internal/cli/call/connect/ConnectCall.java     |  26 ++---
 .../internal/cli/call/connect/DisconnectCall.java  |  17 ++--
 .../internal/cli/commands/node/NodeUrlMixin.java   |   4 +-
 .../questions/ConnectToClusterQuestion.java        |  21 ++--
 .../apache/ignite/internal/cli/core/JdbcUrl.java   |  61 +++++++++++
 .../core/converters/NodeNameOrUrlConverter.java    |   4 +-
 .../ConnectionException.java}                      |  24 ++---
 ...Factory.java => AsyncSessionEventListener.java} |  25 ++---
 .../ignite/internal/cli/core/repl/Session.java     |  70 +++++++------
 .../cli/core/repl/SessionDefaultValueProvider.java |   5 +-
 .../core/repl/{Session.java => SessionInfo.java}   |  45 +++------
 .../completer/DynamicCompleterActivationPoint.java |  35 ++++++-
 .../cli/core/repl/completer/NodeUrlProvider.java   |  65 ------------
 .../{node => }/StringDynamicCompleter.java         |   4 +-
 .../ClusterUrlDynamicCompleterFactory.java}        |  20 ++--
 .../completer/filter/DynamicCompleterFilter.java   |   2 +-
 .../ClusterConfigDynamicCompleterFactory.java      |  41 ++------
 .../hocon/NodeConfigDynamicCompleterFactory.java   |  40 ++------
 .../JdbcUrlDynamicCompleterFactory.java}           |  17 ++--
 .../node/NodeNameDynamicCompleterFactory.java      |   5 +-
 .../repl/completer/path/FilePathCompleter.java     |  75 ++++++++++++++
 .../cli/core/repl/executor/ReplExecutor.java       |   2 +-
 .../core/repl/executor/ReplExecutorProvider.java   |   2 +-
 .../cli/core/repl/prompt/ReplPromptProvider.java   |   6 +-
 .../ClusterConfigRegistry.java}                    |  24 ++---
 .../JdbcUrlRegistry.java}                          |  24 ++---
 .../NodeConfigRegistry.java}                       |  24 ++---
 .../NodeNameRegistry.java}                         |  29 +++---
 .../registry/impl/ClusterConfigRegistryImpl.java   |  68 +++++++++++++
 .../repl/registry/impl/JdbcUrlRegistryImpl.java    | 111 +++++++++++++++++++++
 .../repl/registry/impl/NodeConfigRegistryImpl.java |  69 +++++++++++++
 .../repl/registry/impl/NodeNameRegistryImpl.java}  |  88 +++++++++-------
 .../internal/cli/commands/CliCommandTestBase.java  |   2 +-
 .../cli/commands/UrlOptionsNegativeTest.java       |   2 +-
 .../repl/completer/StringDynamicCompleterTest.java |   1 -
 .../filter/DynamicCompleterFilterTest.java         |  10 +-
 39 files changed, 693 insertions(+), 417 deletions(-)

diff --git a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/CliCommandTestNotInitializedIntegrationBase.java b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/CliCommandTestNotInitializedIntegrationBase.java
index c185b3866e..85fce2958b 100644
--- a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/CliCommandTestNotInitializedIntegrationBase.java
+++ b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/CliCommandTestNotInitializedIntegrationBase.java
@@ -25,7 +25,6 @@ import jakarta.inject.Inject;
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import org.apache.ignite.internal.cli.IntegrationTestBase;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
 import org.apache.ignite.internal.cli.commands.cliconfig.TestConfigManagerHelper;
 import org.apache.ignite.internal.cli.commands.cliconfig.TestConfigManagerProvider;
 import org.apache.ignite.internal.cli.commands.node.NodeNameOrUrl;
@@ -33,6 +32,7 @@ import org.apache.ignite.internal.cli.config.ConfigDefaultValueProvider;
 import org.apache.ignite.internal.cli.config.ini.IniConfigManager;
 import org.apache.ignite.internal.cli.core.converters.NodeNameOrUrlConverter;
 import org.apache.ignite.internal.cli.core.repl.context.CommandLineContextProvider;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeNameRegistry;
 import org.junit.jupiter.api.AfterAll;
 import org.junit.jupiter.api.BeforeAll;
 import org.junit.jupiter.api.BeforeEach;
diff --git a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/NodeNameTest.java b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/ItNodeNameTest.java
similarity index 73%
rename from modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/NodeNameTest.java
rename to modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/ItNodeNameTest.java
index 659fc42d21..39cf32b0bf 100644
--- a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/NodeNameTest.java
+++ b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/ItNodeNameTest.java
@@ -21,32 +21,38 @@ import static org.apache.ignite.internal.testframework.IgniteTestUtils.waitForCo
 import static org.junit.jupiter.api.Assertions.assertAll;
 import static org.junit.jupiter.api.Assertions.assertTrue;
 
+import jakarta.inject.Inject;
 import java.time.Duration;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeNameRegistry;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
 
 /** Tests for ignite node commands with a provided node name. */
-public class NodeNameTest extends CliCommandTestNotInitializedIntegrationBase {
+public class ItNodeNameTest extends CliCommandTestInitializedIntegrationBase {
 
-    private String nodeName;
+    @Inject
+    private NodeNameRegistry nodeNameRegistry;
+
+    @Override
+    protected Class<?> getCommandClass() {
+        return TopLevelCliReplCommand.class;
+    }
 
     @BeforeEach
     void setUp() throws InterruptedException {
-        nodeNameRegistry.startPullingUpdates("http://localhost:10301");
+        execute("connect");
+        resetOutput();
         // wait to pulling node names
-        assertTrue(waitForCondition(() -> !nodeNameRegistry.getAllNames().isEmpty(), Duration.ofSeconds(5).toMillis()));
-        this.nodeName = nodeNameRegistry.getAllNames().stream()
-                .findFirst()
-                .orElseThrow(() -> new RuntimeException("nodeNameRegistry doesn't contain any nodes"));
+        assertTrue(waitForCondition(() -> !nodeNameRegistry.names().isEmpty(), Duration.ofSeconds(5).toMillis()));
     }
 
     @Test
     @DisplayName("Should display node version with provided node name")
     void nodeVersion() {
         // When
-        execute("node", "version", "--node-name", nodeName);
+        execute("node", "version", "--node-name", nodeName());
 
         // Then
         assertAll(
@@ -60,7 +66,7 @@ public class NodeNameTest extends CliCommandTestNotInitializedIntegrationBase {
     @DisplayName("Should display node config with provided node name")
     void nodeConfig() {
         // When
-        execute("node", "config", "show", "--node-name", nodeName);
+        execute("node", "config", "show", "--node-name", nodeName());
 
         // Then
         assertAll(
@@ -74,18 +80,26 @@ public class NodeNameTest extends CliCommandTestNotInitializedIntegrationBase {
     @DisplayName("Should display node status with provided node name")
     void nodeStatus() {
         // When
+        String nodeName = nodeName();
         execute("node", "status", "--node-name", nodeName);
 
         // Then
         assertAll(
                 this::assertExitCodeIsZero,
                 this::assertErrOutputIsEmpty,
-                () -> assertOutputMatches("\\[name: " + nodeName + ", state: starting\\]?\\s+")
+                () -> assertOutputMatches("\\[name: " + nodeName + ", state: started\\]?\\s+")
         );
     }
 
     @AfterEach
     void tearDown() {
-        nodeNameRegistry.stopPullingUpdates();
+        execute("disconnect");
+    }
+
+    private String nodeName() {
+        return nodeNameRegistry.names()
+                .stream()
+                .findAny()
+                .orElseThrow(() -> new IllegalStateException("nodeNameRegistry doesn't have any node names"));
     }
 }
diff --git a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/questions/ItConnectToClusterTest.java b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/questions/ItConnectToClusterTest.java
index 1adfaae91c..12d27b35c2 100644
--- a/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/questions/ItConnectToClusterTest.java
+++ b/modules/cli/src/integrationTest/java/org/apache/ignite/internal/cli/commands/questions/ItConnectToClusterTest.java
@@ -157,6 +157,10 @@ class ItConnectToClusterTest extends CliCommandTestInitializedIntegrationBase {
         // And answer is "y"
         bindAnswers("y");
 
+        // And disconnect
+        resetOutput();
+        execute("disconnect");
+
         // When connect to different URL
         resetOutput();
         execute("connect", "http://localhost:10301");
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/connect/ConnectCall.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/connect/ConnectCall.java
index 506182f81d..9c0b7dd0a8 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/connect/ConnectCall.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/connect/ConnectCall.java
@@ -20,16 +20,16 @@ package org.apache.ignite.internal.cli.call.connect;
 import com.google.gson.Gson;
 import jakarta.inject.Singleton;
 import java.net.MalformedURLException;
-import java.net.URL;
 import java.util.Objects;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
 import org.apache.ignite.internal.cli.config.ConfigConstants;
 import org.apache.ignite.internal.cli.config.StateConfigProvider;
+import org.apache.ignite.internal.cli.core.JdbcUrl;
 import org.apache.ignite.internal.cli.core.call.Call;
 import org.apache.ignite.internal.cli.core.call.CallOutput;
 import org.apache.ignite.internal.cli.core.call.DefaultCallOutput;
 import org.apache.ignite.internal.cli.core.exception.IgniteCliApiException;
 import org.apache.ignite.internal.cli.core.repl.Session;
+import org.apache.ignite.internal.cli.core.repl.SessionInfo;
 import org.apache.ignite.internal.cli.core.repl.config.RootConfig;
 import org.apache.ignite.internal.cli.core.style.component.MessageUiComponent;
 import org.apache.ignite.internal.cli.core.style.element.UiElements;
@@ -48,36 +48,29 @@ public class ConnectCall implements Call<ConnectCallInput, String> {
 
     private final StateConfigProvider stateConfigProvider;
 
-    private final NodeNameRegistry nodeNameRegistry;
-
     /**
      * Constructor.
      */
-    public ConnectCall(Session session, StateConfigProvider stateConfigProvider, NodeNameRegistry nodeNameRegistry) {
+    public ConnectCall(Session session, StateConfigProvider stateConfigProvider) {
         this.session = session;
         this.stateConfigProvider = stateConfigProvider;
-        this.nodeNameRegistry = nodeNameRegistry;
     }
 
     @Override
     public CallOutput<String> execute(ConnectCallInput input) {
         String nodeUrl = input.getNodeUrl();
-        if (session.isConnectedToNode() && Objects.equals(session.nodeUrl(), nodeUrl)) {
+        SessionInfo sessionInfo = session.info();
+        if (sessionInfo != null && Objects.equals(sessionInfo.nodeUrl(), nodeUrl)) {
             MessageUiComponent message = MessageUiComponent.fromMessage("You are already connected to %s", UiElements.url(nodeUrl));
             return DefaultCallOutput.success(message.render());
         }
         try {
             String configuration = fetchNodeConfiguration(nodeUrl);
-            session.setNodeName(fetchNodeName(nodeUrl));
-            session.setNodeUrl(nodeUrl);
             stateConfigProvider.get().setProperty(ConfigConstants.LAST_CONNECTED_URL, nodeUrl);
-            session.setJdbcUrl(constructJdbcUrl(configuration, nodeUrl));
-            session.setConnectedToNode(true);
-            nodeNameRegistry.startPullingUpdates(nodeUrl);
+            session.connect(new SessionInfo(nodeUrl, fetchNodeName(nodeUrl), constructJdbcUrl(configuration, nodeUrl)));
             return DefaultCallOutput.success(MessageUiComponent.fromMessage("Connected to %s", UiElements.url(nodeUrl)).render());
-
         } catch (ApiException | IllegalArgumentException e) {
-            session.setConnectedToNode(false);
+            session.disconnect();
             return DefaultCallOutput.failure(new IgniteCliApiException(e, nodeUrl));
         }
     }
@@ -92,9 +85,8 @@ public class ConnectCall implements Call<ConnectCallInput, String> {
 
     private String constructJdbcUrl(String configuration, String nodeUrl) {
         try {
-            String host = new URL(nodeUrl).getHost();
-            RootConfig config = new Gson().fromJson(configuration, RootConfig.class);
-            return "jdbc:ignite:thin://" + host + ":" + config.clientConnector.port;
+            int port = new Gson().fromJson(configuration, RootConfig.class).clientConnector.port;
+            return JdbcUrl.of(nodeUrl, port).toString();
         } catch (MalformedURLException ignored) {
             // Shouldn't happen ever since we are now connected to this URL
             return null;
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/connect/DisconnectCall.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/connect/DisconnectCall.java
index 941fdf8cb4..1ce901538d 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/connect/DisconnectCall.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/connect/DisconnectCall.java
@@ -19,12 +19,12 @@ package org.apache.ignite.internal.cli.call.connect;
 
 import jakarta.inject.Inject;
 import jakarta.inject.Singleton;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
 import org.apache.ignite.internal.cli.core.call.Call;
 import org.apache.ignite.internal.cli.core.call.CallOutput;
 import org.apache.ignite.internal.cli.core.call.DefaultCallOutput;
 import org.apache.ignite.internal.cli.core.call.EmptyCallInput;
 import org.apache.ignite.internal.cli.core.repl.Session;
+import org.apache.ignite.internal.cli.core.repl.SessionInfo;
 import org.apache.ignite.internal.cli.core.style.component.MessageUiComponent;
 import org.apache.ignite.internal.cli.core.style.element.UiElements;
 
@@ -35,22 +35,17 @@ import org.apache.ignite.internal.cli.core.style.element.UiElements;
 public class DisconnectCall implements Call<EmptyCallInput, String> {
     @Inject
     private final Session session;
-    @Inject
-    private final NodeNameRegistry nodeNameRegistry;
 
-    public DisconnectCall(Session session, NodeNameRegistry nodeNameRegistry) {
+    public DisconnectCall(Session session) {
         this.session = session;
-        this.nodeNameRegistry = nodeNameRegistry;
     }
 
     @Override
     public CallOutput<String> execute(EmptyCallInput input) {
-        if (session.isConnectedToNode()) {
-            String nodeUrl = session.nodeUrl();
-            session.setNodeUrl(null);
-            session.setNodeName(null);
-            session.setConnectedToNode(false);
-            nodeNameRegistry.stopPullingUpdates();
+        SessionInfo sessionInfo = session.info();
+        if (sessionInfo != null) {
+            String nodeUrl = sessionInfo.nodeUrl();
+            session.disconnect();
             return DefaultCallOutput.success(
                     MessageUiComponent.fromMessage("Disconnected from %s", UiElements.url(nodeUrl)).render()
             );
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/NodeUrlMixin.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/NodeUrlMixin.java
index c60f4544b9..12cd789e78 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/NodeUrlMixin.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/NodeUrlMixin.java
@@ -25,9 +25,9 @@ import static org.apache.ignite.internal.cli.commands.Options.Constants.URL_OPTI
 
 import jakarta.inject.Inject;
 import java.net.URL;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
 import org.apache.ignite.internal.cli.core.converters.UrlConverter;
 import org.apache.ignite.internal.cli.core.exception.IgniteCliException;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeNameRegistry;
 import org.jetbrains.annotations.Nullable;
 import picocli.CommandLine.ArgGroup;
 import picocli.CommandLine.Option;
@@ -71,7 +71,7 @@ public class NodeUrlMixin {
             if (options.nodeUrl != null) {
                 return options.nodeUrl.toString();
             } else {
-                return nodeNameRegistry.getNodeUrl(options.nodeName)
+                return nodeNameRegistry.nodeUrlByName(options.nodeName)
                         .map(URL::toString)
                         .orElseThrow(() -> new IgniteCliException("Node " + options.nodeName
                                 + " not found. Provide a valid name or use a URL"));
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 40304184e1..4f5f4df768 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
@@ -28,8 +28,10 @@ import org.apache.ignite.internal.cli.config.StateConfigProvider;
 import org.apache.ignite.internal.cli.core.flow.builder.FlowBuilder;
 import org.apache.ignite.internal.cli.core.flow.builder.Flows;
 import org.apache.ignite.internal.cli.core.repl.Session;
+import org.apache.ignite.internal.cli.core.repl.SessionInfo;
 import org.apache.ignite.internal.cli.core.style.component.QuestionUiComponent;
 import org.apache.ignite.internal.cli.core.style.element.UiElements;
+import org.jetbrains.annotations.Nullable;
 
 
 /**
@@ -72,11 +74,17 @@ public class ConnectToClusterQuestion {
         return Flows.<Void, ConnectCallInput>acceptQuestion(questionUiComponent, () -> new ConnectCallInput(defaultUrl))
                 .then(Flows.fromCall(connectCall))
                 .print()
-                .map(ignored -> session.nodeUrl());
+                .map(ignored -> sessionNodeUrl());
     }
 
+    @Nullable
     private String clusterUrlOrSessionNode(String clusterUrl) {
-        return clusterUrl != null ? clusterUrl : session.nodeUrl();
+        return clusterUrl != null ? clusterUrl : sessionNodeUrl();
+    }
+
+    @Nullable
+    private String sessionNodeUrl() {
+        return session.info() != null ? session.info().nodeUrl() : null;
     }
 
     /**
@@ -86,10 +94,11 @@ public class ConnectToClusterQuestion {
      * @return {@link FlowBuilder} instance with question in case when cluster url.
      */
     public FlowBuilder<Void, String> askQuestionIfConnected(String clusterUrl) {
-        if (session.isConnectedToNode() && !Objects.equals(session.nodeUrl(), clusterUrl)) {
+        SessionInfo sessionInfo = session.info();
+        if (sessionInfo != null && !Objects.equals(sessionInfo.nodeUrl(), clusterUrl)) {
             QuestionUiComponent question = QuestionUiComponent.fromQuestion(
                     "You are already connected to the %s, do you want to connect to the %s? %s ",
-                    UiElements.url(session.nodeUrl()), UiElements.url(clusterUrl), UiElements.yesNo()
+                    UiElements.url(sessionInfo.nodeUrl()), UiElements.url(clusterUrl), UiElements.yesNo()
             );
             return Flows.acceptQuestion(question, () -> clusterUrl);
         }
@@ -100,7 +109,7 @@ 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()) {
+        if (session.info() != null) {
             return;
         }
         String defaultUrl = configManagerProvider.get().getCurrentProperty(ConfigConstants.CLUSTER_URL);
@@ -126,7 +135,7 @@ public class ConnectToClusterQuestion {
         Flows.acceptQuestion(question, () -> new ConnectCallInput(clusterUrl))
                 .then(Flows.fromCall(connectCall))
                 .print()
-                .ifThen(s -> !Objects.equals(clusterUrl, defaultUrl) && session.isConnectedToNode(),
+                .ifThen(s -> !Objects.equals(clusterUrl, defaultUrl) && session.info() != null,
                         defaultUrlQuestion(clusterUrl).print().build())
                 .start();
     }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/JdbcUrl.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/JdbcUrl.java
new file mode 100644
index 0000000000..87a64d6be5
--- /dev/null
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/JdbcUrl.java
@@ -0,0 +1,61 @@
+/*
+ * 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.core;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Objects;
+
+/** Representation of Ignite JDBC url. */
+public class JdbcUrl {
+    private final String host;
+    private final int port;
+
+    /** Constructor. */
+    private JdbcUrl(String host, int port) {
+        this.host = host;
+        this.port = port;
+    }
+
+    /** Returns {@link JdbcUrl} with provided host and port. */
+    public static JdbcUrl of(String url, int port) throws MalformedURLException {
+        return new JdbcUrl(new URL(url).getHost(), port);
+    }
+
+    @Override
+    public String toString() {
+        return "jdbc:ignite:thin://" + host + ":" + port;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof JdbcUrl)) {
+            return false;
+        }
+        JdbcUrl jdbcUrl = (JdbcUrl) o;
+        return port == jdbcUrl.port && Objects.equals(host, jdbcUrl.host);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(host, port);
+    }
+}
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/converters/NodeNameOrUrlConverter.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/converters/NodeNameOrUrlConverter.java
index dbb25711e6..0da16ff179 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/converters/NodeNameOrUrlConverter.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/converters/NodeNameOrUrlConverter.java
@@ -20,8 +20,8 @@ package org.apache.ignite.internal.cli.core.converters;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.regex.Pattern;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
 import org.apache.ignite.internal.cli.commands.node.NodeNameOrUrl;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeNameRegistry;
 import picocli.CommandLine;
 import picocli.CommandLine.TypeConversionException;
 
@@ -55,7 +55,7 @@ public class NodeNameOrUrlConverter implements CommandLine.ITypeConverter<NodeNa
     }
 
     private URL findNodeUrlByNodeName(String name) {
-        return nodeNameRegistry.getNodeUrl(name)
+        return nodeNameRegistry.nodeUrlByName(name)
                 .orElseThrow(() -> new TypeConversionException("Node " + name + " not found. Provide valid name or use URL"));
     }
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/exception/ConnectionException.java
similarity index 50%
copy from modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
copy to modules/cli/src/main/java/org/apache/ignite/internal/cli/core/exception/ConnectionException.java
index 3d26caa1fc..551836e9cf 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/exception/ConnectionException.java
@@ -15,25 +15,13 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cli.core.repl.completer.node;
+package org.apache.ignite.internal.cli.core.exception;
 
-import jakarta.inject.Singleton;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
-import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleter;
-import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleterFactory;
+/** Connection exception. */
+public class ConnectionException extends IgniteCliException {
 
-/** Factory for --node-name option completer. */
-@Singleton
-public class NodeNameDynamicCompleterFactory implements DynamicCompleterFactory {
-
-    private final NodeNameRegistry nodeNameRegistry;
-
-    public NodeNameDynamicCompleterFactory(NodeNameRegistry nodeNameRegistry) {
-        this.nodeNameRegistry = nodeNameRegistry;
-    }
-
-    @Override
-    public DynamicCompleter getDynamicCompleter(String[] words) {
-        return new StringDynamicCompleter(nodeNameRegistry.getAllNames());
+    /** Constructor. */
+    public ConnectionException(String msg) {
+        super(msg);
     }
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/AsyncSessionEventListener.java
similarity index 50%
copy from modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
copy to modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/AsyncSessionEventListener.java
index 3d26caa1fc..272fbbc3f3 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/AsyncSessionEventListener.java
@@ -15,25 +15,14 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cli.core.repl.completer.node;
+package org.apache.ignite.internal.cli.core.repl;
 
-import jakarta.inject.Singleton;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
-import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleter;
-import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleterFactory;
+/** Session event listener. */
+public interface AsyncSessionEventListener {
 
-/** Factory for --node-name option completer. */
-@Singleton
-public class NodeNameDynamicCompleterFactory implements DynamicCompleterFactory {
+    /** Implementation must be async. */
+    void onConnect(SessionInfo sessionInfo);
 
-    private final NodeNameRegistry nodeNameRegistry;
-
-    public NodeNameDynamicCompleterFactory(NodeNameRegistry nodeNameRegistry) {
-        this.nodeNameRegistry = nodeNameRegistry;
-    }
-
-    @Override
-    public DynamicCompleter getDynamicCompleter(String[] words) {
-        return new StringDynamicCompleter(nodeNameRegistry.getAllNames());
-    }
+    /** Implementation must be async. */
+    void onDisconnect();
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/Session.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/Session.java
index 66b5cfb1c5..242764fe43 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/Session.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/Session.java
@@ -18,51 +18,59 @@
 package org.apache.ignite.internal.cli.core.repl;
 
 import jakarta.inject.Singleton;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+import org.apache.ignite.internal.cli.core.exception.ConnectionException;
+import org.apache.ignite.internal.cli.logger.CliLoggers;
+import org.apache.ignite.internal.logger.IgniteLogger;
 
 /**
- * Connection session that in fact is holder for state: connected or disconnected.
- * Also has a nodeUrl if the state is connected.
+ * Connection session that in fact is holder for state: connected or disconnected. Also has session info if the state is connected.
  */
 @Singleton
 public class Session {
 
-    private boolean connectedToNode;
+    private static final IgniteLogger log = CliLoggers.forClass(Session.class);
 
-    private String nodeUrl;
+    private final AtomicReference<SessionInfo> info = new AtomicReference<>();
 
-    private String nodeName;
+    private final List<? extends AsyncSessionEventListener> listeners;
 
-    private String jdbcUrl;
-
-    public boolean isConnectedToNode() {
-        return connectedToNode;
-    }
-
-    public void setConnectedToNode(boolean connectedToNode) {
-        this.connectedToNode = connectedToNode;
-    }
-
-    public String nodeUrl() {
-        return nodeUrl;
-    }
-
-    public String nodeName() {
-        return nodeName;
-    }
-
-    public void setNodeName(String nodeName) {
-        this.nodeName = nodeName;
+    public Session(List<? extends AsyncSessionEventListener> listeners) {
+        this.listeners = listeners;
     }
 
-    public void setNodeUrl(String nodeUrl) {
-        this.nodeUrl = nodeUrl;
+    /** Creates session info with provided nodeUrl, nodeName, jdbcUrl. */
+    public void connect(SessionInfo newInfo) {
+        if (info.compareAndSet(null, newInfo)) {
+            listeners.forEach(it -> {
+                try {
+                    it.onConnect(newInfo);
+                } catch (Exception e) {
+                    log.warn("Got an exception: ", e);
+                }
+            });
+        } else {
+            throw new ConnectionException("Already connected to " + info.get().nodeUrl());
+        }
     }
 
-    public String jdbcUrl() {
-        return jdbcUrl;
+    /** Clears session info and sets false to connectedToNode. */
+    public void disconnect() {
+        SessionInfo wasConnected = info.getAndSet(null);
+        if (wasConnected != null) {
+            listeners.forEach(it -> {
+                try {
+                    it.onDisconnect();
+                } catch (Exception e) {
+                    log.warn("Got an exception: ", e);
+                }
+            });
+        }
     }
 
-    public void setJdbcUrl(String jdbcUrl) {
-        this.jdbcUrl = jdbcUrl;
+    /** Returns {@link SessionInfo}. */
+    public SessionInfo info() {
+        return info.get();
     }
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/SessionDefaultValueProvider.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/SessionDefaultValueProvider.java
index 9c179db2d3..eee0fd62b4 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/SessionDefaultValueProvider.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/SessionDefaultValueProvider.java
@@ -47,9 +47,10 @@ public class SessionDefaultValueProvider implements IDefaultValueProvider {
 
     @Override
     public String defaultValue(ArgSpec argSpec) throws Exception {
-        if (session.isConnectedToNode()) {
+        SessionInfo sessionInfo = session.info();
+        if (sessionInfo != null) {
             if (Objects.equals(argSpec.descriptionKey(), ConfigConstants.JDBC_URL)) {
-                return session.jdbcUrl();
+                return sessionInfo.jdbcUrl();
             }
         }
         return defaultValueProvider.defaultValue(argSpec);
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/Session.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/SessionInfo.java
similarity index 63%
copy from modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/Session.java
copy to modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/SessionInfo.java
index 66b5cfb1c5..5b0139ec4b 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/Session.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/SessionInfo.java
@@ -17,29 +17,26 @@
 
 package org.apache.ignite.internal.cli.core.repl;
 
-import jakarta.inject.Singleton;
+/** Representation of session details. */
+public class SessionInfo {
+    private final String nodeUrl;
 
-/**
- * Connection session that in fact is holder for state: connected or disconnected.
- * Also has a nodeUrl if the state is connected.
- */
-@Singleton
-public class Session {
-
-    private boolean connectedToNode;
-
-    private String nodeUrl;
-
-    private String nodeName;
+    private final String nodeName;
 
-    private String jdbcUrl;
+    private final String jdbcUrl;
 
-    public boolean isConnectedToNode() {
-        return connectedToNode;
+    /** Default constructor. */
+    public SessionInfo() {
+        this.nodeUrl = null;
+        this.nodeName = null;
+        this.jdbcUrl = null;
     }
 
-    public void setConnectedToNode(boolean connectedToNode) {
-        this.connectedToNode = connectedToNode;
+    /** Constructor. */
+    public SessionInfo(String nodeUrl, String nodeName, String jdbcUrl) {
+        this.nodeUrl = nodeUrl;
+        this.nodeName = nodeName;
+        this.jdbcUrl = jdbcUrl;
     }
 
     public String nodeUrl() {
@@ -50,19 +47,7 @@ public class Session {
         return nodeName;
     }
 
-    public void setNodeName(String nodeName) {
-        this.nodeName = nodeName;
-    }
-
-    public void setNodeUrl(String nodeUrl) {
-        this.nodeUrl = nodeUrl;
-    }
-
     public String jdbcUrl() {
         return jdbcUrl;
     }
-
-    public void setJdbcUrl(String jdbcUrl) {
-        this.jdbcUrl = jdbcUrl;
-    }
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/DynamicCompleterActivationPoint.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/DynamicCompleterActivationPoint.java
index a2d8cdd5e1..515ab94aa9 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/DynamicCompleterActivationPoint.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/DynamicCompleterActivationPoint.java
@@ -19,10 +19,13 @@ package org.apache.ignite.internal.cli.core.repl.completer;
 
 import jakarta.inject.Singleton;
 import org.apache.ignite.internal.cli.commands.Options;
+import org.apache.ignite.internal.cli.core.repl.completer.cluster.ClusterUrlDynamicCompleterFactory;
 import org.apache.ignite.internal.cli.core.repl.completer.filter.ExclusionsCompleterFilter;
 import org.apache.ignite.internal.cli.core.repl.completer.hocon.ClusterConfigDynamicCompleterFactory;
 import org.apache.ignite.internal.cli.core.repl.completer.hocon.NodeConfigDynamicCompleterFactory;
+import org.apache.ignite.internal.cli.core.repl.completer.jdbc.JdbcUrlDynamicCompleterFactory;
 import org.apache.ignite.internal.cli.core.repl.completer.node.NodeNameDynamicCompleterFactory;
+import org.apache.ignite.internal.cli.core.repl.completer.path.FilePathCompleter;
 
 /** Activation point that links commands with dynamic completers. */
 @Singleton
@@ -31,16 +34,21 @@ public class DynamicCompleterActivationPoint {
     private final NodeNameDynamicCompleterFactory nodeNameDynamicCompleterFactory;
     private final ClusterConfigDynamicCompleterFactory clusterConfigDynamicCompleterFactory;
     private final NodeConfigDynamicCompleterFactory nodeConfigDynamicCompleterFactory;
+    private final ClusterUrlDynamicCompleterFactory clusterUrlDynamicCompleterFactory;
+    private final JdbcUrlDynamicCompleterFactory jdbcUrlDynamicCompleterFactory;
 
     /** Main constructor. */
     public DynamicCompleterActivationPoint(
             NodeNameDynamicCompleterFactory nodeNameDynamicCompleterFactory,
             ClusterConfigDynamicCompleterFactory clusterConfigDynamicCompleterFactory,
-            NodeConfigDynamicCompleterFactory nodeConfigDynamicCompleterFactory
-    ) {
+            NodeConfigDynamicCompleterFactory nodeConfigDynamicCompleterFactory,
+            ClusterUrlDynamicCompleterFactory clusterUrlDynamicCompleterFactory,
+            JdbcUrlDynamicCompleterFactory jdbcUrlDynamicCompleterFactory) {
         this.nodeNameDynamicCompleterFactory = nodeNameDynamicCompleterFactory;
         this.clusterConfigDynamicCompleterFactory = clusterConfigDynamicCompleterFactory;
         this.nodeConfigDynamicCompleterFactory = nodeConfigDynamicCompleterFactory;
+        this.clusterUrlDynamicCompleterFactory = clusterUrlDynamicCompleterFactory;
+        this.jdbcUrlDynamicCompleterFactory = jdbcUrlDynamicCompleterFactory;
     }
 
 
@@ -86,5 +94,28 @@ public class DynamicCompleterActivationPoint {
                         .build(),
                 nodeNameDynamicCompleterFactory
         );
+
+        registry.register(
+                CompleterConf.builder()
+                        .command("sql")
+                        .enableOptions(Options.SCRIPT_FILE)
+                        .exclusiveEnableOptions().build(),
+                words -> new FilePathCompleter()
+        );
+
+        registry.register(
+                CompleterConf.builder()
+                        .command("sql")
+                        .enableOptions(Options.JDBC_URL)
+                        .exclusiveEnableOptions().build(),
+                jdbcUrlDynamicCompleterFactory
+        );
+
+        registry.register(
+                CompleterConf.builder()
+                        .enableOptions(Options.CLUSTER_URL, Options.NODE_URL)
+                        .exclusiveEnableOptions().build(),
+                clusterUrlDynamicCompleterFactory
+        );
     }
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/NodeUrlProvider.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/NodeUrlProvider.java
deleted file mode 100644
index 90126810da..0000000000
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/NodeUrlProvider.java
+++ /dev/null
@@ -1,65 +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.ignite.internal.cli.core.repl.completer;
-
-import static org.apache.ignite.internal.cli.commands.Options.Constants.CLUSTER_URL_OPTION;
-
-import jakarta.inject.Singleton;
-import org.apache.ignite.internal.cli.config.ConfigConstants;
-import org.apache.ignite.internal.cli.config.ConfigManagerProvider;
-import org.apache.ignite.internal.cli.core.repl.Session;
-
-/**
- * Url provider for completer.
- */
-@Singleton
-public class NodeUrlProvider {
-
-    private final Session session;
-    private final ConfigManagerProvider configManagerProvider;
-
-    /** Default constructor. */
-    public NodeUrlProvider(Session session, ConfigManagerProvider configManagerProvider) {
-        this.session = session;
-        this.configManagerProvider = configManagerProvider;
-    }
-
-    /** Resolves the url for given words. */
-    public String resolveUrl(String[] words) {
-        String urlInWords = findClusterUrlIn(words);
-        if (urlInWords != null) {
-            return urlInWords;
-        }
-
-        if (session.isConnectedToNode()) {
-            return session.nodeUrl();
-        }
-
-        return configManagerProvider.get().getCurrentProperty(ConfigConstants.CLUSTER_URL);
-    }
-
-    private String findClusterUrlIn(String[] words) {
-        for (String word : words) {
-            String prefix = CLUSTER_URL_OPTION + "=";
-            if (word.startsWith(prefix)) {
-                return word.substring(prefix.length());
-            }
-        }
-        return null;
-    }
-}
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/StringDynamicCompleter.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/StringDynamicCompleter.java
similarity index 94%
rename from modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/StringDynamicCompleter.java
rename to modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/StringDynamicCompleter.java
index 020c98224b..f90eb2c3b9 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/StringDynamicCompleter.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/StringDynamicCompleter.java
@@ -15,7 +15,7 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cli.core.repl.completer.node;
+package org.apache.ignite.internal.cli.core.repl.completer;
 
 import static org.apache.ignite.internal.cli.util.ArrayUtils.findLastNotEmptyWord;
 
@@ -30,7 +30,7 @@ import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleter;
  */
 public class StringDynamicCompleter implements DynamicCompleter {
 
-    /** Values that will ve suggested. */
+    /** Values that will be suggested. */
     private final Set<String> values;
 
     /** Default constructor. */
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/cluster/ClusterUrlDynamicCompleterFactory.java
similarity index 62%
copy from modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
copy to modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/cluster/ClusterUrlDynamicCompleterFactory.java
index 3d26caa1fc..39cf583080 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/cluster/ClusterUrlDynamicCompleterFactory.java
@@ -15,25 +15,33 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cli.core.repl.completer.node;
+package org.apache.ignite.internal.cli.core.repl.completer.cluster;
 
 import jakarta.inject.Singleton;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
+import java.net.URL;
+import java.util.Set;
+import java.util.stream.Collectors;
 import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleter;
 import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleterFactory;
+import org.apache.ignite.internal.cli.core.repl.completer.StringDynamicCompleter;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeNameRegistry;
 
-/** Factory for --node-name option completer. */
+/** Factory for --cluster-endpoint-url option completer. */
 @Singleton
-public class NodeNameDynamicCompleterFactory implements DynamicCompleterFactory {
+public class ClusterUrlDynamicCompleterFactory implements DynamicCompleterFactory {
 
     private final NodeNameRegistry nodeNameRegistry;
 
-    public NodeNameDynamicCompleterFactory(NodeNameRegistry nodeNameRegistry) {
+    public ClusterUrlDynamicCompleterFactory(NodeNameRegistry nodeNameRegistry) {
         this.nodeNameRegistry = nodeNameRegistry;
     }
 
     @Override
     public DynamicCompleter getDynamicCompleter(String[] words) {
-        return new StringDynamicCompleter(nodeNameRegistry.getAllNames());
+        Set<String> urls = nodeNameRegistry.urls()
+                .stream()
+                .map(URL::toString)
+                .collect(Collectors.toSet());
+        return new StringDynamicCompleter(urls);
     }
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/filter/DynamicCompleterFilter.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/filter/DynamicCompleterFilter.java
index bc2fe7f204..4674529e2a 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/filter/DynamicCompleterFilter.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/filter/DynamicCompleterFilter.java
@@ -73,7 +73,7 @@ public class DynamicCompleterFilter implements CompleterFilter {
 
     private boolean filterClusterUrl(String[] words, String candidate) {
         return optionTyped(words)
-                || !session.isConnectedToNode()
+                || session.info() == null
                 || (!candidate.equals(CLUSTER_URL_OPTION) && !candidate.equals(NODE_URL_OPTION));
     }
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/hocon/ClusterConfigDynamicCompleterFactory.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/hocon/ClusterConfigDynamicCompleterFactory.java
index e745ae105a..6a89b74aee 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/hocon/ClusterConfigDynamicCompleterFactory.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/hocon/ClusterConfigDynamicCompleterFactory.java
@@ -18,54 +18,29 @@
 package org.apache.ignite.internal.cli.core.repl.completer.hocon;
 
 import com.typesafe.config.Config;
-import com.typesafe.config.ConfigFactory;
 import jakarta.inject.Singleton;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicReference;
-import org.apache.ignite.internal.cli.call.configuration.ClusterConfigShowCall;
-import org.apache.ignite.internal.cli.call.configuration.ClusterConfigShowCallInput;
 import org.apache.ignite.internal.cli.core.repl.completer.DummyCompleter;
 import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleter;
 import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleterFactory;
-import org.apache.ignite.internal.cli.core.repl.completer.NodeUrlProvider;
+import org.apache.ignite.internal.cli.core.repl.registry.ClusterConfigRegistry;
 
 /** Factory for cluster config show/update command. */
 @Singleton
 public class ClusterConfigDynamicCompleterFactory implements DynamicCompleterFactory {
 
-    private final NodeUrlProvider urlProvider;
+    private final ClusterConfigRegistry clusterConfigRegistry;
 
-    private final ClusterConfigShowCall clusterConfigShowCall;
-
-    private final AtomicReference<DynamicCompleter> cachedCompleter = new AtomicReference<>(null);
-
-    public ClusterConfigDynamicCompleterFactory(NodeUrlProvider urlProvider, ClusterConfigShowCall clusterConfigShowCall) {
-        this.urlProvider = urlProvider;
-        this.clusterConfigShowCall = clusterConfigShowCall;
+    public ClusterConfigDynamicCompleterFactory(ClusterConfigRegistry clusterConfigRegistry) {
+        this.clusterConfigRegistry = clusterConfigRegistry;
     }
 
     @Override
     public DynamicCompleter getDynamicCompleter(String[] words) {
-        if (cachedCompleter.getAcquire() != null) {
-            return cachedCompleter.getAcquire();
+        Config config = clusterConfigRegistry.config();
+        if (config != null) {
+            return new HoconDynamicCompleter(config);
         } else {
-            // call REST on the background in order not to freeze UI thread
-            CompletableFuture.runAsync(() -> {
-                try {
-                    Config config = ConfigFactory.parseString(
-                            clusterConfigShowCall.execute(
-                                    // todo https://issues.apache.org/jira/browse/IGNITE-17416
-                                    ClusterConfigShowCallInput.builder().clusterUrl(urlProvider.resolveUrl(new String[]{""})).build()
-                            ).body().getValue()
-                    );
-                    cachedCompleter.compareAndExchangeRelease(null, new HoconDynamicCompleter(config));
-                } catch (Exception ignored) {
-                    // no-op
-                }
-            });
+            return new DummyCompleter();
         }
-
-        // return dummy completer this time, but hope the next call will return cached completer
-        return new DummyCompleter();
     }
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/hocon/NodeConfigDynamicCompleterFactory.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/hocon/NodeConfigDynamicCompleterFactory.java
index 7de52d4c85..990ce92b97 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/hocon/NodeConfigDynamicCompleterFactory.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/hocon/NodeConfigDynamicCompleterFactory.java
@@ -18,53 +18,29 @@
 package org.apache.ignite.internal.cli.core.repl.completer.hocon;
 
 import com.typesafe.config.Config;
-import com.typesafe.config.ConfigFactory;
 import jakarta.inject.Singleton;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicReference;
-import org.apache.ignite.internal.cli.call.configuration.NodeConfigShowCall;
-import org.apache.ignite.internal.cli.call.configuration.NodeConfigShowCallInput;
 import org.apache.ignite.internal.cli.core.repl.completer.DummyCompleter;
 import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleter;
 import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleterFactory;
-import org.apache.ignite.internal.cli.core.repl.completer.NodeUrlProvider;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeConfigRegistry;
 
 /** Factory for node config show/update completer. */
 @Singleton
 public class NodeConfigDynamicCompleterFactory implements DynamicCompleterFactory {
-    private final NodeUrlProvider urlProvider;
 
-    private final NodeConfigShowCall nodeConfigShowCall;
+    private final NodeConfigRegistry nodeConfigRegistry;
 
-    private final AtomicReference<DynamicCompleter> cachedCompleter = new AtomicReference<>(null);
-
-    public NodeConfigDynamicCompleterFactory(NodeUrlProvider urlProvider, NodeConfigShowCall nodeConfigShowCall) {
-        this.urlProvider = urlProvider;
-        this.nodeConfigShowCall = nodeConfigShowCall;
+    public NodeConfigDynamicCompleterFactory(NodeConfigRegistry nodeConfigRegistry) {
+        this.nodeConfigRegistry = nodeConfigRegistry;
     }
 
     @Override
     public DynamicCompleter getDynamicCompleter(String[] words) {
-        if (cachedCompleter.getAcquire() != null) {
-            return cachedCompleter.getAcquire();
+        Config config = nodeConfigRegistry.config();
+        if (config != null) {
+            return new HoconDynamicCompleter(config);
         } else {
-            // call REST on the background in order not to freeze UI thread
-            CompletableFuture.runAsync(() -> {
-                try {
-                    Config config = ConfigFactory.parseString(
-                            nodeConfigShowCall.execute(
-                                    // todo https://issues.apache.org/jira/browse/IGNITE-17416
-                                    NodeConfigShowCallInput.builder().nodeUrl(urlProvider.resolveUrl(new String[]{""})).build()
-                            ).body().getValue()
-                    );
-                    cachedCompleter.compareAndExchangeRelease(null, new HoconDynamicCompleter(config));
-                } catch (Exception ignored) {
-                    // no-op
-                }
-            });
+            return new DummyCompleter();
         }
-
-        // return dummy completer this time, but hope the next call will return cached completer
-        return new DummyCompleter();
     }
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/jdbc/JdbcUrlDynamicCompleterFactory.java
similarity index 64%
copy from modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
copy to modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/jdbc/JdbcUrlDynamicCompleterFactory.java
index 3d26caa1fc..28a0dcaefb 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/jdbc/JdbcUrlDynamicCompleterFactory.java
@@ -15,25 +15,26 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cli.core.repl.completer.node;
+package org.apache.ignite.internal.cli.core.repl.completer.jdbc;
 
 import jakarta.inject.Singleton;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
 import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleter;
 import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleterFactory;
+import org.apache.ignite.internal.cli.core.repl.completer.StringDynamicCompleter;
+import org.apache.ignite.internal.cli.core.repl.registry.JdbcUrlRegistry;
 
-/** Factory for --node-name option completer. */
+/** Factory for --jdbc-url option completer. */
 @Singleton
-public class NodeNameDynamicCompleterFactory implements DynamicCompleterFactory {
+public class JdbcUrlDynamicCompleterFactory implements DynamicCompleterFactory {
 
-    private final NodeNameRegistry nodeNameRegistry;
+    private final JdbcUrlRegistry jdbcUrlRegistry;
 
-    public NodeNameDynamicCompleterFactory(NodeNameRegistry nodeNameRegistry) {
-        this.nodeNameRegistry = nodeNameRegistry;
+    public JdbcUrlDynamicCompleterFactory(JdbcUrlRegistry jdbcUrlRegistry) {
+        this.jdbcUrlRegistry = jdbcUrlRegistry;
     }
 
     @Override
     public DynamicCompleter getDynamicCompleter(String[] words) {
-        return new StringDynamicCompleter(nodeNameRegistry.getAllNames());
+        return new StringDynamicCompleter(jdbcUrlRegistry.jdbcUrls());
     }
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
index 3d26caa1fc..75e5b21577 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
@@ -18,9 +18,10 @@
 package org.apache.ignite.internal.cli.core.repl.completer.node;
 
 import jakarta.inject.Singleton;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
 import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleter;
 import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleterFactory;
+import org.apache.ignite.internal.cli.core.repl.completer.StringDynamicCompleter;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeNameRegistry;
 
 /** Factory for --node-name option completer. */
 @Singleton
@@ -34,6 +35,6 @@ public class NodeNameDynamicCompleterFactory implements DynamicCompleterFactory
 
     @Override
     public DynamicCompleter getDynamicCompleter(String[] words) {
-        return new StringDynamicCompleter(nodeNameRegistry.getAllNames());
+        return new StringDynamicCompleter(nodeNameRegistry.names());
     }
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/path/FilePathCompleter.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/path/FilePathCompleter.java
new file mode 100644
index 0000000000..0d7fa5c377
--- /dev/null
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/path/FilePathCompleter.java
@@ -0,0 +1,75 @@
+/*
+ * 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.core.repl.completer.path;
+
+import static org.apache.ignite.internal.cli.util.ArrayUtils.findLastNotEmptyWord;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleter;
+
+/**
+ * Scans file system and completes typed words.
+ */
+public class FilePathCompleter implements DynamicCompleter {
+
+    @Override
+    public List<String> complete(String[] words) {
+        String notEmptyWord = findLastNotEmptyWord(words);
+        try {
+            return scan(notEmptyWord);
+        } catch (IOException e) {
+            return Collections.emptyList();
+        }
+    }
+
+    private static List<String> scan(String path) throws IOException {
+        Path filePath = Paths.get(path);
+        if (Files.exists(filePath)) {
+            if (Files.isDirectory(filePath)) {
+                return listFiles(filePath, "");
+            } else {
+                return Collections.singletonList(path);
+            }
+        } else {
+            int lastIndexOfPathSeparator = path.lastIndexOf(File.separator);
+            if (lastIndexOfPathSeparator > -1) {
+                String dir = path.substring(0, lastIndexOfPathSeparator + 1);
+                String filePrefix = path.substring(lastIndexOfPathSeparator + 1);
+                return listFiles(Paths.get(dir), filePrefix);
+            } else {
+                return Collections.emptyList();
+            }
+        }
+    }
+
+    private static List<String> listFiles(Path path, String prefix) throws IOException {
+        try (Stream<Path> stream = Files.list(path)) {
+            return stream.filter(it -> it.getFileName().toString().startsWith(prefix))
+                    .map(Path::toString)
+                    .collect(Collectors.toList());
+        }
+    }
+}
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/executor/ReplExecutor.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/executor/ReplExecutor.java
index ce394c2abc..58b5409732 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/executor/ReplExecutor.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/executor/ReplExecutor.java
@@ -22,7 +22,6 @@ import java.nio.file.Paths;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.function.Supplier;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
 import org.apache.ignite.internal.cli.commands.node.NodeNameOrUrl;
 import org.apache.ignite.internal.cli.config.StateFolderProvider;
 import org.apache.ignite.internal.cli.core.converters.NodeNameOrUrlConverter;
@@ -40,6 +39,7 @@ import org.apache.ignite.internal.cli.core.repl.completer.filter.NonRepeatableOp
 import org.apache.ignite.internal.cli.core.repl.completer.filter.ShortOptionsFilter;
 import org.apache.ignite.internal.cli.core.repl.context.CommandLineContextProvider;
 import org.apache.ignite.internal.cli.core.repl.expander.NoopExpander;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeNameRegistry;
 import org.jline.console.impl.SystemRegistryImpl;
 import org.jline.reader.Completer;
 import org.jline.reader.LineReader;
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/executor/ReplExecutorProvider.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/executor/ReplExecutorProvider.java
index c7a8e736db..582a175d61 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/executor/ReplExecutorProvider.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/executor/ReplExecutorProvider.java
@@ -20,7 +20,7 @@ package org.apache.ignite.internal.cli.core.repl.executor;
 import io.micronaut.configuration.picocli.MicronautFactory;
 import jakarta.inject.Inject;
 import jakarta.inject.Singleton;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeNameRegistry;
 import org.jline.terminal.Terminal;
 import picocli.shell.jline3.PicocliCommands.PicocliCommandsFactory;
 
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/prompt/ReplPromptProvider.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/prompt/ReplPromptProvider.java
index b9c2a83a23..3b26823061 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/prompt/ReplPromptProvider.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/prompt/ReplPromptProvider.java
@@ -22,6 +22,7 @@ import static org.apache.ignite.internal.cli.core.style.AnsiStringSupport.fg;
 
 import jakarta.inject.Singleton;
 import org.apache.ignite.internal.cli.core.repl.Session;
+import org.apache.ignite.internal.cli.core.repl.SessionInfo;
 import org.apache.ignite.internal.cli.core.style.AnsiStringSupport.Color;
 
 /**
@@ -41,8 +42,9 @@ public class ReplPromptProvider implements PromptProvider {
     @Override
     public String getPrompt() {
         String postfix = "> ";
-        return session.isConnectedToNode()
-                ? ansi(fg(Color.GREEN).mark("[" + session.nodeName() + "]")) + postfix
+        SessionInfo sessionInfo = session.info();
+        return sessionInfo != null
+                ? ansi(fg(Color.GREEN).mark("[" + sessionInfo.nodeName() + "]")) + postfix
                 : ansi(fg(Color.RED).mark("[disconnected]")) + postfix;
     }
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/ClusterConfigRegistry.java
similarity index 50%
copy from modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
copy to modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/ClusterConfigRegistry.java
index 3d26caa1fc..c42afaa8a1 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/ClusterConfigRegistry.java
@@ -15,25 +15,13 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cli.core.repl.completer.node;
+package org.apache.ignite.internal.cli.core.repl.registry;
 
-import jakarta.inject.Singleton;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
-import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleter;
-import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleterFactory;
+import com.typesafe.config.Config;
 
-/** Factory for --node-name option completer. */
-@Singleton
-public class NodeNameDynamicCompleterFactory implements DynamicCompleterFactory {
+/** Cluster config registry. */
+public interface ClusterConfigRegistry {
 
-    private final NodeNameRegistry nodeNameRegistry;
-
-    public NodeNameDynamicCompleterFactory(NodeNameRegistry nodeNameRegistry) {
-        this.nodeNameRegistry = nodeNameRegistry;
-    }
-
-    @Override
-    public DynamicCompleter getDynamicCompleter(String[] words) {
-        return new StringDynamicCompleter(nodeNameRegistry.getAllNames());
-    }
+    /** Returns cluster config. */
+    Config config();
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/JdbcUrlRegistry.java
similarity index 50%
copy from modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
copy to modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/JdbcUrlRegistry.java
index 3d26caa1fc..4b88ba4fce 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/JdbcUrlRegistry.java
@@ -15,25 +15,13 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cli.core.repl.completer.node;
+package org.apache.ignite.internal.cli.core.repl.registry;
 
-import jakarta.inject.Singleton;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
-import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleter;
-import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleterFactory;
+import java.util.Set;
 
-/** Factory for --node-name option completer. */
-@Singleton
-public class NodeNameDynamicCompleterFactory implements DynamicCompleterFactory {
+/** Jdbc url registry. */
+public interface JdbcUrlRegistry {
 
-    private final NodeNameRegistry nodeNameRegistry;
-
-    public NodeNameDynamicCompleterFactory(NodeNameRegistry nodeNameRegistry) {
-        this.nodeNameRegistry = nodeNameRegistry;
-    }
-
-    @Override
-    public DynamicCompleter getDynamicCompleter(String[] words) {
-        return new StringDynamicCompleter(nodeNameRegistry.getAllNames());
-    }
+    /** Returns set of jdbc urls. */
+    Set<String> jdbcUrls();
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/NodeConfigRegistry.java
similarity index 50%
copy from modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
copy to modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/NodeConfigRegistry.java
index 3d26caa1fc..6fcd041ca9 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/NodeConfigRegistry.java
@@ -15,25 +15,13 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cli.core.repl.completer.node;
+package org.apache.ignite.internal.cli.core.repl.registry;
 
-import jakarta.inject.Singleton;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
-import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleter;
-import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleterFactory;
+import com.typesafe.config.Config;
 
-/** Factory for --node-name option completer. */
-@Singleton
-public class NodeNameDynamicCompleterFactory implements DynamicCompleterFactory {
+/** Node config registry. */
+public interface NodeConfigRegistry {
 
-    private final NodeNameRegistry nodeNameRegistry;
-
-    public NodeNameDynamicCompleterFactory(NodeNameRegistry nodeNameRegistry) {
-        this.nodeNameRegistry = nodeNameRegistry;
-    }
-
-    @Override
-    public DynamicCompleter getDynamicCompleter(String[] words) {
-        return new StringDynamicCompleter(nodeNameRegistry.getAllNames());
-    }
+    /** Returns node config. */
+    Config config();
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/NodeNameRegistry.java
similarity index 50%
copy from modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
copy to modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/NodeNameRegistry.java
index 3d26caa1fc..4c267b1311 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/completer/node/NodeNameDynamicCompleterFactory.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/NodeNameRegistry.java
@@ -15,25 +15,22 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cli.core.repl.completer.node;
+package org.apache.ignite.internal.cli.core.repl.registry;
 
-import jakarta.inject.Singleton;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
-import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleter;
-import org.apache.ignite.internal.cli.core.repl.completer.DynamicCompleterFactory;
+import java.net.URL;
+import java.util.Optional;
+import java.util.Set;
 
-/** Factory for --node-name option completer. */
-@Singleton
-public class NodeNameDynamicCompleterFactory implements DynamicCompleterFactory {
+/** Node name registry. */
+public interface NodeNameRegistry {
 
-    private final NodeNameRegistry nodeNameRegistry;
+    /** Returns a node url by a provided node name. */
+    Optional<URL> nodeUrlByName(String nodeName);
 
-    public NodeNameDynamicCompleterFactory(NodeNameRegistry nodeNameRegistry) {
-        this.nodeNameRegistry = nodeNameRegistry;
-    }
+    /** Returns set of node names. */
+    Set<String> names();
+
+    /** Returns set of node urls. */
+    Set<URL> urls();
 
-    @Override
-    public DynamicCompleter getDynamicCompleter(String[] words) {
-        return new StringDynamicCompleter(nodeNameRegistry.getAllNames());
-    }
 }
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/ClusterConfigRegistryImpl.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/ClusterConfigRegistryImpl.java
new file mode 100644
index 0000000000..292ac24148
--- /dev/null
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/ClusterConfigRegistryImpl.java
@@ -0,0 +1,68 @@
+/*
+ * 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.core.repl.registry.impl;
+
+import com.typesafe.config.Config;
+import com.typesafe.config.ConfigFactory;
+import jakarta.inject.Singleton;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicReference;
+import org.apache.ignite.internal.cli.call.configuration.ClusterConfigShowCall;
+import org.apache.ignite.internal.cli.call.configuration.ClusterConfigShowCallInput;
+import org.apache.ignite.internal.cli.core.repl.AsyncSessionEventListener;
+import org.apache.ignite.internal.cli.core.repl.SessionInfo;
+import org.apache.ignite.internal.cli.core.repl.registry.ClusterConfigRegistry;
+
+/** Implementation of {@link ClusterConfigRegistry}. */
+@Singleton
+public class ClusterConfigRegistryImpl implements ClusterConfigRegistry, AsyncSessionEventListener {
+
+    private final ClusterConfigShowCall clusterConfigShowCall;
+
+    private final AtomicReference<Config> config = new AtomicReference<>(null);
+
+    public ClusterConfigRegistryImpl(ClusterConfigShowCall clusterConfigShowCall) {
+        this.clusterConfigShowCall = clusterConfigShowCall;
+    }
+
+    @Override
+    public void onConnect(SessionInfo sessionInfo) {
+        CompletableFuture.runAsync(() -> {
+            try {
+                config.set(ConfigFactory.parseString(
+                        clusterConfigShowCall.execute(
+                                ClusterConfigShowCallInput.builder().clusterUrl(sessionInfo.nodeUrl()).build()
+                        ).body().getValue()
+                ));
+            } catch (Exception ignored) {
+                // no-op
+            }
+        });
+    }
+
+    @Override
+    public void onDisconnect() {
+
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Config config() {
+        return config.get();
+    }
+}
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/JdbcUrlRegistryImpl.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/JdbcUrlRegistryImpl.java
new file mode 100644
index 0000000000..c0c82e891d
--- /dev/null
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/JdbcUrlRegistryImpl.java
@@ -0,0 +1,111 @@
+/*
+ * 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.core.repl.registry.impl;
+
+import com.google.gson.Gson;
+import jakarta.inject.Singleton;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.Executors;
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+import org.apache.ignite.internal.cli.core.JdbcUrl;
+import org.apache.ignite.internal.cli.core.repl.AsyncSessionEventListener;
+import org.apache.ignite.internal.cli.core.repl.SessionInfo;
+import org.apache.ignite.internal.cli.core.repl.config.RootConfig;
+import org.apache.ignite.internal.cli.core.repl.registry.JdbcUrlRegistry;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeNameRegistry;
+import org.apache.ignite.internal.cli.logger.CliLoggers;
+import org.apache.ignite.internal.logger.IgniteLogger;
+import org.apache.ignite.internal.thread.NamedThreadFactory;
+import org.apache.ignite.rest.client.api.NodeConfigurationApi;
+import org.apache.ignite.rest.client.invoker.ApiException;
+import org.apache.ignite.rest.client.invoker.Configuration;
+
+/** Implementation of {@link JdbcUrlRegistry}. */
+@Singleton
+public class JdbcUrlRegistryImpl implements JdbcUrlRegistry, AsyncSessionEventListener {
+
+    private static final IgniteLogger log = CliLoggers.forClass(JdbcUrlRegistryImpl.class);
+
+    private final NodeNameRegistry nodeNameRegistry;
+
+    private volatile Set<JdbcUrl> jdbcUrls = Set.of();
+
+    private ScheduledExecutorService executor;
+
+    public JdbcUrlRegistryImpl(NodeNameRegistry nodeNameRegistry) {
+        this.nodeNameRegistry = nodeNameRegistry;
+    }
+
+    private void fetchJdbcUrls() {
+        jdbcUrls = nodeNameRegistry.urls()
+                .stream()
+                .map(URL::toString)
+                .map(this::fetchJdbcUrl)
+                .filter(Objects::nonNull)
+                .collect(Collectors.toSet());
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Set<String> jdbcUrls() {
+        return jdbcUrls.stream()
+                .map(JdbcUrl::toString)
+                .collect(Collectors.toSet());
+    }
+
+    private JdbcUrl fetchJdbcUrl(String nodeUrl) {
+        try {
+            return constructJdbcUrl(fetchNodeConfiguration(nodeUrl), nodeUrl);
+        } catch (Exception e) {
+            log.warn("Couldn't fetch jdbc url of " + nodeUrl + " node: ", e);
+            return null;
+        }
+    }
+
+    private String fetchNodeConfiguration(String nodeUrl) throws ApiException {
+        return new NodeConfigurationApi(Configuration.getDefaultApiClient().setBasePath(nodeUrl)).getNodeConfiguration();
+    }
+
+    private JdbcUrl constructJdbcUrl(String configuration, String nodeUrl) {
+        try {
+            int port = new Gson().fromJson(configuration, RootConfig.class).clientConnector.port;
+            return JdbcUrl.of(nodeUrl, port);
+        } catch (MalformedURLException ignored) {
+            // Shouldn't happen ever since we are now connected to this URL
+            return null;
+        }
+    }
+
+    @Override
+    public void onConnect(SessionInfo sessionInfo) {
+        if (executor == null) {
+            executor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("JdbcUrlRegistry", log));
+            executor.scheduleWithFixedDelay(() -> fetchJdbcUrls(), 0, 5, TimeUnit.SECONDS);
+        }
+    }
+
+    @Override
+    public void onDisconnect() {
+
+    }
+}
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/NodeConfigRegistryImpl.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/NodeConfigRegistryImpl.java
new file mode 100644
index 0000000000..1f97fb22b1
--- /dev/null
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/NodeConfigRegistryImpl.java
@@ -0,0 +1,69 @@
+/*
+ * 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.core.repl.registry.impl;
+
+import com.typesafe.config.Config;
+import com.typesafe.config.ConfigFactory;
+import jakarta.inject.Singleton;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.atomic.AtomicReference;
+import org.apache.ignite.internal.cli.call.configuration.NodeConfigShowCall;
+import org.apache.ignite.internal.cli.call.configuration.NodeConfigShowCallInput;
+import org.apache.ignite.internal.cli.core.repl.AsyncSessionEventListener;
+import org.apache.ignite.internal.cli.core.repl.SessionInfo;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeConfigRegistry;
+
+/** Implementation of {@link NodeConfigRegistry}. */
+@Singleton
+public class NodeConfigRegistryImpl implements NodeConfigRegistry, AsyncSessionEventListener {
+
+    private final NodeConfigShowCall nodeConfigShowCall;
+
+    private final AtomicReference<Config> config = new AtomicReference<>(null);
+
+    public NodeConfigRegistryImpl(NodeConfigShowCall nodeConfigShowCall) {
+        this.nodeConfigShowCall = nodeConfigShowCall;
+    }
+
+    @Override
+    public void onConnect(SessionInfo sessionInfo) {
+        CompletableFuture.runAsync(() -> {
+            try {
+                config.set(ConfigFactory.parseString(
+                        nodeConfigShowCall.execute(
+                                // todo https://issues.apache.org/jira/browse/IGNITE-17416
+                                NodeConfigShowCallInput.builder().nodeUrl(sessionInfo.nodeUrl()).build()
+                        ).body().getValue())
+                );
+            } catch (Exception ignored) {
+                // no-op
+            }
+        });
+    }
+
+    @Override
+    public void onDisconnect() {
+
+    }
+
+    /** {@inheritDoc} */
+    @Override
+    public Config config() {
+        return this.config.get();
+    }
+}
diff --git a/modules/cli/src/main/java/org/apache/ignite/internal/cli/NodeNameRegistry.java b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/NodeNameRegistryImpl.java
similarity index 69%
rename from modules/cli/src/main/java/org/apache/ignite/internal/cli/NodeNameRegistry.java
rename to modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/NodeNameRegistryImpl.java
index 4037a0966a..72a048b13b 100644
--- a/modules/cli/src/main/java/org/apache/ignite/internal/cli/NodeNameRegistry.java
+++ b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/repl/registry/impl/NodeNameRegistryImpl.java
@@ -15,12 +15,13 @@
  * limitations under the License.
  */
 
-package org.apache.ignite.internal.cli;
+package org.apache.ignite.internal.cli.core.repl.registry.impl;
 
 import static org.apache.ignite.internal.util.IgniteUtils.shutdownAndAwaitTermination;
 
 import jakarta.inject.Singleton;
 import java.net.URL;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Optional;
 import java.util.Set;
@@ -30,63 +31,52 @@ import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
 import org.apache.ignite.internal.cli.call.cluster.topology.PhysicalTopologyCall;
 import org.apache.ignite.internal.cli.core.call.UrlCallInput;
+import org.apache.ignite.internal.cli.core.repl.AsyncSessionEventListener;
+import org.apache.ignite.internal.cli.core.repl.SessionInfo;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeNameRegistry;
+import org.apache.ignite.internal.cli.logger.CliLoggers;
 import org.apache.ignite.internal.logger.IgniteLogger;
-import org.apache.ignite.internal.logger.Loggers;
 import org.apache.ignite.internal.thread.NamedThreadFactory;
 import org.apache.ignite.rest.client.model.ClusterNode;
 import org.apache.ignite.rest.client.model.NodeMetadata;
 import org.jetbrains.annotations.Nullable;
 
-/**
- * Registry to get a node URL by a node name.
- */
+/** Implementation of {@link NodeNameRegistry}. */
 @Singleton
-public class NodeNameRegistry {
+public class NodeNameRegistryImpl implements NodeNameRegistry, AsyncSessionEventListener {
+
+    private static final IgniteLogger log = CliLoggers.forClass(NodeNameRegistryImpl.class);
+
+    private final PhysicalTopologyCall physicalTopologyCall;
 
-    private final IgniteLogger log = Loggers.forClass(getClass());
     private volatile Map<String, URL> nodeNameToNodeUrl = Map.of();
+
     private ScheduledExecutorService executor;
 
-    /**
-     * Start pulling updates from a node.
-     *
-     * @param nodeUrl Node URL.
-     */
-    public synchronized void startPullingUpdates(String nodeUrl) {
-        stopPullingUpdates();
-        if (executor == null) {
-            executor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("NodeNameRegistry", log));
-            executor.scheduleWithFixedDelay(() -> updateNodeNames(nodeUrl), 0, 5, TimeUnit.SECONDS);
-        }
+    public NodeNameRegistryImpl(PhysicalTopologyCall physicalTopologyCall) {
+        this.physicalTopologyCall = physicalTopologyCall;
     }
 
-    /**
-     * Gets a node url by a provided node name.
-     */
-    public Optional<URL> getNodeUrl(String nodeName) {
+    /** {@inheritDoc} */
+    @Override
+    public Optional<URL> nodeUrlByName(String nodeName) {
         return Optional.ofNullable(nodeNameToNodeUrl.get(nodeName));
     }
 
-    /**
-     * Gets all node names.
-     */
-    public Set<String> getAllNames() {
+    /** {@inheritDoc} */
+    @Override
+    public Set<String> names() {
         return nodeNameToNodeUrl.keySet();
     }
 
-    /**
-     * Stops pulling updates.
-     */
-    public synchronized void stopPullingUpdates() {
-        if (executor != null) {
-            shutdownAndAwaitTermination(executor, 3, TimeUnit.SECONDS);
-            executor = null;
-        }
+    /** {@inheritDoc} */
+    @Override
+    public Set<URL> urls() {
+        return new HashSet<>(nodeNameToNodeUrl.values());
     }
 
     private void updateNodeNames(String nodeUrl) {
-        PhysicalTopologyCall topologyCall = new PhysicalTopologyCall();
-        nodeNameToNodeUrl = topologyCall.execute(new UrlCallInput(nodeUrl))
+        nodeNameToNodeUrl = physicalTopologyCall.execute(new UrlCallInput(nodeUrl))
                 .body()
                 .stream()
                 .map(this::toNodeNameAndUrlPair)
@@ -111,6 +101,32 @@ public class NodeNameRegistry {
         }
     }
 
+    /**
+     * Start pulling updates from a node.
+     *
+     * @param sessionInfo sessionInfo.
+     */
+
+    @Override
+    public void onConnect(SessionInfo sessionInfo) {
+        if (executor == null) {
+            executor = Executors.newSingleThreadScheduledExecutor(new NamedThreadFactory("NodeNameRegistry", log));
+            executor.scheduleWithFixedDelay(() ->
+                    updateNodeNames(sessionInfo.nodeUrl()), 0, 5, TimeUnit.SECONDS);
+        }
+    }
+
+    /**
+     * Stops pulling updates.
+     */
+    @Override
+    public void onDisconnect() {
+        if (executor != null) {
+            shutdownAndAwaitTermination(executor, 3, TimeUnit.SECONDS);
+            executor = null;
+        }
+    }
+
     private static class NodeNameAndUrlPair {
         private final String name;
         private final URL url;
diff --git a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/CliCommandTestBase.java b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/CliCommandTestBase.java
index 2c96d96034..a0e767c2c4 100644
--- a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/CliCommandTestBase.java
+++ b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/CliCommandTestBase.java
@@ -27,9 +27,9 @@ import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.HashMap;
 import java.util.Map;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
 import org.apache.ignite.internal.cli.commands.node.NodeNameOrUrl;
 import org.apache.ignite.internal.cli.core.converters.NodeNameOrUrlConverter;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeNameRegistry;
 import org.junit.jupiter.api.BeforeEach;
 import picocli.CommandLine;
 
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 3bf8b67591..6ef3a715d4 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
@@ -29,7 +29,6 @@ import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.util.ArrayList;
 import java.util.List;
-import org.apache.ignite.internal.cli.NodeNameRegistry;
 import org.apache.ignite.internal.cli.commands.cliconfig.TestConfigManagerHelper;
 import org.apache.ignite.internal.cli.commands.cliconfig.TestConfigManagerProvider;
 import org.apache.ignite.internal.cli.commands.cluster.config.ClusterConfigShowCommand;
@@ -61,6 +60,7 @@ import org.apache.ignite.internal.cli.commands.node.status.NodeStatusReplCommand
 import org.apache.ignite.internal.cli.config.ini.IniConfigManager;
 import org.apache.ignite.internal.cli.core.converters.NodeNameOrUrlConverter;
 import org.apache.ignite.internal.cli.core.repl.context.CommandLineContextProvider;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeNameRegistry;
 import org.junit.jupiter.api.DisplayName;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
diff --git a/modules/cli/src/test/java/org/apache/ignite/internal/cli/core/repl/completer/StringDynamicCompleterTest.java b/modules/cli/src/test/java/org/apache/ignite/internal/cli/core/repl/completer/StringDynamicCompleterTest.java
index 7445377329..96a2b2d77e 100644
--- a/modules/cli/src/test/java/org/apache/ignite/internal/cli/core/repl/completer/StringDynamicCompleterTest.java
+++ b/modules/cli/src/test/java/org/apache/ignite/internal/cli/core/repl/completer/StringDynamicCompleterTest.java
@@ -22,7 +22,6 @@ import static org.hamcrest.Matchers.containsInAnyOrder;
 
 import java.util.Set;
 import java.util.stream.Stream;
-import org.apache.ignite.internal.cli.core.repl.completer.node.StringDynamicCompleter;
 import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.Arguments;
diff --git a/modules/cli/src/test/java/org/apache/ignite/internal/cli/core/repl/completer/filter/DynamicCompleterFilterTest.java b/modules/cli/src/test/java/org/apache/ignite/internal/cli/core/repl/completer/filter/DynamicCompleterFilterTest.java
index ee0c5df94a..c6e879a900 100644
--- a/modules/cli/src/test/java/org/apache/ignite/internal/cli/core/repl/completer/filter/DynamicCompleterFilterTest.java
+++ b/modules/cli/src/test/java/org/apache/ignite/internal/cli/core/repl/completer/filter/DynamicCompleterFilterTest.java
@@ -22,7 +22,9 @@ import static org.hamcrest.MatcherAssert.assertThat;
 import static org.hamcrest.Matchers.containsInAnyOrder;
 import static org.hamcrest.Matchers.emptyArray;
 
+import java.util.Collections;
 import org.apache.ignite.internal.cli.core.repl.Session;
+import org.apache.ignite.internal.cli.core.repl.SessionInfo;
 import org.apache.ignite.internal.cli.core.repl.completer.filter.DynamicCompleterFilter;
 import org.junit.jupiter.api.Test;
 
@@ -45,14 +47,14 @@ class DynamicCompleterFilterTest {
     }
 
     private static Session notConnected() {
-        Session session = new Session();
-        session.setConnectedToNode(false);
+        Session session = new Session(Collections.emptyList());
+        session.disconnect();
         return session;
     }
 
     private static Session connected() {
-        Session session = new Session();
-        session.setConnectedToNode(true);
+        Session session = new Session(Collections.emptyList());
+        session.connect(new SessionInfo("nodeUrl", "nodeName", "jdbcUrl"));
         return session;
     }