This commit is contained in:
Chang-Yu Huang 2025-10-07 17:00:44 -04:00 committed by GitHub
commit 7e0d5d02a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 34 additions and 11 deletions

View File

@ -76,7 +76,7 @@ public class FeatureCommand {
.newArgumentParser("kafka-features")
.defaultHelp(true)
.description("This tool manages feature flags in Kafka.");
MutuallyExclusiveGroup bootstrapGroup = parser.addMutuallyExclusiveGroup().required(true);
MutuallyExclusiveGroup bootstrapGroup = parser.addMutuallyExclusiveGroup();
bootstrapGroup.addArgument("--bootstrap-server")
.help("A comma-separated list of host:port pairs to use for establishing the connection to the Kafka cluster.");
bootstrapGroup.addArgument("--bootstrap-controller")
@ -92,14 +92,27 @@ public class FeatureCommand {
addVersionMappingParser(subparsers);
addFeatureDependenciesParser(subparsers);
Namespace namespace = parser.parseArgsOrFail(args);
Namespace namespace = parser.parseArgs(args);
String command = namespace.getString("command");
if (command.equals("version-mapping")) {
handleVersionMapping(namespace, Feature.PRODUCTION_FEATURES);
return;
} else if (command.equals("feature-dependencies")) {
handleFeatureDependencies(namespace, Feature.PRODUCTION_FEATURES);
return;
}
String configPath = namespace.getString("command_config");
Properties properties = (configPath == null) ? new Properties() : Utils.loadProps(configPath);
CommandLineUtils.initializeBootstrapProperties(properties,
Optional.ofNullable(namespace.getString("bootstrap_server")),
Optional.ofNullable(namespace.getString("bootstrap_controller")));
try {
CommandLineUtils.initializeBootstrapProperties(properties,
Optional.ofNullable(namespace.getString("bootstrap_server")),
Optional.ofNullable(namespace.getString("bootstrap_controller")));
} catch (Exception e) {
// bootstrap_server and bootstrap_controller are in a mutually exclusive group,
// so the exception happens only when both of them are missing
throw new ArgumentParserException(e.getMessage(), parser);
}
try (Admin adminClient = Admin.create(properties)) {
switch (command) {
@ -115,12 +128,6 @@ public class FeatureCommand {
case "disable":
handleDisable(namespace, adminClient);
break;
case "version-mapping":
handleVersionMapping(namespace, Feature.PRODUCTION_FEATURES);
break;
case "feature-dependencies":
handleFeatureDependencies(namespace, Feature.PRODUCTION_FEATURES);
break;
default:
throw new TerseException("Unknown command " + command);
}

View File

@ -459,6 +459,22 @@ public class FeatureCommandTest {
MetadataVersion.MINIMUM_VERSION, MetadataVersion.latestTesting()), exception2.getMessage());
}
@Test
public void testHandleVersionMappingWithoutBootstrap() {
Map.Entry<String, String> output = ToolsTestUtils.grabConsoleOutputAndError(() -> FeatureCommand.mainNoExit("version-mapping"));
assertEquals("", output.getValue());
MetadataVersion metadataVersion = MetadataVersion.latestProduction();
assertTrue(output.getKey().contains("metadata.version=" + metadataVersion.featureLevel() + " (" + metadataVersion.version() + ")"),
"Output did not contain expected Metadata Version: " + output.getKey());
}
@Test
public void testHandleRemoteCommandWithoutBootstrap() {
String errorMessage = ToolsTestUtils.grabConsoleError(() -> FeatureCommand.mainNoExit("upgrade"));
assertTrue(errorMessage.contains("You must specify either --bootstrap-controller " +
"or --bootstrap-server."));
}
@Test
public void testHandleFeatureDependenciesForFeatureWithDependencies() {
Map<String, Object> namespace = new HashMap<>();