Overview

Many gfsh commands are mutually-reliant to be feature-complete.
For instance, there exist commands createdescribedestroy, and list for multiple cluster components.

Because the scope of an individual commit should be concise, it is unlikely that a single commit would (or should) simultaneously introduce all mutually-reliant commands for a new feature.
As a developer, it would be convenient to be able to feature-flag commands via an annotation rather than requiring feature-flag / system property logic in the command's implementation.

Approach

Add an annotation @FeatureFlag that conditionally prevents a class implementing CommandMarker from being loaded into the CommandManager.

Intended Use

@FeatureFlag(flag = "disabled.unless.this.system.property.is.set")
public class MyCommandClass implements CommandMarker {
  @CliCommand(value = "my-command")
  public Result myCommandMethod(){
    ...
  }
}

 

The above will then not appear in gfsh unless gfsh is launched with JAVA_ARGS="-Ddisabled.unless.this.system.property.is.set=anyValue".

If the above is an "online" command that would be execute on a manager, the member would need to be launched with (for instance) start locator --J=-Ddisabled.unless.this.system.property.is.set=anyValue ...

Exposure Considerations

By preventing the CommandManager from loading the class, it is inaccessible locally via gfsh.

If the command is a disabled "online" command that is (due to incorrect configuration) enabled in the local gfsh, execution will fail when the remote execution attempts to parse the command, as the GfshParser relies on the CommandManager to provide a list of valid commands.

If the command is a disabled "online" command, it will be inaccessible also by the REST API endpoint /management/command/cmd=my-command.  This endpoint also relies on GfshParser.

Explicit instantiation of the class in invocation of the @CliCommand method is not explicitly guarded.  However, this is not a significant exposure since this will only affect the local environment, not a remote cluster.

Other Considerations

Would it be more intuitive to use an annotation @Disabled and/or @Disabled(unlessPropertyIsSet = "some.system.property")?

Should this flag also prevent a class implementing org.apache.geode.cache.execute.Function from loading into the FunctionService, preventing it from being executed via gfsh's execute function command?

  • No labels