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 62c47e04531 IGNITE-26336 Fix node name and node url options (#6510)
62c47e04531 is described below

commit 62c47e04531371fb2498dee52c16fcd071b38596
Author: Vadim Pakhnushev <[email protected]>
AuthorDate: Tue Sep 2 11:53:27 2025 +0300

    IGNITE-26336 Fix node name and node url options (#6510)
---
 .../internal/cli/commands/node/NodeUrlMixin.java   |  13 +-
 .../ignite/internal/cli/commands/MixinTest.java    | 246 +++++++++++++++++++++
 2 files changed, 257 insertions(+), 2 deletions(-)

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 c41208a0eaa..75fe92b7e55 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
@@ -48,13 +48,22 @@ public class NodeUrlMixin {
         /**
          * Node URL option.
          */
-        @Option(names = NODE_URL_OPTION, description = NODE_URL_OPTION_DESC, 
converter = RestEndpointUrlConverter.class)
+        @Option(
+                names = NODE_URL_OPTION,
+                description = NODE_URL_OPTION_DESC,
+                converter = RestEndpointUrlConverter.class,
+                defaultValue = Option.NULL_VALUE
+        )
         private URL nodeUrl;
 
         /**
          * Node name option.
          */
-        @Option(names = {NODE_NAME_OPTION_SHORT, NODE_NAME_OPTION}, 
description = NODE_NAME_OPTION_DESC)
+        @Option(
+                names = {NODE_NAME_OPTION_SHORT, NODE_NAME_OPTION},
+                description = NODE_NAME_OPTION_DESC,
+                defaultValue = Option.NULL_VALUE
+        )
         private String nodeName;
     }
 
diff --git 
a/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/MixinTest.java
 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/MixinTest.java
new file mode 100644
index 00000000000..b89ef3ac0b9
--- /dev/null
+++ 
b/modules/cli/src/test/java/org/apache/ignite/internal/cli/commands/MixinTest.java
@@ -0,0 +1,246 @@
+/*
+ * 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.commands;
+
+import static 
org.apache.ignite.internal.cli.commands.Options.Constants.CLUSTER_CONFIG_OPTION;
+import static 
org.apache.ignite.internal.cli.commands.Options.Constants.CLUSTER_NAME_OPTION;
+import static 
org.apache.ignite.internal.cli.commands.Options.Constants.CLUSTER_URL_OPTION;
+import static 
org.apache.ignite.internal.cli.commands.Options.Constants.NODE_NAME_OPTION;
+import static 
org.apache.ignite.internal.cli.commands.Options.Constants.NODE_URL_OPTION;
+import static 
org.apache.ignite.internal.cli.commands.Options.Constants.PASSWORD_OPTION;
+import static 
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_CMG_NODES_OPTION;
+import static 
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_METASTORAGE_REPLICATION_OPTION;
+import static 
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_NODE_NAMES_OPTION;
+import static 
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_PARTITION_GLOBAL_OPTION;
+import static 
org.apache.ignite.internal.cli.commands.Options.Constants.RECOVERY_PARTITION_LOCAL_OPTION;
+import static 
org.apache.ignite.internal.cli.commands.Options.Constants.USERNAME_OPTION;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.empty;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.nullValue;
+
+import io.micronaut.configuration.picocli.MicronautFactory;
+import io.micronaut.context.ApplicationContext;
+import io.micronaut.context.annotation.Bean;
+import io.micronaut.context.annotation.Replaces;
+import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
+import jakarta.inject.Inject;
+import java.util.Optional;
+import java.util.Set;
+import org.apache.ignite.internal.cli.commands.cluster.ClusterUrlMixin;
+import org.apache.ignite.internal.cli.commands.cluster.init.ClusterInitOptions;
+import org.apache.ignite.internal.cli.commands.connect.ConnectOptions;
+import org.apache.ignite.internal.cli.commands.node.NodeUrlMixin;
+import 
org.apache.ignite.internal.cli.commands.recovery.cluster.reset.ResetClusterMixin;
+import 
org.apache.ignite.internal.cli.commands.recovery.partitions.states.PartitionStatesMixin;
+import org.apache.ignite.internal.cli.core.repl.registry.NodeNameRegistry;
+import org.junit.jupiter.api.Test;
+import picocli.CommandLine;
+import picocli.CommandLine.ArgGroup;
+import picocli.CommandLine.Command;
+import picocli.CommandLine.Mixin;
+
+@SuppressWarnings("unused")
+@MicronautTest
+class MixinTest {
+    @Inject
+    private ApplicationContext context;
+
+    @Test
+    void doubleInvocationNodeName() {
+        NodeCommand command = new NodeCommand();
+        CommandLine commandLine = new CommandLine(command, new 
MicronautFactory(context));
+
+        String nodeName = "test";
+
+        commandLine.parseArgs(NODE_NAME_OPTION, nodeName);
+        assertThat(command.nodeUrl.getNodeUrl(), is("http://"; + nodeName));
+
+        commandLine.parseArgs();
+        assertThat(command.nodeUrl.getNodeUrl(), is(nullValue()));
+    }
+
+    @Test
+    void doubleInvocationNodeUrl() {
+        NodeCommand command = new NodeCommand();
+        CommandLine commandLine = new CommandLine(command, new 
MicronautFactory(context));
+
+        String nodeUrl = "http://test";;
+
+        commandLine.parseArgs(NODE_URL_OPTION, nodeUrl);
+        assertThat(command.nodeUrl.getNodeUrl(), is(nodeUrl));
+
+        commandLine.parseArgs();
+        assertThat(command.nodeUrl.getNodeUrl(), is(nullValue()));
+    }
+
+    @Test
+    void doubleInvocationClusterUrl() {
+        ClusterCommand command = new ClusterCommand();
+        CommandLine commandLine = new CommandLine(command, new 
MicronautFactory(context));
+
+        String clusterUrl = "http://test";;
+
+        commandLine.parseArgs(CLUSTER_URL_OPTION, clusterUrl);
+        assertThat(command.clusterUrl.getClusterUrl(), is(clusterUrl));
+
+        commandLine.parseArgs();
+        assertThat(command.clusterUrl.getClusterUrl(), is(nullValue()));
+    }
+
+    @Test
+    void doubleInvocationUnitList() {
+        UnitCommand command = new UnitCommand();
+        CommandLine commandLine = new CommandLine(command, new 
MicronautFactory(context));
+
+        String version = "version";
+
+        commandLine.parseArgs("--version", version, "unitId");
+        
assertThat(command.unitListOptions.toListUnitCallInput(null).version(), 
is(version));
+
+        commandLine.parseArgs("unitId");
+        
assertThat(command.unitListOptions.toListUnitCallInput(null).version(), 
is(nullValue()));
+    }
+
+    @Test
+    void doubleInvocationResetCluster() {
+        ResetCommand command = new ResetCommand();
+        CommandLine commandLine = new CommandLine(command, new 
MicronautFactory(context));
+
+        String version = "version";
+
+        commandLine.parseArgs(RECOVERY_METASTORAGE_REPLICATION_OPTION, "1");
+        assertThat(command.resetCluster.metastorageReplicationFactor(), is(1));
+        assertThat(command.resetCluster.cmgNodeNames(), is(nullValue()));
+
+        commandLine.parseArgs(RECOVERY_CMG_NODES_OPTION, "node");
+        assertThat(command.resetCluster.metastorageReplicationFactor(), 
is(nullValue()));
+        assertThat(command.resetCluster.cmgNodeNames(), contains("node"));
+    }
+
+    @Test
+    void doubleInvocationInit() {
+        InitCommand command = new InitCommand();
+        CommandLine commandLine = new CommandLine(command, new 
MicronautFactory(context));
+
+        String config = "config";
+
+        commandLine.parseArgs(CLUSTER_NAME_OPTION, "name", 
CLUSTER_CONFIG_OPTION, config);
+        assertThat(command.initOptions.clusterConfiguration(), is(config));
+
+        commandLine.parseArgs(CLUSTER_NAME_OPTION, "name");
+        assertThat(command.initOptions.clusterConfiguration(), 
is(nullValue()));
+    }
+
+    @Test
+    void doubleInvocationConnect() {
+        ConnectCommand command = new ConnectCommand();
+        CommandLine commandLine = new CommandLine(command, new 
MicronautFactory(context));
+
+        String username = "username";
+        String password = "password";
+
+        commandLine.parseArgs(USERNAME_OPTION, username, PASSWORD_OPTION, 
password);
+        assertThat(command.connectOptions.username(), is(username));
+        assertThat(command.connectOptions.password(), is(password));
+
+        commandLine.parseArgs();
+        assertThat(command.connectOptions.username(), is(nullValue()));
+        assertThat(command.connectOptions.password(), is(nullValue()));
+    }
+
+    @Test
+    void doubleInvocationPartitionStates() {
+        PartitionStatesCommand command = new PartitionStatesCommand();
+        CommandLine commandLine = new CommandLine(command, new 
MicronautFactory(context));
+
+        String node = "node";
+
+        commandLine.parseArgs(RECOVERY_PARTITION_LOCAL_OPTION, 
RECOVERY_NODE_NAMES_OPTION, "node");
+        assertThat(command.partitionStates.nodeNames(), contains(node));
+        assertThat(command.partitionStates.local(), is(true));
+
+        commandLine.parseArgs(RECOVERY_PARTITION_GLOBAL_OPTION);
+        assertThat(command.partitionStates.nodeNames(), is(empty()));
+        assertThat(command.partitionStates.local(), is(false));
+    }
+
+    @Command
+    private static class NodeCommand {
+        @Mixin
+        private NodeUrlMixin nodeUrl;
+    }
+
+    @Command
+    private static class ClusterCommand {
+        @Mixin
+        private ClusterUrlMixin clusterUrl;
+    }
+
+    @Command
+    private static class UnitCommand {
+        @Mixin
+        private UnitListOptionsMixin unitListOptions;
+    }
+
+    @Command
+    private static class ResetCommand {
+        @Mixin
+        private ResetClusterMixin resetCluster;
+    }
+
+    @Command
+    private static class InitCommand {
+        @Mixin
+        private ClusterInitOptions initOptions;
+    }
+
+    @Command
+    private static class ConnectCommand {
+        @ArgGroup(exclusive = false)
+        private ConnectOptions connectOptions;
+    }
+
+    @Command
+    private static class PartitionStatesCommand {
+        @Mixin
+        private PartitionStatesMixin partitionStates;
+    }
+
+    @Bean
+    @Replaces(NodeNameRegistry.class)
+    public static NodeNameRegistry nodeNameRegistry() {
+        return new NodeNameRegistry() {
+            @Override
+            public Optional<String> nodeUrlByName(String nodeName) {
+                return Optional.of("http://"; + nodeName);
+            }
+
+            @Override
+            public Set<String> names() {
+                return Set.of();
+            }
+
+            @Override
+            public Set<String> urls() {
+                return Set.of();
+            }
+        };
+    }
+}

Reply via email to