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

adoroszlai pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git


The following commit(s) were added to refs/heads/master by this push:
     new 175e2934fe1 HDDS-7957. Deprecate multi-char short options (#10494)
175e2934fe1 is described below

commit 175e2934fe1b92d250f6c59f9bf5106a1d6559f4
Author: hani-fouladgar <[email protected]>
AuthorDate: Sun Jun 14 02:09:16 2026 -0500

    HDDS-7957. Deprecate multi-char short options (#10494)
---
 .../hadoop/hdds/cli/DeprecatedCliOption.java       | 78 ++++++++++++++++++
 .../org/apache/hadoop/hdds/cli/GenericCli.java     | 33 +++++++-
 .../hdds/cli/TestGenericCliConfiguration.java      | 78 ++++++++++++++++++
 .../org/apache/hadoop/hdds/scm/cli/ScmOption.java  | 20 ++++-
 .../scm/cli/pipeline/FilterPipelineOptions.java    | 20 ++++-
 .../scm/cli/pipeline/ListPipelinesSubcommand.java  | 24 +++++-
 .../ozone/admin/om/DecommissionOMSubcommand.java   | 78 +++++++++++++-----
 .../hadoop/ozone/admin/om/PrepareSubCommand.java   | 92 ++++++++++++++++++----
 .../ozone/admin/scm/DecommissionScmSubcommand.java | 33 ++++++--
 .../hadoop/hdds/cli/TestDeprecatedCliOption.java   | 77 ++++++++++++++++++
 .../java/org/apache/hadoop/ozone/shell/Shell.java  |  2 +
 .../apache/hadoop/ozone/shell/acl/AclOption.java   | 47 +++++++----
 12 files changed, 510 insertions(+), 72 deletions(-)

diff --git 
a/hadoop-hdds/cli-common/src/main/java/org/apache/hadoop/hdds/cli/DeprecatedCliOption.java
 
b/hadoop-hdds/cli-common/src/main/java/org/apache/hadoop/hdds/cli/DeprecatedCliOption.java
new file mode 100644
index 00000000000..d455c29ece7
--- /dev/null
+++ 
b/hadoop-hdds/cli-common/src/main/java/org/apache/hadoop/hdds/cli/DeprecatedCliOption.java
@@ -0,0 +1,78 @@
+/*
+ * 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.hadoop.hdds.cli;
+
+import java.io.PrintWriter;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import picocli.CommandLine;
+
+/**
+ * Emits warnings when deprecated multi-character short CLI options are used.
+ */
+public final class DeprecatedCliOption {
+
+  private static final Map<String, String> DEPRECATED_OPTIONS = 
buildDeprecatedOptions();
+
+  private DeprecatedCliOption() {
+    // no instances
+  }
+
+  private static Map<String, String> buildDeprecatedOptions() {
+    Map<String, String> options = new LinkedHashMap<>();
+    options.put("-conf", "--conf");
+    options.put("-id", "--service-id");
+    options.put("-host", "--service-host");
+    options.put("-nodeid", "--nodeid");
+    options.put("-hostname", "--node-host-address");
+    options.put("-al", "--acls");
+    options.put("-ffc", "--filter-by-factor");
+    options.put("-fst", "--filter-by-state");
+    options.put("-tawt", "--transaction-apply-wait-timeout");
+    options.put("-tact", "--transaction-apply-check-interval");
+    options.put("-pct", "--prepare-check-interval");
+    options.put("-pt", "--prepare-timeout");
+    return options;
+  }
+
+  /**
+   * Print a warning to stderr for each deprecated option present on the 
command line.
+   */
+  public static void warnIfMatched(CommandLine.ParseResult parseResult) {
+    if (parseResult == null) {
+      return;
+    }
+
+    for (CommandLine cli : parseResult.asCommandLineList()) {
+      CommandLine.ParseResult subcommandResult = cli.getParseResult();
+      if (subcommandResult.matchedOptions().isEmpty()) {
+        continue;
+      }
+      for (Map.Entry<String, String> entry : DEPRECATED_OPTIONS.entrySet()) {
+        if (subcommandResult.hasMatchedOption(entry.getKey())) {
+          warn(cli.getErr(), entry.getKey(), entry.getValue());
+        }
+      }
+    }
+  }
+
+  private static void warn(PrintWriter err, String deprecated, String 
replacement) {
+    err.printf("WARNING: Option '%s' is deprecated. Use '%s' instead.%n",
+        deprecated, replacement);
+  }
+}
diff --git 
a/hadoop-hdds/cli-common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java
 
b/hadoop-hdds/cli-common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java
index b12330ab2d0..6fcdd686219 100644
--- 
a/hadoop-hdds/cli-common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java
+++ 
b/hadoop-hdds/cli-common/src/main/java/org/apache/hadoop/hdds/cli/GenericCli.java
@@ -46,6 +46,10 @@ public abstract class GenericCli implements 
GenericParentCommand {
 
   private UserGroupInformation user;
 
+  private String configurationPath;
+  private String deprecatedConfigurationPath;
+  private boolean isConfigurationPathAdded = false;
+
   @Option(names = {"--verbose"},
       scope = CommandLine.ScopeType.INHERIT,
       description = "More verbose output. Show the stack trace of the errors.")
@@ -56,9 +60,25 @@ public void setConfigurationOverrides(Map<String, String> 
configOverrides) {
     configOverrides.forEach(config::set);
   }
 
-  @Option(names = {"-conf"})
+  @Option(names = {"--conf"},
+      description = "Path to custom configuration file.")
   public void setConfigurationPath(String configPath) {
-    config.addResource(new Path(configPath));
+    configurationPath = configPath;
+  }
+
+  /** For backward compatibility. */
+  @Option(names = {"-conf"}, hidden = true)
+  @Deprecated
+  @SuppressWarnings("DeprecatedIsStillUsed")
+  public void setDeprecatedConfigurationPath(String configPath) {
+    deprecatedConfigurationPath = configPath;
+  }
+
+  private String getConfigurationPath() {
+    if (configurationPath != null) {
+      return configurationPath;
+    }
+    return deprecatedConfigurationPath;
   }
 
   public GenericCli() {
@@ -71,6 +91,10 @@ public GenericCli(CommandLine.IFactory factory) {
       printError(ex);
       return EXECUTION_ERROR_EXIT_CODE;
     });
+    cmd.setExecutionStrategy(parseResult -> {
+      DeprecatedCliOption.warnIfMatched(parseResult);
+      return new CommandLine.RunLast().execute(parseResult);
+    });
 
     ExtensibleParentCommand.addSubcommands(cmd);
   }
@@ -111,6 +135,11 @@ public void printError(Throwable error) {
 
   @Override
   public OzoneConfiguration getOzoneConf() {
+    String path = getConfigurationPath();
+    if (path != null && !isConfigurationPathAdded) {
+      config.addResource(new Path(path));
+      isConfigurationPathAdded = true;
+    }
     return config;
   }
 
diff --git 
a/hadoop-hdds/cli-common/src/test/java/org/apache/hadoop/hdds/cli/TestGenericCliConfiguration.java
 
b/hadoop-hdds/cli-common/src/test/java/org/apache/hadoop/hdds/cli/TestGenericCliConfiguration.java
new file mode 100644
index 00000000000..5334d4b86c3
--- /dev/null
+++ 
b/hadoop-hdds/cli-common/src/test/java/org/apache/hadoop/hdds/cli/TestGenericCliConfiguration.java
@@ -0,0 +1,78 @@
+/*
+ * 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.hadoop.hdds.cli;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import org.junit.jupiter.api.Test;
+
+/**
+ * Tests for {@link GenericCli} configuration option handling.
+ */
+public class TestGenericCliConfiguration {
+
+  private static final class TestGenericCli extends GenericCli {
+  }
+
+  @Test
+  public void nonDeprecatedConfWinsWhenBothAreProvided() throws IOException {
+    Path deprecatedConf = writeConf("deprecated");
+    Path preferredConf = writeConf("preferred");
+
+    TestGenericCli cli = new TestGenericCli();
+    cli.getCmd().parseArgs("-conf", deprecatedConf.toString(), "--conf",
+        preferredConf.toString());
+
+    assertThat(cli.getOzoneConf().get("test.key")).isEqualTo("preferred");
+  }
+
+  @Test
+  public void nonDeprecatedConfWinsRegardlessOfOrder() throws IOException {
+    Path deprecatedConf = writeConf("deprecated");
+    Path preferredConf = writeConf("preferred");
+
+    TestGenericCli cli = new TestGenericCli();
+    cli.getCmd().parseArgs("--conf", preferredConf.toString(), "-conf",
+        deprecatedConf.toString());
+
+    assertThat(cli.getOzoneConf().get("test.key")).isEqualTo("preferred");
+  }
+
+  @Test
+  public void deprecatedConfIsUsedWhenNonDeprecatedIsAbsent() throws 
IOException {
+    Path deprecatedConf = writeConf("deprecated");
+
+    TestGenericCli cli = new TestGenericCli();
+    cli.getCmd().parseArgs("-conf", deprecatedConf.toString());
+
+    assertThat(cli.getOzoneConf().get("test.key")).isEqualTo("deprecated");
+  }
+
+  private static Path writeConf(String value) throws IOException {
+    Path conf = Files.createTempFile("ozone-conf-", ".xml");
+    Files.write(conf,
+        ("<configuration><property><name>test.key</name><value>" + value
+            + 
"</value></property></configuration>").getBytes(StandardCharsets.UTF_8));
+    conf.toFile().deleteOnExit();
+    return conf;
+  }
+}
diff --git 
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/ScmOption.java
 
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/ScmOption.java
index f82b2be6c88..acb7a4424b9 100644
--- 
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/ScmOption.java
+++ 
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/ScmOption.java
@@ -42,10 +42,16 @@ public class ScmOption extends AbstractMixin {
       description = "The destination scm (host:port)")
   private String scm;
 
-  @CommandLine.Option(names = {"--service-id", "-id"}, description =
+  @CommandLine.Option(names = {"--service-id"}, description =
       "ServiceId of SCM HA Cluster")
   private String scmServiceId;
 
+  /** For backward compatibility. */
+  @CommandLine.Option(names = {"-id"}, hidden = true)
+  @Deprecated
+  @SuppressWarnings("DeprecatedIsStillUsed")
+  private String deprecatedScmServiceId;
+
   public ScmClient createScmClient() throws IOException {
     OzoneConfiguration conf = getOzoneConf();
     checkAndSetSCMAddressArg(conf);
@@ -70,8 +76,9 @@ private void 
checkAndSetSCMAddressArg(MutableConfigurationSource conf) {
 
     // Use the scm service Id passed from the client.
 
-    if (StringUtils.isNotEmpty(scmServiceId)) {
-      conf.set(ScmConfigKeys.OZONE_SCM_DEFAULT_SERVICE_ID, scmServiceId);
+    String serviceId = getScmServiceId();
+    if (StringUtils.isNotEmpty(serviceId)) {
+      conf.set(ScmConfigKeys.OZONE_SCM_DEFAULT_SERVICE_ID, serviceId);
     } else if (StringUtils.isBlank(HddsUtils.getScmServiceId(conf))) {
       // Scm service id is not passed, and scm service id is not defined in
       // the config, assuming it should be non-HA cluster.
@@ -98,4 +105,11 @@ public SCMSecurityProtocol createScmSecurityClient() {
   public String getScm() {
     return scm;
   }
+
+  public String getScmServiceId() {
+    if (StringUtils.isNotEmpty(scmServiceId)) {
+      return scmServiceId;
+    }
+    return deprecatedScmServiceId;
+  }
 }
diff --git 
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/pipeline/FilterPipelineOptions.java
 
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/pipeline/FilterPipelineOptions.java
index 64e6ad0f390..b30f2c45071 100644
--- 
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/pipeline/FilterPipelineOptions.java
+++ 
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/pipeline/FilterPipelineOptions.java
@@ -45,20 +45,30 @@ public class FilterPipelineOptions {
   private String replication;
 
   @CommandLine.Option(
-      names = {"-ffc", "--filterByFactor", "--filter-by-factor"},
+      names = {"--filterByFactor", "--filter-by-factor"},
       description = "[deprecated] Filter pipelines by factor (e.g. ONE, THREE) 
(implies RATIS replication type)")
   private ReplicationFactor factor;
 
+  /** For backward compatibility. */
+  @CommandLine.Option(
+      names = {"-ffc"},
+      hidden = true
+  )
+  @Deprecated
+  @SuppressWarnings("DeprecatedIsStillUsed")
+  private ReplicationFactor deprecatedFactor;
+
   Optional<Predicate<? super Pipeline>> getReplicationFilter() {
+    ReplicationFactor effectiveFactor = getFactor();
     boolean hasReplication = !Strings.isNullOrEmpty(replication);
-    boolean hasFactor = factor != null;
+    boolean hasFactor = effectiveFactor != null;
     boolean hasReplicationType = !Strings.isNullOrEmpty(replicationType);
 
     if (hasFactor) {
       if (hasReplication) {
         throw new IllegalArgumentException("Factor and replication are 
mutually exclusive");
       }
-      ReplicationConfig replicationConfig = 
RatisReplicationConfig.getInstance(factor.toProto());
+      ReplicationConfig replicationConfig = 
RatisReplicationConfig.getInstance(effectiveFactor.toProto());
       return Optional.of(p -> 
replicationConfig.equals(p.getReplicationConfig()));
     }
 
@@ -81,4 +91,8 @@ Optional<Predicate<? super Pipeline>> getReplicationFilter() {
 
     return Optional.empty();
   }
+
+  private ReplicationFactor getFactor() {
+    return factor != null ? factor : deprecatedFactor;
+  }
 }
diff --git 
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/pipeline/ListPipelinesSubcommand.java
 
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/pipeline/ListPipelinesSubcommand.java
index 53c70a657f4..b1e5ec6d3ae 100644
--- 
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/pipeline/ListPipelinesSubcommand.java
+++ 
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/hdds/scm/cli/pipeline/ListPipelinesSubcommand.java
@@ -44,11 +44,21 @@ public class ListPipelinesSubcommand extends ScmSubcommand {
   private final FilterPipelineOptions filterOptions = new 
FilterPipelineOptions();
 
   @CommandLine.Option(
-      names = {"-s", "--state", "-fst", "--filterByState", 
"--filter-by-state"},
+      names = {"-s", "--state", "--filterByState", "--filter-by-state"},
       description = "Filter listed pipelines by State, eg OPEN, CLOSED",
       defaultValue = "")
   private String state;
 
+  /** For backward compatibility. */
+  @CommandLine.Option(
+      names = {"-fst"},
+      hidden = true,
+      defaultValue = ""
+  )
+  @Deprecated
+  @SuppressWarnings("DeprecatedIsStillUsed")
+  private String deprecatedState;
+
   @CommandLine.Option(
       names = {"--json"},
       defaultValue = "false",
@@ -63,9 +73,10 @@ public void execute(ScmClient scmClient) throws IOException {
     if (replicationFilter.isPresent()) {
       stream = stream.filter(replicationFilter.get());
     }
-    if (!Strings.isNullOrEmpty(state)) {
+    String effectiveState = getState();
+    if (!Strings.isNullOrEmpty(effectiveState)) {
       stream = stream.filter(p -> p.getPipelineState().toString()
-          .compareToIgnoreCase(state) == 0);
+          .compareToIgnoreCase(effectiveState) == 0);
     }
 
     if (json) {
@@ -76,4 +87,11 @@ public void execute(ScmClient scmClient) throws IOException {
       stream.forEach(System.out::println);
     }
   }
+
+  private String getState() {
+    if (!Strings.isNullOrEmpty(state)) {
+      return state;
+    }
+    return deprecatedState;
+  }
 }
diff --git 
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/DecommissionOMSubcommand.java
 
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/DecommissionOMSubcommand.java
index 5e17e1f6f81..1b1a46f6654 100644
--- 
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/DecommissionOMSubcommand.java
+++ 
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/DecommissionOMSubcommand.java
@@ -43,8 +43,8 @@
 @CommandLine.Command(
     name = "decommission",
     customSynopsis = "ozone admin om decommission --service-id=<om-service-id> 
" +
-        "-nodeid=<decommission-om-node-id> " +
-        "-hostname=<decommission-om-node-address> [options]",
+        "--nodeid=<decommission-om-node-id> " +
+        "--node-host-address=<decommission-om-node-address> [options]",
     description = "Decommission an OzoneManager. Ensure that the node being " +
         "decommissioned is shutdown first." +
         "%nNote - Add the node to be decommissioned to " +
@@ -67,15 +67,11 @@ public class DecommissionOMSubcommand implements 
Callable<Void> {
   @CommandLine.Mixin
   private OmAddressOptions.MandatoryServiceIdMixin omServiceOption;
 
-  @CommandLine.Option(names = {"-nodeid", "--nodeid"},
-      description = "NodeID of the OM to be decommissioned.",
-      required = true)
-  private String decommNodeId;
+  @CommandLine.ArgGroup(multiplicity = "1")
+  private NodeIdOptions nodeIdOptions;
 
-  @CommandLine.Option(names = {"-hostname", "--node-host-address"},
-      description = "Host name/address of the OM to be decommissioned.",
-      required = true)
-  private String hostname;
+  @CommandLine.ArgGroup(multiplicity = "1")
+  private HostnameOptions hostnameOptions;
 
   private InetAddress hostInetAddress;
 
@@ -106,14 +102,14 @@ public Void call() throws IOException {
              OMAdminProtocolClientSideImpl.createProxyForOMHA(ozoneConf, user,
                  omServiceOption.getServiceID())) {
       OMNodeDetails decommNodeDetails = new OMNodeDetails.Builder()
-          .setOMNodeId(decommNodeId)
+          .setOMNodeId(nodeIdOptions.getNodeId())
           .setHostAddress(hostInetAddress.getHostAddress())
           .build();
       omAdminProtocolClient.decommission(decommNodeDetails);
 
-      System.out.println("Successfully decommissioned OM " + decommNodeId);
+      System.out.println("Successfully decommissioned OM " + 
nodeIdOptions.getNodeId());
     } catch (IOException e) {
-      System.out.println("Failed to decommission OM " + decommNodeId);
+      System.out.println("Failed to decommission OM " + 
nodeIdOptions.getNodeId());
       throw e;
     }
     return null;
@@ -125,19 +121,19 @@ public Void call() throws IOException {
    */
   private void verifyNodeIdAndHostAddress() throws IOException {
     String rpcAddrKey = ConfUtils.addKeySuffixes(OZONE_OM_ADDRESS_KEY,
-        omServiceOption.getServiceID(), decommNodeId);
+        omServiceOption.getServiceID(), nodeIdOptions.getNodeId());
     String rpcAddrStr = OmUtils.getOmRpcAddress(ozoneConf, rpcAddrKey);
     if (rpcAddrStr == null || rpcAddrStr.isEmpty()) {
-      throw new IOException("There is no OM corresponding to " + decommNodeId
+      throw new IOException("There is no OM corresponding to " + 
nodeIdOptions.getNodeId()
           + "in the configuration.");
     }
 
-    hostInetAddress = InetAddress.getByName(hostname);
+    hostInetAddress = InetAddress.getByName(hostnameOptions.getHostname());
     InetAddress rpcAddressFromConfig = InetAddress.getByName(
         rpcAddrStr.split(":")[0]);
 
     if (!hostInetAddress.equals(rpcAddressFromConfig)) {
-      throw new IOException("OM " + decommNodeId + "'s host address in " +
+      throw new IOException("OM " + nodeIdOptions.getNodeId() + "'s host 
address in " +
           "config - " + rpcAddressFromConfig.getHostAddress() + " does not " +
           "match the provided host address " + hostInetAddress);
     }
@@ -153,9 +149,9 @@ private void verifyConfigUpdatedOnAllOMs() throws 
IOException {
         OZONE_OM_DECOMMISSIONED_NODES_KEY, omServiceOption.getServiceID());
     Collection<String> decommNodes =
         OmUtils.getDecommissionedNodeIds(ozoneConf, decommNodesKey);
-    if (!decommNodes.contains(decommNodeId)) {
+    if (!decommNodes.contains(nodeIdOptions.getNodeId())) {
       throw new IOException("Please add the to be decommissioned OM "
-          + decommNodeId + " to the " + decommNodesKey + " config in " +
+          + nodeIdOptions.getNodeId() + " to the " + decommNodesKey + " config 
in " +
           "ozone-site.xml of all nodes.");
     }
 
@@ -165,7 +161,7 @@ private void verifyConfigUpdatedOnAllOMs() throws 
IOException {
     List<OMNodeDetails> activeOMNodeDetails = OmUtils.getAllOMHAAddresses(
         ozoneConf, omServiceOption.getServiceID(), false);
     if (activeOMNodeDetails.isEmpty()) {
-      throw new IOException("Cannot decommission OM " + decommNodeId + " as " +
+      throw new IOException("Cannot decommission OM " + 
nodeIdOptions.getNodeId() + " as " +
           "it is the only node in the ring.");
     }
 
@@ -194,7 +190,7 @@ private boolean checkOMConfig(OMNodeDetails omNodeDetails)
                  user, omNodeDetails)) {
       OMConfiguration omConfig = omAdminProtocolClient.getOMConfiguration();
       OMNodeDetails decommNodeDetails = omConfig
-          .getDecommissionedNodesInNewConf().get(decommNodeId);
+          .getDecommissionedNodesInNewConf().get(nodeIdOptions.getNodeId());
       if (decommNodeDetails == null) {
         return false;
       }
@@ -205,4 +201,44 @@ private boolean checkOMConfig(OMNodeDetails omNodeDetails)
     }
     return true;
   }
+
+  /** Options for OM node ID. */
+  static class NodeIdOptions {
+    @CommandLine.Option(names = {"--nodeid"},
+        description = "NodeID of the OM to be decommissioned.",
+        required = true)
+    private String nodeId;
+
+    /** For backward compatibility. */
+    @CommandLine.Option(names = {"-nodeid"},
+        hidden = true,
+        required = true)
+    @Deprecated
+    @SuppressWarnings("DeprecatedIsStillUsed")
+    private String deprecatedNodeId;
+
+    String getNodeId() {
+      return nodeId != null ? nodeId : deprecatedNodeId;
+    }
+  }
+
+  /** Options for OM host name/address. */
+  static class HostnameOptions {
+    @CommandLine.Option(names = {"--node-host-address"},
+        description = "Host name/address of the OM to be decommissioned.",
+        required = true)
+    private String hostname;
+
+    /** For backward compatibility. */
+    @CommandLine.Option(names = {"-hostname"},
+        hidden = true,
+        required = true)
+    @Deprecated
+    @SuppressWarnings("DeprecatedIsStillUsed")
+    private String deprecatedHostname;
+
+    String getHostname() {
+      return hostname != null ? hostname : deprecatedHostname;
+    }
+  }
 }
diff --git 
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/PrepareSubCommand.java
 
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/PrepareSubCommand.java
index a0eabd4b7d1..4dad5f979e7 100644
--- 
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/PrepareSubCommand.java
+++ 
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/om/PrepareSubCommand.java
@@ -57,39 +57,71 @@ public class PrepareSubCommand implements Callable<Void> {
   private OmAddressOptions.MandatoryServiceIdMixin omServiceOption;
 
   @CommandLine.Option(
-      names = {"-tawt", "--transaction-apply-wait-timeout"},
+      names = {"--transaction-apply-wait-timeout"},
       description = "Max time in SECONDS to wait for all transactions before" +
           "the prepare request to be applied to the OM DB.",
-      defaultValue = "120",
       hidden = true
   )
-  private long txnApplyWaitTimeSeconds;
+  private Long txnApplyWaitTimeSeconds;
 
+  /** For backward compatibility. */
   @CommandLine.Option(
-      names = {"-tact", "--transaction-apply-check-interval"},
+      names = {"-tawt"},
+      hidden = true
+  )
+  @Deprecated
+  @SuppressWarnings("DeprecatedIsStillUsed")
+  private Long deprecatedTxnApplyWaitTimeSeconds;
+
+  @CommandLine.Option(
+      names = {"--transaction-apply-check-interval"},
       description = "Time in SECONDS to wait between successive checks for " +
           "all transactions to be applied to the OM DB.",
-      defaultValue = "5",
       hidden = true
   )
-  private long txnApplyCheckIntervalSeconds;
+  private Long txnApplyCheckIntervalSeconds;
+
+  /** For backward compatibility. */
+  @CommandLine.Option(
+      names = {"-tact"},
+      hidden = true
+  )
+  @Deprecated
+  @SuppressWarnings("DeprecatedIsStillUsed")
+  private Long deprecatedTxnApplyCheckIntervalSeconds;
 
   @CommandLine.Option(
-      names = {"-pct", "--prepare-check-interval"},
+      names = {"--prepare-check-interval"},
       description = "Time in SECONDS to wait between successive checks for OM" 
+
           " preparation.",
-      defaultValue = "10",
       hidden = true
   )
-  private long prepareCheckInterval;
+  private Long prepareCheckInterval;
 
+  /** For backward compatibility. */
   @CommandLine.Option(
-      names = {"-pt", "--prepare-timeout"},
+      names = {"-pct"},
+      hidden = true
+  )
+  @Deprecated
+  @SuppressWarnings("DeprecatedIsStillUsed")
+  private Long deprecatedPrepareCheckInterval;
+
+  @CommandLine.Option(
+      names = {"--prepare-timeout"},
       description = "Max time in SECONDS to wait for all OMs to be prepared",
-      defaultValue = "300",
       hidden = true
   )
-  private long prepareTimeOut;
+  private Long prepareTimeOut;
+
+  /** For backward compatibility. */
+  @CommandLine.Option(
+      names = {"-pt"},
+      hidden = true
+  )
+  @Deprecated
+  @SuppressWarnings("DeprecatedIsStillUsed")
+  private Long deprecatedPrepareTimeOut;
 
   @Override
   public Void call() throws Exception {
@@ -100,8 +132,8 @@ public Void call() throws Exception {
   }
 
   private void execute(OzoneManagerProtocol client) throws Exception {
-    long prepareTxnId = client.prepareOzoneManager(txnApplyWaitTimeSeconds,
-        txnApplyCheckIntervalSeconds);
+    long prepareTxnId = 
client.prepareOzoneManager(getTxnApplyWaitTimeSeconds(),
+        getTxnApplyCheckIntervalSeconds());
     System.out.println("Ozone Manager Prepare Request successfully returned " +
         "with Transaction Id : [" + prepareTxnId + "].");
 
@@ -109,8 +141,8 @@ private void execute(OzoneManagerProtocol client) throws 
Exception {
     Set<String> omHosts = getOmHostsFromConfig(
         parent.getParent().getOzoneConf(), omServiceOption.getServiceID());
     omHosts.forEach(h -> omPreparedStatusMap.put(h, false));
-    Duration pTimeout = Duration.of(prepareTimeOut, ChronoUnit.SECONDS);
-    Duration pInterval = Duration.of(prepareCheckInterval, ChronoUnit.SECONDS);
+    Duration pTimeout = Duration.of(getPrepareTimeOut(), ChronoUnit.SECONDS);
+    Duration pInterval = Duration.of(getPrepareCheckInterval(), 
ChronoUnit.SECONDS);
 
     System.out.println();
     System.out.println("Checking individual OM instances for prepare request " 
+
@@ -143,7 +175,7 @@ private void execute(OzoneManagerProtocol client) throws 
Exception {
         }
       }
       if (currentNumPreparedOms < expectedNumPreparedOms) {
-        System.out.println("Waiting for " + prepareCheckInterval +
+        System.out.println("Waiting for " + getPrepareCheckInterval() +
             " seconds before retrying...");
         Thread.sleep(pInterval.toMillis());
       }
@@ -169,4 +201,30 @@ private void execute(OzoneManagerProtocol client) throws 
Exception {
     }
   }
 
+  private long getTxnApplyWaitTimeSeconds() {
+    return resolveOption(txnApplyWaitTimeSeconds, 
deprecatedTxnApplyWaitTimeSeconds, 120L);
+  }
+
+  private long getTxnApplyCheckIntervalSeconds() {
+    return resolveOption(txnApplyCheckIntervalSeconds, 
deprecatedTxnApplyCheckIntervalSeconds, 5L);
+  }
+
+  private long getPrepareCheckInterval() {
+    return resolveOption(prepareCheckInterval, deprecatedPrepareCheckInterval, 
10L);
+  }
+
+  private long getPrepareTimeOut() {
+    return resolveOption(prepareTimeOut, deprecatedPrepareTimeOut, 300L);
+  }
+
+  private static long resolveOption(Long value, Long deprecatedValue, long 
defaultValue) {
+    if (value != null) {
+      return value;
+    }
+    if (deprecatedValue != null) {
+      return deprecatedValue;
+    }
+    return defaultValue;
+  }
+
 }
diff --git 
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/scm/DecommissionScmSubcommand.java
 
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/scm/DecommissionScmSubcommand.java
index eb09b246ccd..cb0f5634736 100644
--- 
a/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/scm/DecommissionScmSubcommand.java
+++ 
b/hadoop-ozone/cli-admin/src/main/java/org/apache/hadoop/ozone/admin/scm/DecommissionScmSubcommand.java
@@ -39,23 +39,42 @@ public class DecommissionScmSubcommand extends 
ScmSubcommand {
   @CommandLine.ParentCommand
   private ScmAdmin parent;
 
-  @CommandLine.Option(names = {"-nodeid", "--nodeid"},
-      description = "NodeID of the SCM to be decommissioned.",
-      required = true)
-  private String nodeId;
+  @CommandLine.ArgGroup(multiplicity = "1")
+  private NodeIdOptions nodeIdOptions;
 
   @Override
   public void execute(ScmClient scmClient) throws IOException {
-    DecommissionScmResponseProto response = scmClient.decommissionScm(nodeId);
+    DecommissionScmResponseProto response = scmClient.decommissionScm(
+        nodeIdOptions.getNodeId());
     if (!response.getSuccess()) {
-      String errorMsg = "Error decommissioning Scm " + nodeId;
+      String errorMsg = "Error decommissioning Scm " + 
nodeIdOptions.getNodeId();
       if (response.hasErrorMsg()) {
         errorMsg = errorMsg + ", " + response.getErrorMsg();
       }
       // Throwing exception to create non-zero exit code in case of failure.
       throw new IOException(errorMsg);
     } else {
-      System.out.println("Decommissioned Scm " + nodeId);
+      System.out.println("Decommissioned Scm " + nodeIdOptions.getNodeId());
+    }
+  }
+
+  /** Options for SCM node ID. */
+  static class NodeIdOptions {
+    @CommandLine.Option(names = {"--nodeid"},
+        description = "NodeID of the SCM to be decommissioned.",
+        required = true)
+    private String nodeId;
+
+    /** For backward compatibility. */
+    @CommandLine.Option(names = {"-nodeid"},
+        hidden = true,
+        required = true)
+    @Deprecated
+    @SuppressWarnings("DeprecatedIsStillUsed")
+    private String deprecatedNodeId;
+
+    String getNodeId() {
+      return nodeId != null ? nodeId : deprecatedNodeId;
     }
   }
 }
diff --git 
a/hadoop-ozone/cli-admin/src/test/java/org/apache/hadoop/hdds/cli/TestDeprecatedCliOption.java
 
b/hadoop-ozone/cli-admin/src/test/java/org/apache/hadoop/hdds/cli/TestDeprecatedCliOption.java
new file mode 100644
index 00000000000..85e00cf8f46
--- /dev/null
+++ 
b/hadoop-ozone/cli-admin/src/test/java/org/apache/hadoop/hdds/cli/TestDeprecatedCliOption.java
@@ -0,0 +1,77 @@
+/*
+ * 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.hadoop.hdds.cli;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import org.apache.hadoop.hdds.scm.cli.pipeline.ListPipelinesSubcommand;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import picocli.CommandLine;
+
+/**
+ * Tests for deprecated CLI option warnings.
+ */
+public class TestDeprecatedCliOption {
+  private StringWriter err;
+
+  @BeforeEach
+  public void setup() {
+    err = new StringWriter();
+  }
+
+  private CommandLine createCommandLine(Object command) {
+    CommandLine cli = new CommandLine(command);
+    cli.setErr(new PrintWriter(err, true));
+    cli.setExecutionStrategy(parseResult -> {
+      DeprecatedCliOption.warnIfMatched(parseResult);
+      return CommandLine.ExitCode.OK;
+    });
+    return cli;
+  }
+
+  @Test
+  public void warnsForDeprecatedOption() {
+    createCommandLine(new ListPipelinesSubcommand())
+        .execute("-ffc", "THREE");
+
+    assertThat(err.toString())
+        .contains("WARNING: Option '-ffc' is deprecated")
+        .contains("--filter-by-factor");
+  }
+
+  @Test
+  public void warnsForMultipleDeprecatedOptions() {
+    createCommandLine(new ListPipelinesSubcommand())
+        .execute("-ffc", "THREE", "-fst", "OPEN");
+
+    assertThat(err.toString())
+        .contains("WARNING: Option '-ffc' is deprecated")
+        .contains("WARNING: Option '-fst' is deprecated");
+  }
+
+  @Test
+  public void doesNotWarnForLongOption() {
+    createCommandLine(new ListPipelinesSubcommand())
+        .execute("--filter-by-factor", "THREE");
+
+    assertThat(err.toString()).isEmpty();
+  }
+}
diff --git 
a/hadoop-ozone/cli-shell/src/main/java/org/apache/hadoop/ozone/shell/Shell.java 
b/hadoop-ozone/cli-shell/src/main/java/org/apache/hadoop/ozone/shell/Shell.java
index 5106497a8d1..267bf4eedba 100644
--- 
a/hadoop-ozone/cli-shell/src/main/java/org/apache/hadoop/ozone/shell/Shell.java
+++ 
b/hadoop-ozone/cli-shell/src/main/java/org/apache/hadoop/ozone/shell/Shell.java
@@ -19,6 +19,7 @@
 
 import java.util.Collections;
 import java.util.List;
+import org.apache.hadoop.hdds.cli.DeprecatedCliOption;
 import org.apache.hadoop.hdds.cli.GenericCli;
 import org.apache.hadoop.hdds.tracing.TracingUtil;
 import org.apache.hadoop.ozone.om.exceptions.OMException;
@@ -89,6 +90,7 @@ protected List<String> interactiveWelcomeLines() {
   }
 
   private int execute(CommandLine.ParseResult parseResult) {
+    DeprecatedCliOption.warnIfMatched(parseResult);
     name = spec.name();
 
     if (parseResult.hasMatchedOption("--interactive") || 
parseResult.hasMatchedOption("--execute")) {
diff --git 
a/hadoop-ozone/cli-shell/src/main/java/org/apache/hadoop/ozone/shell/acl/AclOption.java
 
b/hadoop-ozone/cli-shell/src/main/java/org/apache/hadoop/ozone/shell/acl/AclOption.java
index 5986c114ede..e15980ff805 100644
--- 
a/hadoop-ozone/cli-shell/src/main/java/org/apache/hadoop/ozone/shell/acl/AclOption.java
+++ 
b/hadoop-ozone/cli-shell/src/main/java/org/apache/hadoop/ozone/shell/acl/AclOption.java
@@ -31,24 +31,39 @@
  */
 public class AclOption implements CommandLine.ITypeConverter<OzoneAcl> {
 
-  @CommandLine.Option(names = {"--acls", "--acl", "-al", "-a"}, split = ",",
-      required = true,
-      converter = AclOption.class,
-      description = "Comma separated ACL list:%n" +
-          "Example: user:user2:a OR user:user1:rw,group:hadoop:a%n" +
-          "r = READ, " +
-          "w = WRITE, " +
-          "c = CREATE, " +
-          "d = DELETE, " +
-          "l = LIST, " +
-          "a = ALL, " +
-          "n = NONE, " +
-          "x = READ_ACL, " +
-          "y = WRITE_ACL.")
-  private OzoneAcl[] values;
+  @CommandLine.ArgGroup(multiplicity = "1")
+  private Exclusive exclusive = new Exclusive();
+
+  private static final class Exclusive {
+    @CommandLine.Option(names = {"--acls", "--acl", "-a"}, split = ",",
+        required = true,
+        converter = AclOption.class,
+        description = "Comma separated ACL list:%n" +
+            "Example: user:user2:a OR user:user1:rw,group:hadoop:a%n" +
+            "r = READ, " +
+            "w = WRITE, " +
+            "c = CREATE, " +
+            "d = DELETE, " +
+            "l = LIST, " +
+            "a = ALL, " +
+            "n = NONE, " +
+            "x = READ_ACL, " +
+            "y = WRITE_ACL.")
+        private OzoneAcl[] values;
+
+    /** For backward compatibility. */
+    @CommandLine.Option(names = {"-al"}, split = ",", hidden = true,
+        required = true, converter = AclOption.class)
+    @Deprecated
+    @SuppressWarnings("DeprecatedIsStillUsed")
+    private OzoneAcl[] deprecatedValues;
+  }
 
   private List<OzoneAcl> getAclList() {
-    return ImmutableList.copyOf(values);
+    OzoneAcl[] acls = exclusive.values != null
+        ? exclusive.values
+        : exclusive.deprecatedValues;
+    return ImmutableList.copyOf(acls);
   }
 
   public void addTo(OzoneObj obj, ObjectStore objectStore, PrintWriter out)


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to