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

apkhmv 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 b87aef7902 IGNITE-18943 Disable the set of endpoints for 
non-initialized cluster (#1812)
b87aef7902 is described below

commit b87aef79020daff0a3110546a46866f6fd376270
Author: Aleksandr Pakhomov <[email protected]>
AuthorDate: Wed Mar 22 15:06:47 2023 +0400

    IGNITE-18943 Disable the set of endpoints for non-initialized cluster 
(#1812)
    
    Co-authored-by: Vadim Pakhnushev <[email protected]>
---
 .../cli/call/cluster/status/ClusterStatusCall.java |   2 +-
 .../internal/cli/call/unit/DeployUnitCall.java     |   4 +
 .../internal/cli/call/unit/ListUnitCall.java       |   2 +-
 .../internal/cli/call/unit/UndeployUnitCall.java   |   3 +-
 .../internal/cli/call/unit/UnitStatusCall.java     |   2 +-
 .../node/metric/NodeMetricDisableCommand.java      |   2 +
 .../node/metric/NodeMetricDisableReplCommand.java  |   2 +
 .../node/metric/NodeMetricEnableCommand.java       |   2 +
 .../node/metric/NodeMetricEnableReplCommand.java   |   2 +
 .../node/metric/NodeMetricListCommand.java         |   2 +
 .../node/metric/NodeMetricListReplCommand.java     |   2 +
 .../cli/commands/unit/UnitDeployCommand.java       |   2 +
 .../cli/commands/unit/UnitListCommand.java         |   2 +
 .../cli/commands/unit/UnitStatusCommand.java       |   2 +
 .../cli/commands/unit/UnitUndeployCommand.java     |   2 +
 .../ClusterNotInitializedExceptionHandler.java     |   2 +-
 .../management/ClusterManagementGroupManager.java  |   2 +-
 .../ItNodeOnlyEndpointsFilterInitializedTest.java  |  74 +++++++++++++++
 ...tNodeOnlyEndpointsFilterNotInitializedTest.java | 105 +++++++++++++++++++++
 .../apache/ignite/internal/rest/RestComponent.java |  12 +--
 .../authentication/NodeOnlyEndpointsFilter.java    |  89 +++++++++++++++++
 .../rest/ItNotInitializedClusterRestTest.java      |  24 ++---
 22 files changed, 317 insertions(+), 24 deletions(-)

diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/cluster/status/ClusterStatusCall.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/cluster/status/ClusterStatusCall.java
index dcb0b64f9a..bb726633f4 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/cluster/status/ClusterStatusCall.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/cluster/status/ClusterStatusCall.java
@@ -58,7 +58,7 @@ public class ClusterStatusCall implements Call<UrlCallInput, 
ClusterStatus> {
                     .metadataStorageNodes(clusterState.getMsNodes())
                     .cmgNodes(clusterState.getCmgNodes());
         } catch (ApiException e) {
-            if (e.getCode() == 404) { // NOT_FOUND means the cluster is not 
initialized yet
+            if (e.getCode() == 409) { // CONFLICT means the cluster is not 
initialized yet
                 
clusterStatusBuilder.initialized(false).nodeCount(fetchNumberOfAllNodes(input));
             } else {
                 return DefaultCallOutput.failure(new IgniteCliApiException(e, 
clusterUrl));
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/DeployUnitCall.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/DeployUnitCall.java
index 02537ddf5f..7093accc12 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/DeployUnitCall.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/DeployUnitCall.java
@@ -89,6 +89,10 @@ public class DeployUnitCall implements 
AsyncCall<DeployUnitCallInput, String> {
         if (exception instanceof ApiException) {
             ApiException apiException = (ApiException) exception;
             if (apiException.getCode() == 409) {
+                // special case when cluster is not initialized
+                if (apiException.getResponseBody().contains("Cluster is not 
initialized")) {
+                    return DefaultCallOutput.failure(new 
IgniteCliApiException(exception, input.clusterUrl()));
+                }
                 return DefaultCallOutput.failure(new 
UnitAlreadyExistsException(input.id(), input.version()));
             }
         }
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/ListUnitCall.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/ListUnitCall.java
index 8d7b4f4465..8a51311660 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/ListUnitCall.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/ListUnitCall.java
@@ -53,7 +53,7 @@ public class ListUnitCall implements Call<UrlCallInput, 
List<UnitStatusRecord>>
                             .collect(Collectors.toList())
             );
         } catch (ApiException e) {
-            throw new IgniteCliApiException(e, input.getUrl());
+            return DefaultCallOutput.failure(new IgniteCliApiException(e, 
input.getUrl()));
         }
     }
 
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/UndeployUnitCall.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/UndeployUnitCall.java
index 87f8c8f1c8..e6a532caf0 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/UndeployUnitCall.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/UndeployUnitCall.java
@@ -22,6 +22,7 @@ import org.apache.ignite.internal.cli.core.ApiClientFactory;
 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.exception.UnitNotFoundException;
 import org.apache.ignite.internal.cli.core.repl.registry.UnitsRegistry;
 import org.apache.ignite.internal.cli.core.style.component.MessageUiComponent;
@@ -57,7 +58,7 @@ public class UndeployUnitCall implements 
Call<UndeployUnitCallInput, String> {
                 return DefaultCallOutput.failure(new 
UnitNotFoundException(input.id(), input.version()));
             }
 
-            return DefaultCallOutput.failure(e);
+            return DefaultCallOutput.failure(new IgniteCliApiException(e, 
input.clusterUrl()));
         }
     }
 }
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/UnitStatusCall.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/UnitStatusCall.java
index 075da4db38..64cc308eca 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/UnitStatusCall.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/call/unit/UnitStatusCall.java
@@ -48,7 +48,7 @@ public class UnitStatusCall implements 
Call<UnitStatusCallInput, UnitStatusRecor
                 return DefaultCallOutput.failure(new 
UnitNotFoundException(input.id()));
             }
 
