Skip to content

Commit

Permalink
IGNITE-23459 Add console input if argument presented without value fo…
Browse files Browse the repository at this point in the history
…r ./control.sh
  • Loading branch information
Положаев Денис Александрович committed Jan 17, 2025
1 parent a09b821 commit 670d644
Show file tree
Hide file tree
Showing 7 changed files with 243 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ public class ArgumentParser {
/** */
private final List<CLIArgument<?>> common = new ArrayList<>();

/** Console instance */
protected final GridConsole console;

static {
SENSITIVE_ARGUMENTS.add(CMD_PASSWORD);
SENSITIVE_ARGUMENTS.add(CMD_KEYSTORE_PASSWORD);
Expand All @@ -179,16 +182,26 @@ public static boolean isSensitiveArgument(String arg) {
* @param registry Supported commands.
*/
public ArgumentParser(IgniteLogger log, IgniteCommandRegistry registry) {
this(log, registry, null);
}

/**
* @param log Logger.
* @param registry Supported commands.
* @param console Supported commands.
*/
public ArgumentParser(IgniteLogger log, IgniteCommandRegistry registry, GridConsole console) {
this.log = log;
this.registry = registry;
this.console = console;

BiConsumer<String, ?> securityWarn = (name, val) -> log.info(String.format("Warning: %s is insecure. " +
"Whenever possible, use interactive prompt for password (just discard %s option).", name, name));

arg(CMD_HOST, "HOST_OR_IP", String.class, DFLT_HOST);
arg(CMD_PORT, "PORT", Integer.class, useConnectorConnection() ? DFLT_TCP_PORT : DFLT_PORT, PORT_VALIDATOR);
arg(CMD_USER, "USER", String.class, null);
arg(CMD_PASSWORD, "PASSWORD", String.class, null, (BiConsumer<String, String>)securityWarn);
arg(CMD_PASSWORD, "PASSWORD", String.class, null, (BiConsumer<String, String>)securityWarn, true);
arg(CMD_PING_INTERVAL, "PING_INTERVAL", Long.class, DFLT_PING_INTERVAL, POSITIVE_LONG);
arg(CMD_PING_TIMEOUT, "PING_TIMEOUT", Long.class, DFLT_PING_TIMEOUT, POSITIVE_LONG);
arg(CMD_VERBOSE, CMD_VERBOSE, boolean.class, false);
Expand All @@ -198,10 +211,10 @@ public ArgumentParser(IgniteLogger log, IgniteCommandRegistry registry) {
arg(CMD_SSL_FACTORY, "SSL_FACTORY_PATH", String.class, null);
arg(CMD_KEYSTORE_TYPE, "KEYSTORE_TYPE", String.class, SslContextFactory.DFLT_STORE_TYPE);
arg(CMD_KEYSTORE, "KEYSTORE_PATH", String.class, null);
arg(CMD_KEYSTORE_PASSWORD, "KEYSTORE_PASSWORD", char[].class, null, (BiConsumer<String, char[]>)securityWarn);
arg(CMD_KEYSTORE_PASSWORD, "KEYSTORE_PASSWORD", char[].class, null, (BiConsumer<String, char[]>)securityWarn, true);
arg(CMD_TRUSTSTORE_TYPE, "TRUSTSTORE_TYPE", String.class, SslContextFactory.DFLT_STORE_TYPE);
arg(CMD_TRUSTSTORE, "TRUSTSTORE_PATH", String.class, null);
arg(CMD_TRUSTSTORE_PASSWORD, "TRUSTSTORE_PASSWORD", char[].class, null, (BiConsumer<String, char[]>)securityWarn);
arg(CMD_TRUSTSTORE_PASSWORD, "TRUSTSTORE_PASSWORD", char[].class, null, (BiConsumer<String, char[]>)securityWarn, true);
arg(CMD_AUTO_CONFIRMATION, CMD_AUTO_CONFIRMATION, boolean.class, false);
arg(
CMD_ENABLE_EXPERIMENTAL,
Expand All @@ -210,6 +223,11 @@ public ArgumentParser(IgniteLogger log, IgniteCommandRegistry registry) {
);
}

/** */
private <T> void arg(String name, String usage, Class<T> type, T dflt, BiConsumer<String, T> validator, boolean isConsoleReq) {
common.add(optionalArg(name, usage, type, t -> dflt, validator, isConsoleReq));
}

/** */
private <T> void arg(String name, String usage, Class<T> type, T dflt, BiConsumer<String, T> validator) {
common.add(optionalArg(name, usage, type, t -> dflt, validator));
Expand Down Expand Up @@ -255,7 +273,7 @@ public <A extends IgniteDataTransferObject> ConnectionAndSslParameters<A> parseA

CLIArgumentParser parser = createArgumentParser();

parser.parse(args.iterator());
parser.parse(args.listIterator());

A arg = (A)argument(
cmdPath.peek().argClass(),
Expand Down Expand Up @@ -348,7 +366,9 @@ private CLIArgumentParser createArgumentParser() {
optional,
fld.getType(),
null,
(name, val) -> {}
(name, val) -> {},
(!fld.getType().equals(Boolean.class) && !fld.getType().equals(boolean.class))
&& fld.getAnnotation(Argument.class).consoleReq()
);

List<Set<String>> grpdFlds = CommandUtils.argumentGroupsValues(cmdPath.peek().argClass());
Expand Down Expand Up @@ -378,6 +398,6 @@ private CLIArgumentParser createArgumentParser() {

namedArgs.addAll(common);

return new CLIArgumentParser(positionalArgs, namedArgs);
return new CLIArgumentParser(positionalArgs, namedArgs, console);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ public <A extends IgniteDataTransferObject> int execute(List<String> rawArgs) {

verbose = F.exist(rawArgs, CMD_VERBOSE::equalsIgnoreCase);

ConnectionAndSslParameters<A> args = new ArgumentParser(logger, registry).parseAndValidate(rawArgs);
ConnectionAndSslParameters<A> args = new ArgumentParser(logger, registry, console).parseAndValidate(rawArgs);

cmdName = toFormattedCommandName(args.cmdPath().peekLast().getClass()).toUpperCase();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ public class CLIArgument<T> {
/** */
private final BiConsumer<String, T> validator;

/** */
private final boolean isConsoleReq;

/** */
public static <T> CLIArgument<T> optionalArg(String name, String usage, Class<T> type) {
return new CLIArgument<>(name, usage, true, type, null, null);
Expand All @@ -68,6 +71,18 @@ public static <T> CLIArgument<T> optionalArg(
return new CLIArgument<>(name, usage, true, type, dfltValSupplier, validator);
}

/** */
public static <T> CLIArgument<T> optionalArg(
String name,
String usage,
Class<T> type,
Function<CLIArgumentParser, T> dfltValSupplier,
BiConsumer<String, T> validator,
boolean isConsoleReq
) {
return new CLIArgument<>(name, usage, true, type, dfltValSupplier, validator, isConsoleReq);
}

/** */
public static <T> CLIArgument<T> mandatoryArg(String name, String usage, Class<T> type) {
return new CLIArgument<>(name, usage, false, type, null, null);
Expand All @@ -81,6 +96,19 @@ public CLIArgument(
Class<T> type,
Function<CLIArgumentParser, T> dfltValSupplier,
BiConsumer<String, T> validator
) {
this(name, usage, isOptional, type, dfltValSupplier, validator, false);
}

/** */
public CLIArgument(
String name,
String usage,
boolean isOptional,
Class<T> type,
Function<CLIArgumentParser, T> dfltValSupplier,
BiConsumer<String, T> validator,
boolean isConsoleReq
) {
this.name = name;
this.usage = usage;
Expand All @@ -90,6 +118,7 @@ public CLIArgument(
? (type.equals(Boolean.class) ? p -> (T)Boolean.FALSE : p -> null)
: dfltValSupplier;
this.validator = validator;
this.isConsoleReq = !type.equals(Boolean.class) && !type.equals(boolean.class) && isConsoleReq;
}

/** */
Expand Down Expand Up @@ -121,4 +150,9 @@ public Function<CLIArgumentParser, T> defaultValueSupplier() {
public BiConsumer<String, T> validator() {
return validator == null ? EMPTY : validator;
}

/** */
public boolean isConsoleReq() {
return isConsoleReq;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import org.apache.ignite.IgniteException;
import org.apache.ignite.internal.commandline.GridConsole;
import org.apache.ignite.internal.util.GridStringBuilder;

import static java.util.stream.Collectors.toSet;
Expand All @@ -49,20 +51,34 @@ public class CLIArgumentParser {
/** */
private final Map<String, Object> parsedArgs = new HashMap<>();

/** Console instance */
protected final GridConsole console;

/** */
public CLIArgumentParser(List<CLIArgument<?>> argConfiguration) {
this(Collections.emptyList(), argConfiguration);
}

/** */
public CLIArgumentParser(
List<CLIArgument<?>> positionalArgConfig,
List<CLIArgument<?>> positionalArgCfg,
List<CLIArgument<?>> argConfiguration
) {
this.positionalArgCfg = positionalArgConfig;
this(positionalArgCfg, argConfiguration, null);
}

/** */
public CLIArgumentParser(
List<CLIArgument<?>> positionalArgCfg,
List<CLIArgument<?>> argConfiguration,
GridConsole console
) {
this.positionalArgCfg = positionalArgCfg;

for (CLIArgument<?> cliArg : argConfiguration)
this.argConfiguration.put(cliArg.name(), cliArg);

this.console = console;
}

/**
Expand All @@ -71,7 +87,7 @@ public CLIArgumentParser(
*
* @param argsIter Iterator.
*/
public void parse(Iterator<String> argsIter) {
public void parse(ListIterator<String> argsIter) {
Set<String> obligatoryArgs =
argConfiguration.values().stream().filter(a -> !a.optional()).map(CLIArgument::name).collect(toSet());

Expand Down Expand Up @@ -104,10 +120,21 @@ else if (parsedArgs.get(cliArg.name()) != null)

boolean bool = cliArg.type().equals(Boolean.class) || cliArg.type().equals(boolean.class);

if (!bool && !argsIter.hasNext())
throw new IllegalArgumentException("Please specify a value for argument: " + arg);
String strVal;

String strVal = bool ? "true" : argsIter.next();
if (cliArg.isConsoleReq() && console != null) {
strVal = argsIter.hasNext() ? argsIter.next() : null;

if (strVal != null && strVal.startsWith(NAME_PREFIX))
argsIter.previous();

if (strVal == null && !argsIter.hasNext() || strVal.startsWith(NAME_PREFIX))
strVal = requestDataFromConsole(arg.substring(NAME_PREFIX.length()) + ": ");
}
else if (!bool && !argsIter.hasNext())
throw new IllegalArgumentException("Please specify a value for argument: " + arg);
else
strVal = bool ? "true" : argsIter.next();

if (strVal != null && strVal.startsWith(NAME_PREFIX))
throw new IllegalArgumentException("Unexpected value: " + strVal);
Expand Down Expand Up @@ -214,4 +241,20 @@ private String argNameForUsage(CLIArgument<?> arg) {
else
return arg.name();
}

/**
* Requests data from console with message.
*
* @param msg Message.
* @return Input data.
*/
private String requestDataFromConsole(String msg) {
if (console != null)
return console.readLine(msg);
else {
Scanner scanner = new Scanner(System.in);

return scanner.nextLine();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,7 @@ public static void main(String[] args) {
return;
}

p.parse(asList(args).iterator());
p.parse(asList(args).listIterator());

Set<String> idxs = new HashSet<>(asList(p.get(INDEXES_ARG)));

Expand Down
Loading

0 comments on commit 670d644

Please sign in to comment.