diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/diskbalancer/command/HelpCommand.java b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/diskbalancer/command/HelpCommand.java index ec180538a9843..a3b6df61bd784 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/diskbalancer/command/HelpCommand.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/diskbalancer/command/HelpCommand.java @@ -56,6 +56,15 @@ public void execute(CommandLine cmd) throws Exception { Preconditions.checkState(cmd.hasOption(DiskBalancerCLI.HELP)); verifyCommandOptions(DiskBalancerCLI.HELP, cmd); String helpCommand = cmd.getOptionValue(DiskBalancerCLI.HELP); + if (helpCommand == null || helpCommand.isEmpty()) { + // With optionalArg(true), space-separated form "-help " leaves the + // sub-command as a positional arg rather than the option's value. + // Fall back to the first leftover arg so "-help plan" works as expected. + String[] leftoverArgs = cmd.getArgs(); + if (leftoverArgs != null && leftoverArgs.length > 0) { + helpCommand = leftoverArgs[0]; + } + } if (helpCommand == null || helpCommand.isEmpty()) { this.printHelp(); return; diff --git a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/diskbalancer/command/TestDiskBalancerCommand.java b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/diskbalancer/command/TestDiskBalancerCommand.java index 7f9c05a6a721e..e88aac28ab72e 100644 --- a/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/diskbalancer/command/TestDiskBalancerCommand.java +++ b/hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/diskbalancer/command/TestDiskBalancerCommand.java @@ -756,6 +756,33 @@ public void testHelpCommand() throws Exception { runCommand(cmdLine); } + /** + * HDFS-17809: "-help " must display command-specific help text, + * not just the generic usage summary. + */ + @Test + @Timeout(value = 60) + public void testHelpCommandWithSubCommand() throws Exception { + // Each sub-command help should contain its own option/keyword. + String[][] subCommands = { + {PLAN, "plan"}, + {EXECUTE, "execute"}, + {QUERY, "query"}, + {CANCEL, "cancel"}, + {REPORT, "report"}, + }; + for (String[] pair : subCommands) { + String subCmd = pair[0]; + String expectedToken = pair[1]; + String cmdLine = String.format("hdfs diskbalancer -%s %s", HELP, subCmd); + List output = runCommand(cmdLine); + String joined = String.join("\n", output).toLowerCase(); + assertTrue(joined.contains(expectedToken), + "Expected '" + expectedToken + "' in help output for '-help " + + subCmd + "', got:\n" + joined); + } + } + @Test public void testPrintFullPathOfPlan() throws Exception {