-            throw new IgniteCliApiException(e, input.clusterUrl());
+            return DefaultCallOutput.failure(new IgniteCliApiException(e, 
input.clusterUrl()));
         }
     }
 
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricDisableCommand.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricDisableCommand.java
index fdefe92bef..fdaad9a48d 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricDisableCommand.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricDisableCommand.java
@@ -24,6 +24,7 @@ import org.apache.ignite.internal.cli.commands.BaseCommand;
 import org.apache.ignite.internal.cli.commands.metric.MetricSourceMixin;
 import org.apache.ignite.internal.cli.commands.node.NodeUrlProfileMixin;
 import org.apache.ignite.internal.cli.core.call.CallExecutionPipeline;
+import 
org.apache.ignite.internal.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Mixin;
 
@@ -48,6 +49,7 @@ public class NodeMetricDisableCommand extends BaseCommand 
implements Callable<In
                 .output(spec.commandLine().getOut())
                 .errOutput(spec.commandLine().getErr())
                 .verbose(verbose)
+                .exceptionHandler(new 
ClusterNotInitializedExceptionHandler("Cannot disable metrics", "cluster init"))
                 .build()
                 .runPipeline();
     }
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricDisableReplCommand.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricDisableReplCommand.java
index c549fe4747..39c0e38852 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricDisableReplCommand.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricDisableReplCommand.java
@@ -23,6 +23,7 @@ import org.apache.ignite.internal.cli.commands.BaseCommand;
 import org.apache.ignite.internal.cli.commands.metric.MetricSourceMixin;
 import org.apache.ignite.internal.cli.commands.node.NodeUrlMixin;
 import 
org.apache.ignite.internal.cli.commands.questions.ConnectToClusterQuestion;
+import 
org.apache.ignite.internal.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import org.apache.ignite.internal.cli.core.flow.builder.Flows;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Mixin;
@@ -48,6 +49,7 @@ public class NodeMetricDisableReplCommand extends BaseCommand 
implements Runnabl
         question.askQuestionIfNotConnected(nodeUrl.getNodeUrl())
                 .map(metricSource::buildDisableCallInput)
                 .then(Flows.fromCall(call))
