Skip to content

Commit

Permalink
HDDS-11831. Finer-grained interface for dynamically registered subcom…
Browse files Browse the repository at this point in the history
…mands (apache#7514)
  • Loading branch information
adoroszlai authored Dec 2, 2024
1 parent db36e39 commit 6ba309a
Show file tree
Hide file tree
Showing 17 changed files with 132 additions and 123 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* 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 picocli.CommandLine;

import java.util.ServiceLoader;

/**
* Interface for parent commands that accept subcommands to be dynamically registered.
* Subcommands should:
* <li>implement the interface returned by {@link #subcommandType()}</li>
* <li>be annotated with {@code MetaInfServices} parameterized with the same type</li>
*/
public interface ExtensibleParentCommand {

/** @return The class of the marker interface for subcommands. */
Class<?> subcommandType();

/** Recursively find and add subcommands to {@code cli}. */
static void addSubcommands(CommandLine cli) {
Object command = cli.getCommand();

// find and add subcommands
if (command instanceof ExtensibleParentCommand) {
ExtensibleParentCommand parentCommand = (ExtensibleParentCommand) command;
ServiceLoader<?> subcommands = ServiceLoader.load(parentCommand.subcommandType());
for (Object subcommand : subcommands) {
final CommandLine.Command commandAnnotation = subcommand.getClass().getAnnotation(CommandLine.Command.class);
CommandLine subcommandCommandLine = new CommandLine(subcommand);
cli.addSubcommand(commandAnnotation.name(), subcommandCommandLine);
}
}

// process subcommands recursively
for (CommandLine subcommand : cli.getSubcommands().values()) {
addSubcommands(subcommand);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -52,16 +52,20 @@ public class GenericCli implements Callable<Void>, GenericParentCommand {
private final CommandLine cmd;

public GenericCli() {
this(null);
}

public GenericCli(Class<?> type) {
cmd = new CommandLine(this);
cmd.setExecutionExceptionHandler((ex, commandLine, parseResult) -> {
printError(ex);
return EXECUTION_ERROR_EXIT_CODE;
});
}

public GenericCli(Class<?> type) {
this();
addSubcommands(getCmd(), type);
if (type != null) {
addSubcommands(getCmd(), type);
}
ExtensibleParentCommand.addSubcommands(cmd);
}

private void addSubcommands(CommandLine cli, Class<?> type) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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;

/** Marker interface for subcommands to be added to {@code OzoneAdmin}. */
public interface AdminSubcommand {
// marker
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,18 @@
description = "Developer tools for Ozone Admin operations",
versionProvider = HddsVersionProvider.class,
mixinStandardHelpOptions = true)
public class OzoneAdmin extends GenericCli {
public class OzoneAdmin extends GenericCli implements ExtensibleParentCommand {

private OzoneConfiguration ozoneConf;

private UserGroupInformation user;

public OzoneAdmin() {
super(OzoneAdmin.class);
super();
}

@VisibleForTesting
public OzoneAdmin(OzoneConfiguration conf) {
super(OzoneAdmin.class);
ozoneConf = conf;
}

Expand Down Expand Up @@ -79,4 +78,9 @@ public int execute(String[] argv) {
return TracingUtil.executeInNewSpan(spanName,
() -> super.execute(argv));
}

@Override
public Class<? extends AdminSubcommand> subcommandType() {
return AdminSubcommand.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@
*/
package org.apache.hadoop.hdds.scm.cli;

import org.apache.hadoop.hdds.cli.AdminSubcommand;
import org.apache.hadoop.hdds.cli.GenericCli;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
import org.apache.hadoop.hdds.cli.OzoneAdmin;
import org.apache.hadoop.hdds.cli.SubcommandWithParent;
import org.kohsuke.MetaInfServices;
import picocli.CommandLine.Command;
import picocli.CommandLine.Model.CommandSpec;
Expand Down Expand Up @@ -90,9 +89,8 @@
ContainerBalancerStopSubcommand.class,
ContainerBalancerStatusSubcommand.class
})
@MetaInfServices(SubcommandWithParent.class)
public class ContainerBalancerCommands implements Callable<Void>,
SubcommandWithParent {
@MetaInfServices(AdminSubcommand.class)
public class ContainerBalancerCommands implements Callable<Void>, AdminSubcommand {

@Spec
private CommandSpec spec;
Expand All @@ -102,9 +100,4 @@ public Void call() throws Exception {
GenericCli.missingSubcommand(spec);
return null;
}

@Override
public Class<?> getParentType() {
return OzoneAdmin.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@

import java.util.concurrent.Callable;

import org.apache.hadoop.hdds.cli.AdminSubcommand;
import org.apache.hadoop.hdds.cli.GenericCli;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
import org.apache.hadoop.hdds.cli.OzoneAdmin;
import org.apache.hadoop.hdds.cli.SubcommandWithParent;

import org.kohsuke.MetaInfServices;
import picocli.CommandLine.Command;
Expand All @@ -42,9 +41,8 @@
ReplicationManagerStopSubcommand.class,
ReplicationManagerStatusSubcommand.class
})
@MetaInfServices(SubcommandWithParent.class)
public class ReplicationManagerCommands implements Callable<Void>,
SubcommandWithParent {
@MetaInfServices(AdminSubcommand.class)
public class ReplicationManagerCommands implements Callable<Void>, AdminSubcommand {

@Spec
private CommandSpec spec;
Expand All @@ -54,9 +52,4 @@ public Void call() throws Exception {
GenericCli.missingSubcommand(spec);
return null;
}

@Override
public Class<?> getParentType() {
return OzoneAdmin.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@

import java.util.concurrent.Callable;

import org.apache.hadoop.hdds.cli.AdminSubcommand;
import org.apache.hadoop.hdds.cli.GenericCli;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
import org.apache.hadoop.hdds.cli.OzoneAdmin;
import org.apache.hadoop.hdds.cli.SubcommandWithParent;

import org.kohsuke.MetaInfServices;
import picocli.CommandLine.Command;
Expand All @@ -42,8 +41,8 @@
SafeModeExitSubcommand.class,
SafeModeWaitSubcommand.class
})
@MetaInfServices(SubcommandWithParent.class)
public class SafeModeCommands implements Callable<Void>, SubcommandWithParent {
@MetaInfServices(AdminSubcommand.class)
public class SafeModeCommands implements Callable<Void>, AdminSubcommand {

@Spec
private CommandSpec spec;
Expand All @@ -53,9 +52,4 @@ public Void call() throws Exception {
GenericCli.missingSubcommand(spec);
return null;
}

@Override
public Class<?> getParentType() {
return OzoneAdmin.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,8 @@
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.apache.hadoop.hdds.cli.AdminSubcommand;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
import org.apache.hadoop.hdds.cli.OzoneAdmin;
import org.apache.hadoop.hdds.cli.SubcommandWithParent;
import org.apache.hadoop.hdds.protocol.DatanodeDetails;
import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
import org.apache.hadoop.hdds.scm.client.ScmClient;
Expand All @@ -56,9 +55,9 @@
description = "Print a tree of the network topology as reported by SCM",
mixinStandardHelpOptions = true,
versionProvider = HddsVersionProvider.class)
@MetaInfServices(SubcommandWithParent.class)
@MetaInfServices(AdminSubcommand.class)
public class TopologySubcommand extends ScmSubcommand
implements SubcommandWithParent {
implements AdminSubcommand {

private static final List<HddsProtos.NodeState> STATES = new ArrayList<>();

Expand Down Expand Up @@ -137,11 +136,6 @@ public void execute(ScmClient scmClient) throws IOException {
}
}

@Override
public Class<?> getParentType() {
return OzoneAdmin.class;
}

// Format
// Location: rack1
// ipAddress(hostName) OperationalState
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,9 @@

import java.util.concurrent.Callable;

import org.apache.hadoop.hdds.cli.AdminSubcommand;
import org.apache.hadoop.hdds.cli.GenericCli;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
import org.apache.hadoop.hdds.cli.OzoneAdmin;
import org.apache.hadoop.hdds.cli.SubcommandWithParent;

import org.kohsuke.MetaInfServices;
import picocli.CommandLine.Command;
Expand All @@ -43,8 +42,8 @@
CleanExpiredCertsSubcommand.class,
})

@MetaInfServices(SubcommandWithParent.class)
public class CertCommands implements Callable<Void>, SubcommandWithParent {
@MetaInfServices(AdminSubcommand.class)
public class CertCommands implements Callable<Void>, AdminSubcommand {

@Spec
private CommandSpec spec;
Expand All @@ -54,9 +53,4 @@ public Void call() throws Exception {
GenericCli.missingSubcommand(spec);
return null;
}

@Override
public Class<?> getParentType() {
return OzoneAdmin.class;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@

import java.util.concurrent.Callable;

import org.apache.hadoop.hdds.cli.AdminSubcommand;
import org.apache.hadoop.hdds.cli.GenericCli;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
import org.apache.hadoop.hdds.cli.OzoneAdmin;
import org.apache.hadoop.hdds.cli.SubcommandWithParent;

import org.kohsuke.MetaInfServices;
import picocli.CommandLine.Command;
Expand All @@ -46,8 +46,8 @@
ReportSubcommand.class,
UpgradeSubcommand.class
})
@MetaInfServices(SubcommandWithParent.class)
public class ContainerCommands implements Callable<Void>, SubcommandWithParent {
@MetaInfServices(AdminSubcommand.class)
public class ContainerCommands implements Callable<Void>, AdminSubcommand {

@Spec
private CommandSpec spec;
Expand All @@ -61,11 +61,6 @@ public Void call() throws Exception {
return null;
}

@Override
public Class<?> getParentType() {
return OzoneAdmin.class;
}

public OzoneAdmin getParent() {
return parent;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,9 @@
*/
package org.apache.hadoop.hdds.scm.cli.datanode;

import org.apache.hadoop.hdds.cli.AdminSubcommand;
import org.apache.hadoop.hdds.cli.GenericCli;
import org.apache.hadoop.hdds.cli.HddsVersionProvider;
import org.apache.hadoop.hdds.cli.OzoneAdmin;
import org.apache.hadoop.hdds.cli.SubcommandWithParent;
import org.kohsuke.MetaInfServices;
import picocli.CommandLine;
import picocli.CommandLine.Model.CommandSpec;
Expand All @@ -41,10 +40,11 @@
DecommissionSubCommand.class,
MaintenanceSubCommand.class,
RecommissionSubCommand.class,
StatusSubCommand.class,
UsageInfoSubcommand.class
})
@MetaInfServices(SubcommandWithParent.class)
public class DatanodeCommands implements Callable<Void>, SubcommandWithParent {
@MetaInfServices(AdminSubcommand.class)
public class DatanodeCommands implements Callable<Void>, AdminSubcommand {

@Spec
private CommandSpec spec;
Expand All @@ -54,9 +54,4 @@ public Void call() throws Exception {
GenericCli.missingSubcommand(spec);
return null;
}

@Override
public Class<?> getParentType() {
return OzoneAdmin.class;
}
}
Loading

0 comments on commit 6ba309a

Please sign in to comment.