From 58a091a5d3f77896c37a378bd8a8649c36b46c91 Mon Sep 17 00:00:00 2001 From: Trevor Date: Sat, 16 Nov 2024 09:12:24 -0800 Subject: [PATCH] Add CLI help to validator (#1028) --- .../java/com/google/udmi/util/SiteModel.java | 14 +-- .../google/daq/mqtt/validator/Validator.java | 85 ++++++++++--------- 2 files changed, 51 insertions(+), 48 deletions(-) diff --git a/common/src/main/java/com/google/udmi/util/SiteModel.java b/common/src/main/java/com/google/udmi/util/SiteModel.java index 5698b199bc..a01e465792 100644 --- a/common/src/main/java/com/google/udmi/util/SiteModel.java +++ b/common/src/main/java/com/google/udmi/util/SiteModel.java @@ -143,13 +143,6 @@ public SiteModel(String specPath, Supplier specSupplier, ExecutionConfig } } - private static void loadVersionInfo(ExecutionConfiguration exeConfig) { - exeConfig.udmi_version = System.getenv(UDMI_VERSION_ENV); - exeConfig.udmi_commit = System.getenv(UDMI_COMMIT_ENV); - exeConfig.udmi_ref = System.getenv(UDMI_REF_ENV); - exeConfig.udmi_timever = System.getenv(UDMI_TIMEVER_ENV); - } - public SiteModel(String toolName, List argList) { this(removeStringArg(argList, "site_model"), projectSpecSupplier(argList), null); ExecutionConfiguration executionConfiguration = getExecutionConfiguration(); @@ -166,6 +159,13 @@ public SiteModel(ExecutionConfiguration executionConfiguration) { exeConfig.registry_suffix = executionConfiguration.registry_suffix; } + private static void loadVersionInfo(ExecutionConfiguration exeConfig) { + exeConfig.udmi_version = System.getenv(UDMI_VERSION_ENV); + exeConfig.udmi_commit = System.getenv(UDMI_COMMIT_ENV); + exeConfig.udmi_ref = System.getenv(UDMI_REF_ENV); + exeConfig.udmi_timever = System.getenv(UDMI_TIMEVER_ENV); + } + private static Supplier projectSpecSupplier(List argList) { return () -> { if (argList.isEmpty()) { diff --git a/validator/src/main/java/com/google/daq/mqtt/validator/Validator.java b/validator/src/main/java/com/google/daq/mqtt/validator/Validator.java index ed38dffeee..69edeff7c8 100644 --- a/validator/src/main/java/com/google/daq/mqtt/validator/Validator.java +++ b/validator/src/main/java/com/google/daq/mqtt/validator/Validator.java @@ -25,7 +25,6 @@ import static com.google.udmi.util.Common.UPGRADED_FROM; import static com.google.udmi.util.Common.getExceptionMessage; import static com.google.udmi.util.Common.getNamespacePrefix; -import static com.google.udmi.util.Common.removeNextArg; import static com.google.udmi.util.GeneralUtils.friendlyStackTrace; import static com.google.udmi.util.GeneralUtils.getTimestamp; import static com.google.udmi.util.GeneralUtils.ifNotNullGet; @@ -70,6 +69,8 @@ import com.google.daq.mqtt.util.MessagePublisher.QuerySpeed; import com.google.daq.mqtt.util.PubSubClient; import com.google.daq.mqtt.util.ValidationException; +import com.google.udmi.util.CommandLineOption; +import com.google.udmi.util.CommandLineProcessor; import com.google.udmi.util.Common; import com.google.udmi.util.GeneralUtils; import com.google.udmi.util.JsonUtil; @@ -94,7 +95,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.MissingFormatArgumentException; import java.util.Scanner; import java.util.Set; import java.util.TreeMap; @@ -188,7 +188,8 @@ public class Validator { private static final String TOOL_NAME = "validator"; public static final String VALIDATOR_TOOL_NAME = "validator"; public static final String REGISTRY_DEVICE_DEFAULT = "_regsitry"; - private long reportingDelay = DEFAULT_INTERVAL_SEC; + private long reportingDelaySec = DEFAULT_INTERVAL_SEC; + private final CommandLineProcessor commandLineProcessor = new CommandLineProcessor(this); private final Map reportingDevices = new TreeMap<>(); private final Set extraDevices = new TreeSet<>(); private final Set processedDevices = new TreeSet<>(); @@ -256,10 +257,13 @@ public Validator() { Validator processArgs(List argListRaw) { List argList = new ArrayList<>(argListRaw); - siteModel = new SiteModel(TOOL_NAME, argList); + try { + siteModel = new SiteModel(TOOL_NAME, argList); + } catch (IllegalArgumentException e) { + commandLineProcessor.showUsage(e.getMessage()); + } processProfile(siteModel.getExecutionConfiguration()); - postProcessArgs(argList); - targetDevices = Set.copyOf(argList); + targetDevices = Set.copyOf(postProcessArgs(argList)); initializeExpectedDevices(); return this; } @@ -349,33 +353,8 @@ private List parseArgs(List argList) { private List postProcessArgs(List argList) { try { - while (!argList.isEmpty()) { - String option = removeNextArg(argList); - try { - switch (option) { - case "-p" -> setProjectId(removeNextArg(argList)); - case "-s" -> setSiteDir(removeNextArg(argList)); - case "-a" -> setSchemaSpec(removeNextArg(argList)); - case "-t" -> validatePubSub(removeNextArg(argList), true); - case "-f" -> validateFilesOutput(removeNextArg(argList)); - case "-c" -> setValidateCurrent(true); - case "-d" -> setReportDelay(removeNextArg(argList)); - case "-u" -> forceUpgrade = true; - case "-r" -> validateMessageTrace(removeNextArg(argList)); - case "-n" -> client = new NullPublisher(); - case "-w" -> setMessageTraceDir(removeNextArg(argList)); - case "-z" -> setProfileMode(); - case "--" -> { - // All remaining arguments remain in the return list. - return argList; - } - default -> throw new RuntimeException("Unknown cmdline option " + option); - } - } catch (MissingFormatArgumentException e) { - throw new RuntimeException("For command line option " + option, e); - } - } - return argList; + List remainingArgs = commandLineProcessor.processArgs(argList); + return ofNullable(remainingArgs).orElse(ImmutableList.of()); } finally { if (schemaMap == null) { setSchemaSpec(new File(UDMI_ROOT, "schema").getAbsolutePath()); @@ -383,19 +362,33 @@ private List postProcessArgs(List argList) { } } + @CommandLineOption(short_form = "-n", description = "Use null client") + private void setNullClient() { + client = new NullPublisher(); + } + + @CommandLineOption(short_form = "-u", description = "Set force message upgrade") + private void setForceUpgrade() { + forceUpgrade = true; + } + + @CommandLineOption(short_form = "-z", description = "Turn on system profiling") private void setProfileMode() { IotReflectorClient.reportStatistics = true; MqttPublisher.reportStatistics = true; } + @CommandLineOption(short_form = "-d", arg_type = "n", description = "Report delay (sec)") private void setReportDelay(String arg) { - reportingDelay = Integer.parseInt(arg); + reportingDelaySec = Integer.parseInt(arg); } - private void setValidateCurrent(boolean current) { - validateCurrent = current; + @CommandLineOption(short_form = "-c", description = "Validate current device messages") + private void setValidateCurrent() { + validateCurrent = true; } + @CommandLineOption(short_form = "-p", arg_type = "s", description = "Set project id") private void setProjectId(String projectId) { if (!projectId.startsWith(PROJECT_PROVIDER_PREFIX)) { config.project_id = projectId; @@ -406,6 +399,11 @@ private void setProjectId(String projectId) { config.project_id = parts[1]; } + @CommandLineOption(short_form = "-t", arg_type = "s", description = "Validate pub sub target") + private void validatePubSub(String pubSubCombo) { + validatePubSub(pubSubCombo, true); + } + private void validatePubSub(String pubSubCombo, boolean reflect) { String[] parts = pubSubCombo.split("/"); Preconditions.checkArgument(parts.length <= 2, "Too many parts in pubsub path " + pubSubCombo); @@ -441,6 +439,7 @@ MessageReadingClient getMessageReadingClient() { return (MessageReadingClient) client; } + @CommandLineOption(short_form = "-r", arg_type = "s", description = "Validate message trace") private void validateMessageTrace(String messageDir) { client = new MessageReadingClient(getRegistryId(), messageDir); dataSinks.add(client); @@ -457,7 +456,8 @@ Validator prepForMock() { * * @param siteDir site model directory */ - public void setSiteDir(String siteDir) { + @CommandLineOption(short_form = "-s", arg_type = "s", description = "Set site directory") + private void setSiteDir(String siteDir) { config.site_model = siteDir; final File baseDir; if (NO_SITE.equals(siteDir)) { @@ -482,6 +482,7 @@ private ExecutionConfiguration resolveSiteConfig(ExecutionConfiguration config, return GeneralUtils.mergeObject(siteConfig, config); } + @CommandLineOption(short_form = "-w", arg_type = "s", description = "Write trace output") private void setMessageTraceDir(String writeDirArg) { traceDir = new File(writeDirArg); outputLogger.info("Tracing message capture to " + traceDir.getAbsolutePath()); @@ -515,7 +516,7 @@ private void initializeExpectedDevices() { private ReportingDevice newReportingDevice(String device) { ReportingDevice reportingDevice = new ReportingDevice(device); - ifTrueThen(validateCurrent, () -> reportingDevice.setThreshold(reportingDelay)); + ifTrueThen(validateCurrent, () -> reportingDevice.setThreshold(reportingDelaySec)); return reportingDevice; } @@ -524,7 +525,8 @@ private ReportingDevice newReportingDevice(String device) { * * @param schemaPath schema specification directory */ - public void setSchemaSpec(String schemaPath) { + @CommandLineOption(short_form = "-a", arg_type = "s", description = "Set schema path") + private void setSchemaSpec(String schemaPath) { File schemaPart = new File(schemaPath); boolean rawPath = schemaPart.isAbsolute() || Strings.isNullOrEmpty(config.udmi_root); File schemaFile = rawPath ? schemaPart : new File(new File(config.udmi_root), schemaPath); @@ -607,7 +609,7 @@ void messageLoop() { processValidationReport(); ScheduledFuture reportSender = simulatedMessages ? null : executor.scheduleAtFixedRate(this::processValidationReport, - reportingDelay, reportingDelay, TimeUnit.SECONDS); + reportingDelaySec, reportingDelaySec, TimeUnit.SECONDS); try { while (client.isActive()) { try { @@ -1090,7 +1092,7 @@ private synchronized void sendDeviceValidationReports(Map sendList = summaryDevices.stream().limit(batchSize).toList(); System.err.printf("Sending %d device validation state updates out of an available %d%n", sendList.size(), summaryDevices.size()); @@ -1177,6 +1179,7 @@ private void validateFiles(String schemaSpec, String prefix, String targetSpec) schemaExceptions.throwIfNotEmpty(); } + @CommandLineOption(short_form = "-f", arg_type = "s", description = "Validate from files") private void validateFilesOutput(String targetSpec) { try { String[] parts = targetSpec.split(":");