+                .exceptionHandler(new 
ClusterNotInitializedExceptionHandler("Cannot disable metrics", "cluster init"))
                 .verbose(verbose)
                 .print()
                 .start();
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricEnableCommand.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricEnableCommand.java
index efd67828d8..f4f2bd6772 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricEnableCommand.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricEnableCommand.java
@@ -24,6 +24,7 @@ import org.apache.ignite.internal.cli.commands.BaseCommand;
 import org.apache.ignite.internal.cli.commands.metric.MetricSourceMixin;
 import org.apache.ignite.internal.cli.commands.node.NodeUrlProfileMixin;
 import org.apache.ignite.internal.cli.core.call.CallExecutionPipeline;
+import 
org.apache.ignite.internal.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Mixin;
 
@@ -48,6 +49,7 @@ public class NodeMetricEnableCommand extends BaseCommand 
implements Callable<Int
                 .output(spec.commandLine().getOut())
                 .errOutput(spec.commandLine().getErr())
                 .verbose(verbose)
+                .exceptionHandler(new 
ClusterNotInitializedExceptionHandler("Cannot enable metrics", "cluster init"))
                 .build()
                 .runPipeline();
     }
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricEnableReplCommand.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricEnableReplCommand.java
index 290d2f929f..be7d604898 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricEnableReplCommand.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricEnableReplCommand.java
@@ -23,6 +23,7 @@ import org.apache.ignite.internal.cli.commands.BaseCommand;
 import org.apache.ignite.internal.cli.commands.metric.MetricSourceMixin;
 import org.apache.ignite.internal.cli.commands.node.NodeUrlMixin;
 import 
org.apache.ignite.internal.cli.commands.questions.ConnectToClusterQuestion;
+import 
org.apache.ignite.internal.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import org.apache.ignite.internal.cli.core.flow.builder.Flows;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Mixin;
@@ -48,6 +49,7 @@ public class NodeMetricEnableReplCommand extends BaseCommand 
implements Runnable
         question.askQuestionIfNotConnected(nodeUrl.getNodeUrl())
                 .map(metricSource::buildEnableCallInput)
                 .then(Flows.fromCall(call))
+                .exceptionHandler(new 
ClusterNotInitializedExceptionHandler("Cannot enable metrics", "cluster init"))
                 .verbose(verbose)
                 .print()
                 .start();
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricListCommand.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricListCommand.java
index adfe1ce727..f273a65619 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricListCommand.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricListCommand.java
@@ -24,6 +24,7 @@ import org.apache.ignite.internal.cli.commands.BaseCommand;
 import org.apache.ignite.internal.cli.commands.node.NodeUrlProfileMixin;
 import org.apache.ignite.internal.cli.core.call.CallExecutionPipeline;
 import org.apache.ignite.internal.cli.core.call.StringCallInput;
+import 
org.apache.ignite.internal.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import org.apache.ignite.internal.cli.decorators.MetricListDecorator;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Mixin;
@@ -47,6 +48,7 @@ public class NodeMetricListCommand extends BaseCommand 
implements Callable<Integ
                 .errOutput(spec.commandLine().getErr())
                 .decorator(new MetricListDecorator())
                 .verbose(verbose)
+                .exceptionHandler(new 
ClusterNotInitializedExceptionHandler("Cannot list metrics", "cluster init"))
                 .build()
                 .runPipeline();
     }
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricListReplCommand.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricListReplCommand.java
index 0ee87407d2..0c32af3f63 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricListReplCommand.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/node/metric/NodeMetricListReplCommand.java
@@ -23,6 +23,7 @@ import org.apache.ignite.internal.cli.commands.BaseCommand;
 import org.apache.ignite.internal.cli.commands.node.NodeUrlMixin;
 import 
org.apache.ignite.internal.cli.commands.questions.ConnectToClusterQuestion;
 import org.apache.ignite.internal.cli.core.call.StringCallInput;
+import 
org.apache.ignite.internal.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import org.apache.ignite.internal.cli.core.flow.builder.Flows;
 import org.apache.ignite.internal.cli.decorators.MetricListDecorator;
 import picocli.CommandLine.Command;
@@ -47,6 +48,7 @@ public class NodeMetricListReplCommand extends BaseCommand 
implements Runnable {
         question.askQuestionIfNotConnected(nodeUrl.getNodeUrl())
                 .map(StringCallInput::new)
                 .then(Flows.fromCall(call))
+                .exceptionHandler(new 
ClusterNotInitializedExceptionHandler("Cannot list metrics", "cluster init"))
                 .print(new MetricListDecorator())
                 .start();
     }
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitDeployCommand.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitDeployCommand.java
index 16d5b664ba..6745dbd44c 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitDeployCommand.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitDeployCommand.java
@@ -33,6 +33,7 @@ import 
org.apache.ignite.internal.cli.call.unit.DeployUnitCallInput;
 import org.apache.ignite.internal.cli.commands.BaseCommand;
 import org.apache.ignite.internal.cli.commands.cluster.ClusterUrlProfileMixin;
 import org.apache.ignite.internal.cli.core.call.CallExecutionPipeline;
+import 
org.apache.ignite.internal.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Mixin;
 import picocli.CommandLine.Option;
@@ -72,6 +73,7 @@ public class UnitDeployCommand extends BaseCommand implements 
Callable<Integer>
                 .output(spec.commandLine().getOut())
                 .errOutput(spec.commandLine().getErr())
                 .verbose(verbose)
+                .exceptionHandler(new 
ClusterNotInitializedExceptionHandler("Cannot deploy unit", "cluster init"))
                 .build().runPipeline();
     }
 }
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitListCommand.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitListCommand.java
index 788867544a..8234cb6167 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitListCommand.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitListCommand.java
@@ -25,6 +25,7 @@ import org.apache.ignite.internal.cli.commands.BaseCommand;
 import org.apache.ignite.internal.cli.commands.cluster.ClusterUrlProfileMixin;
 import org.apache.ignite.internal.cli.core.call.CallExecutionPipeline;
 import org.apache.ignite.internal.cli.core.call.UrlCallInput;
+import 
org.apache.ignite.internal.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import org.apache.ignite.internal.cli.decorators.UnitListDecorator;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Mixin;
@@ -47,6 +48,7 @@ public class UnitListCommand extends BaseCommand implements 
Callable<Integer> {
                 .errOutput(spec.commandLine().getErr())
                 .verbose(verbose)
                 .decorator(new UnitListDecorator())
+                .exceptionHandler(new 
ClusterNotInitializedExceptionHandler("Cannot list units", "cluster init"))
                 .build().runPipeline();
     }
 }
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitStatusCommand.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitStatusCommand.java
index e6e31d70a9..457df8f7f3 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitStatusCommand.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitStatusCommand.java
@@ -25,6 +25,7 @@ import 
org.apache.ignite.internal.cli.call.unit.UnitStatusCallInput;
 import org.apache.ignite.internal.cli.commands.BaseCommand;
 import org.apache.ignite.internal.cli.commands.cluster.ClusterUrlProfileMixin;
 import org.apache.ignite.internal.cli.core.call.CallExecutionPipeline;
+import 
org.apache.ignite.internal.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import org.apache.ignite.internal.cli.decorators.UnitStatusDecorator;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Mixin;
@@ -56,6 +57,7 @@ public class UnitStatusCommand extends BaseCommand implements 
Callable<Integer>
                 .errOutput(spec.commandLine().getErr())
                 .verbose(verbose)
                 .decorator(new UnitStatusDecorator())
+                .exceptionHandler(new 
ClusterNotInitializedExceptionHandler("Cannot get unit status", "cluster init"))
                 .build().runPipeline();
     }
 }
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitUndeployCommand.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitUndeployCommand.java
index c2a1f8d616..6cfd3e734d 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitUndeployCommand.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/commands/unit/UnitUndeployCommand.java
@@ -29,6 +29,7 @@ import 
org.apache.ignite.internal.cli.call.unit.UndeployUnitCallInput;
 import org.apache.ignite.internal.cli.commands.BaseCommand;
 import org.apache.ignite.internal.cli.commands.cluster.ClusterUrlProfileMixin;
 import org.apache.ignite.internal.cli.core.call.CallExecutionPipeline;
+import 
org.apache.ignite.internal.cli.core.exception.handler.ClusterNotInitializedExceptionHandler;
 import picocli.CommandLine.Command;
 import picocli.CommandLine.Mixin;
 import picocli.CommandLine.Option;
@@ -63,6 +64,7 @@ public class UnitUndeployCommand extends BaseCommand 
implements Callable<Integer
                 .output(spec.commandLine().getOut())
                 .errOutput(spec.commandLine().getErr())
                 .verbose(verbose)
+                .exceptionHandler(new 
ClusterNotInitializedExceptionHandler("Cannot undeploy unit", "cluster init"))
                 .build().runPipeline();
     }
 }
diff --git 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/exception/handler/ClusterNotInitializedExceptionHandler.java
 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/exception/handler/ClusterNotInitializedExceptionHandler.java
index 459a9f15a8..7cbde65b61 100644
--- 
a/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/exception/handler/ClusterNotInitializedExceptionHandler.java
+++ 
b/modules/cli/src/main/java/org/apache/ignite/internal/cli/core/exception/handler/ClusterNotInitializedExceptionHandler.java
@@ -46,7 +46,7 @@ public class ClusterNotInitializedExceptionHandler extends 
IgniteCliApiException
     public int handle(ExceptionWriter err, IgniteCliApiException e) {
         if (e.getCause() instanceof ApiException) {
             ApiException apiException = (ApiException) e.getCause();
-            if (apiException.getCode() == 404) {
+            if (apiException.getCode() == 409) { // CONFLICT means not 
initialized
                 err.write(
                         ErrorUiComponent.builder()
                                 .header(header)
diff --git 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManager.java
 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManager.java
index 84ca9c6521..d56aed7592 100644
--- 
a/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManager.java
+++ 
b/modules/cluster-management/src/main/java/org/apache/ignite/internal/cluster/management/ClusterManagementGroupManager.java
@@ -404,7 +404,7 @@ public class ClusterManagementGroupManager implements 
IgniteComponent {
                         LOG.info("No REST auth configuration found in the Raft 
storage");
                         return completedFuture(null);
                     } else {
-                        //TODO 
https://issues.apache.org/jira/browse/IGNITE-18943
+                        //TODO 
https://issues.apache.org/jira/browse/IGNITE-19077
                         LOG.info("REST auth configuration found in the Raft 
storage, going to apply it");
                         Authentication restAuthToApply = 
state.restAuthToApply();
                         return 
distributedConfigurationUpdater.updateRestAuthConfiguration(restAuthToApply)
diff --git 
a/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/ItNodeOnlyEndpointsFilterInitializedTest.java
 
b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/ItNodeOnlyEndpointsFilterInitializedTest.java
new file mode 100644
index 0000000000..4da84b98c5
--- /dev/null
+++ 
b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/ItNodeOnlyEndpointsFilterInitializedTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.rest;
+
+import static 
org.apache.ignite.internal.testframework.IgniteTestUtils.testNodeName;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+import io.micronaut.http.HttpRequest;
+import io.micronaut.http.client.HttpClient;
+import io.micronaut.http.client.annotation.Client;
+import jakarta.inject.Inject;
+import java.util.stream.Stream;
+import org.apache.ignite.internal.testframework.IntegrationTestBase;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+/** Tests that after cluster is initialized, all endpoints are available. */
+public class ItNodeOnlyEndpointsFilterInitializedTest extends 
IntegrationTestBase {
+
+    @Inject
+    @Client(NODE_URL + "/management/v1")
+    HttpClient client;
+
+    private static Stream<Arguments> endpoints() {
+        return Stream.of(
+                Arguments.of("deployment/units"),
+                Arguments.of("node/state"),
+                Arguments.of("configuration/cluster"),
+                Arguments.of("configuration/node"),
+                Arguments.of("configuration/node/rest"),
+                Arguments.of("cluster/topology/logical"),
+                Arguments.of("cluster/topology/physical")
+        );
+    }
+
+    @BeforeAll
+    public void setup(TestInfo testInfo) {
+        startNodes(testInfo);
+        String metaStorageNodeName = testNodeName(testInfo, 0);
+        initializeCluster(metaStorageNodeName);
+    }
+
+    @AfterAll
+    public void cleanup(TestInfo testInfo) throws Exception {
+        stopNodes(testInfo);
+    }
+
+    @ParameterizedTest
+    @MethodSource("endpoints")
+    void clusterEndpointsEnabled(String path) {
+        assertDoesNotThrow(
+                () -> client.toBlocking().retrieve(HttpRequest.GET(path))
+        );
+    }
+}
diff --git 
a/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/ItNodeOnlyEndpointsFilterNotInitializedTest.java
 
b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/ItNodeOnlyEndpointsFilterNotInitializedTest.java
new file mode 100644
index 0000000000..6e78409b72
--- /dev/null
+++ 
b/modules/rest/src/integrationTest/java/org/apache/ignite/internal/rest/ItNodeOnlyEndpointsFilterNotInitializedTest.java
@@ -0,0 +1,105 @@
+/*
+ * 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.rest;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import io.micronaut.http.HttpRequest;
+import io.micronaut.http.client.HttpClient;
+import io.micronaut.http.client.annotation.Client;
+import io.micronaut.http.client.exceptions.HttpClientResponseException;
+import jakarta.inject.Inject;
+import java.util.stream.Stream;
+import org.apache.ignite.internal.rest.api.Problem;
+import org.apache.ignite.internal.testframework.IntegrationTestBase;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.TestInfo;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+/** Tests that before cluster is initialized, only a subset of endpoints are 
available. */
+public class ItNodeOnlyEndpointsFilterNotInitializedTest extends 
IntegrationTestBase {
+
+    private ObjectMapper mapper = new ObjectMapper();
+
+    @Inject
+    @Client(NODE_URL + "/management/v1")
+    HttpClient client;
+
+    private static Stream<Arguments> disabledEndpoints() {
+        return Stream.of(
+                Arguments.of("deployment/units"),
+                Arguments.of("configuration/cluster"),
+                Arguments.of("cluster/topology/logical")
+        );
+    }
+
+    private static Stream<Arguments> enabledEndpoints() {
+        return Stream.of(
+                Arguments.of("node/state"),
+                Arguments.of("configuration/node"),
+                Arguments.of("configuration/node/rest"),
+                Arguments.of("cluster/topology/physical")
+        );
+    }
+
+    @BeforeAll
+    public void setup(TestInfo testInfo) {
+        // Given non-initialized cluster.
+        startNodes(testInfo);
+    }
+
+    @AfterAll
+    public void cleanup(TestInfo testInfo) throws Exception {
+        stopNodes(testInfo);
+    }
+
+    @ParameterizedTest
+    @MethodSource("disabledEndpoints")
+    void clusterEndpointsDisabledWhenNotInitialized(String path) throws 
JsonProcessingException {
+        HttpClientResponseException ex = assertThrows(
+                HttpClientResponseException.class,
+                () -> client.toBlocking().retrieve(HttpRequest.GET(path), 
String.class)
+        );
+
+        assertThat(ex.getStatus().getCode(), is(409));
+        Problem problem = readProblem(ex);
+        assertThat(problem.status(), is(409));
+        assertThat(problem.detail(), is("Cluster is not initialized. Call 
/management/v1/cluster/init in order to initialize cluster."));
+    }
+
+    private Problem readProblem(HttpClientResponseException ex) throws 
JsonProcessingException {
+        return mapper.readValue(ex.getResponse().getBody(String.class).get(), 
Problem.class);
+    }
+
+    @ParameterizedTest
+    @MethodSource("enabledEndpoints")
+    void nodeConfigAndClusterInitAreEnabled(String path) {
+        // But node config and cluster init endpoints are enabled
+        assertDoesNotThrow(
+                () -> client.toBlocking().retrieve(HttpRequest.GET(path))
+        );
+    }
+}
diff --git 
a/modules/rest/src/main/java/org/apache/ignite/internal/rest/RestComponent.java 
b/modules/rest/src/main/java/org/apache/ignite/internal/rest/RestComponent.java
index 518bb06ffb..a7a29def2f 100644
--- 
a/modules/rest/src/main/java/org/apache/ignite/internal/rest/RestComponent.java
+++ 
b/modules/rest/src/main/java/org/apache/ignite/internal/rest/RestComponent.java
@@ -196,13 +196,15 @@ public class RestComponent implements IgniteComponent {
         RestSslView restSslView = restConfiguration.ssl().value();
         boolean sslEnabled = restSslView.enabled();
 
+        Map<String, Object> result = new HashMap<>();
+        result.put("micronaut.server.port", port);
+        result.put("ignite.endpoints.filter-non-initialized", "true");
+
         if (sslEnabled) {
             KeyStoreView keyStore = restSslView.keyStore();
             boolean dualProtocol = restConfiguration.dualProtocol().value();
 
-            Map<String, Object> result = new HashMap<>();
             // Micronaut is not going to handle requests on that port, but 
it's required
-            result.put("micronaut.server.port", port);
             result.put("micronaut.server.dual-protocol", dualProtocol);
             result.put("micronaut.server.ssl.port", sslPort);
             if (!restSslView.ciphers().isBlank()) {
@@ -224,11 +226,9 @@ public class RestComponent implements IgniteComponent {
             result.put("micronaut.server.ssl.trust-store.path", "file:" + 
trustStore.path());
             result.put("micronaut.server.ssl.trust-store.password", 
trustStore.password());
             result.put("micronaut.server.ssl.trust-store.type", 
trustStore.type());
-
-            return result;
-        } else {
-            return Map.of("micronaut.server.port", port);
         }
+
+        return result;
     }
 
     private Map<String, Object> authProperties() {
diff --git 
a/modules/rest/src/main/java/org/apache/ignite/internal/rest/authentication/NodeOnlyEndpointsFilter.java
 
b/modules/rest/src/main/java/org/apache/ignite/internal/rest/authentication/NodeOnlyEndpointsFilter.java
new file mode 100644
index 0000000000..47c3ba722a
--- /dev/null
+++ 
b/modules/rest/src/main/java/org/apache/ignite/internal/rest/authentication/NodeOnlyEndpointsFilter.java
@@ -0,0 +1,89 @@
+/*
+ * 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.rest.authentication;
+
+import io.micronaut.context.annotation.Requires;
+import io.micronaut.core.async.publisher.Publishers;
+import io.micronaut.http.HttpRequest;
+import io.micronaut.http.MutableHttpResponse;
+import io.micronaut.http.annotation.Filter;
+import io.micronaut.http.filter.HttpServerFilter;
+import io.micronaut.http.filter.ServerFilterChain;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+import 
org.apache.ignite.internal.cluster.management.ClusterManagementGroupManager;
+import org.apache.ignite.internal.cluster.management.ClusterState;
+import org.apache.ignite.internal.rest.api.Problem;
+import org.apache.ignite.internal.rest.constants.HttpCode;
+import org.apache.ignite.internal.rest.problem.HttpProblemResponse;
+import org.apache.ignite.lang.ErrorGroups.Common;
+import org.apache.ignite.lang.IgniteException;
+import org.reactivestreams.Publisher;
+
+/** Filters out endpoints that are not allowed to be accessed before cluster 
is initialized. */
+@Filter(Filter.MATCH_ALL_PATTERN)
+@Requires(property = "ignite.endpoints.filter-non-initialized", value = 
"true", defaultValue = "false")
+// TODO: https://issues.apache.org/jira/browse/IGNITE-19077
+public class NodeOnlyEndpointsFilter implements HttpServerFilter {
+    private static final String[] ENABLED_ENDPOINTS = {
+            "/management/v1/configuration/node",
+            "/management/v1/cluster/init",
+            "/management/v1/cluster/topology/physical",
+            "/management/v1/node"
+    };
+
+    private final ClusterManagementGroupManager cmgMgr;
+
+    public NodeOnlyEndpointsFilter(ClusterManagementGroupManager cmgMgr) {
+        this.cmgMgr = cmgMgr;
+    }
+
+    private static boolean pathDisabledForNotInitializedCluster(String path) {
+        for (String enabledPath : ENABLED_ENDPOINTS) {
+            if (path.startsWith(enabledPath)) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public Publisher<MutableHttpResponse<?>> doFilter(HttpRequest<?> request, 
ServerFilterChain chain) {
+        try {
+            if (clusterNotInitialized() && 
pathDisabledForNotInitializedCluster(request.getPath())) {
+                return Publishers.just(HttpProblemResponse.from(
+                        Problem.fromHttpCode(HttpCode.CONFLICT)
+                                .detail("Cluster is not initialized. Call 
/management/v1/cluster/init in order to initialize cluster.")
+                                .build()
+                ));
+            }
+        } catch (InterruptedException | ExecutionException | TimeoutException 
e) {
+            throw new IgniteException(Common.UNEXPECTED_ERR, e);
+        }
+
+        return chain.proceed(request);
+    }
+
+    private boolean clusterNotInitialized() throws InterruptedException, 
ExecutionException, TimeoutException {
+        CompletableFuture<ClusterState> stateFuture = cmgMgr.clusterState();
+        return stateFuture == null || stateFuture.get(1, TimeUnit.SECONDS) == 
null;
+    }
+}
+
diff --git 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/rest/ItNotInitializedClusterRestTest.java
 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/rest/ItNotInitializedClusterRestTest.java
index 2acb14435a..c25a484add 100644
--- 
a/modules/runner/src/integrationTest/java/org/apache/ignite/internal/rest/ItNotInitializedClusterRestTest.java
+++ 
b/modules/runner/src/integrationTest/java/org/apache/ignite/internal/rest/ItNotInitializedClusterRestTest.java
@@ -104,10 +104,10 @@ public class ItNotInitializedClusterRestTest extends 
AbstractRestTestBase {
         // Expect cluster configuration is not available
         Problem problem = objectMapper.readValue(response.body(), 
Problem.class);
         assertAll(
-                () -> assertThat(problem.status(), is(404)),
-                () -> assertThat(problem.title(), is("Not Found")),
+                () -> assertThat(problem.status(), is(409)),
+                () -> assertThat(problem.title(), is("Conflict")),
                 () -> assertThat(problem.detail(),
-                        is("Cluster not initialized. Call 
/management/v1/cluster/init in order to initialize cluster"))
+                        is("Cluster is not initialized. Call 
/management/v1/cluster/init in order to initialize cluster."))
         );
     }
 
@@ -123,10 +123,10 @@ public class ItNotInitializedClusterRestTest extends 
AbstractRestTestBase {
         // Expect cluster configuration could not be updated
         Problem problem = objectMapper.readValue(response.body(), 
Problem.class);
         assertAll(
-                () -> assertThat(problem.status(), is(404)),
-                () -> assertThat(problem.title(), is("Not Found")),
+                () -> assertThat(problem.status(), is(409)),
+                () -> assertThat(problem.title(), is("Conflict")),
                 () -> assertThat(problem.detail(),
-                        is("Cluster not initialized. Call 
/management/v1/cluster/init in order to initialize cluster"))
+                        is("Cluster is not initialized. Call 
/management/v1/cluster/init in order to initialize cluster."))
         );
     }
 
@@ -139,10 +139,10 @@ public class ItNotInitializedClusterRestTest extends 
AbstractRestTestBase {
         // Then
         Problem problem = objectMapper.readValue(response.body(), 
Problem.class);
         assertAll(
-                () -> assertThat(problem.status(), is(404)),
-                () -> assertThat(problem.title(), is("Not Found")),
+                () -> assertThat(problem.status(), is(409)),
+                () -> assertThat(problem.title(), is("Conflict")),
                 () -> assertThat(problem.detail(),
-                        is("Cluster not initialized. Call 
/management/v1/cluster/init in order to initialize cluster"))
+                        is("Cluster is not initialized. Call 
/management/v1/cluster/init in order to initialize cluster."))
         );
     }
 
@@ -188,10 +188,10 @@ public class ItNotInitializedClusterRestTest extends 
AbstractRestTestBase {
         // Then
         Problem problem = objectMapper.readValue(response.body(), 
Problem.class);
         assertAll(
-                () -> assertThat(problem.status(), is(404)),
-                () -> assertThat(problem.title(), is("Not Found")),
+                () -> assertThat(problem.status(), is(409)),
+                () -> assertThat(problem.title(), is("Conflict")),
                 () -> assertThat(problem.detail(),
-                        is("Cluster not initialized. Call 
/management/v1/cluster/init in order to initialize cluster"))
+                        is("Cluster is not initialized. Call 
/management/v1/cluster/init in order to initialize cluster."))
         );
     }
 


Reply via email to