From 0d78aa2708ac1299819756d66a5f7242831f6466 Mon Sep 17 00:00:00 2001 From: Lee Hinman Date: Thu, 2 Jan 2020 16:57:51 -0700 Subject: [PATCH] Don't dump a stacktrace for invalid patterns when executing elasticsearch-croneval (#49744) (#50578) Co-authored-by: bellengao --- docs/reference/commands/croneval.asciidoc | 6 +- .../trigger/schedule/tool/CronEvalTool.java | 90 +++++++++++-------- 2 files changed, 60 insertions(+), 36 deletions(-) diff --git a/docs/reference/commands/croneval.asciidoc b/docs/reference/commands/croneval.asciidoc index be9b16770dc33..fa7b9aed33bb3 100644 --- a/docs/reference/commands/croneval.asciidoc +++ b/docs/reference/commands/croneval.asciidoc @@ -30,7 +30,11 @@ This command is provided in the `$ES_HOME/bin` directory. `-c, --count` :: The number of future times this expression will be triggered. The default value is `10`. - + +`-d, --detail`:: + Shows detail for invalid cron expression. It will print the stacktrace if the + expression is not valid. + `-h, --help`:: Returns all of the command parameters. diff --git a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/tool/CronEvalTool.java b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/tool/CronEvalTool.java index 565bae15ea998..9464abcc4ba59 100644 --- a/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/tool/CronEvalTool.java +++ b/x-pack/plugin/watcher/src/main/java/org/elasticsearch/xpack/watcher/trigger/schedule/tool/CronEvalTool.java @@ -37,13 +37,16 @@ public static void main(String[] args) throws Exception { private final OptionSpec countOption; private final OptionSpec arguments; + private final OptionSpec detailOption; CronEvalTool() { super("Validates and evaluates a cron expression"); - this.countOption = parser.acceptsAll(Arrays.asList("c", "count"), - "The number of future times this expression will be triggered") - .withRequiredArg().ofType(Integer.class).defaultsTo(10); + this.countOption = parser.acceptsAll(Arrays.asList("c", "count"), "The number of future times this expression will be triggered") + .withRequiredArg() + .ofType(Integer.class) + .defaultsTo(10); this.arguments = parser.nonOptions("expression"); + this.detailOption = parser.acceptsAll(Arrays.asList("d", "detail"), "Show detail for invalid cron expression"); parser.accepts("E", "Unused. Only for compatibility with other CLI tools.").withRequiredArg(); } @@ -55,46 +58,63 @@ protected void execute(Terminal terminal, OptionSet options) throws Exception { if (args.size() != 1) { throw new UserException(ExitCodes.USAGE, "expecting a single argument that is the cron expression to evaluate"); } - execute(terminal, args.get(0), count); + boolean printDetail = options.has(detailOption); + execute(terminal, args.get(0), count, printDetail); } - private void execute(Terminal terminal, String expression, int count) throws Exception { - Cron.validate(expression); - terminal.println("Valid!"); + private void execute(Terminal terminal, String expression, int count, boolean printDetail) throws Exception { + try { + Cron.validate(expression); + terminal.println("Valid!"); - final ZonedDateTime date = ZonedDateTime.now(ZoneOffset.UTC); - final boolean isLocalTimeUTC = UTC_FORMATTER.zone().equals(LOCAL_FORMATTER.zone()); - if (isLocalTimeUTC) { - terminal.println("Now is [" + UTC_FORMATTER.format(date) + "] in UTC"); - } else { - terminal.println("Now is [" + UTC_FORMATTER.format(date) + "] in UTC, local time is [" + LOCAL_FORMATTER.format(date) + "]"); + final ZonedDateTime date = ZonedDateTime.now(ZoneOffset.UTC); + final boolean isLocalTimeUTC = UTC_FORMATTER.zone().equals(LOCAL_FORMATTER.zone()); + if (isLocalTimeUTC) { + terminal.println("Now is [" + UTC_FORMATTER.format(date) + "] in UTC"); + } else { + terminal.println( + "Now is [" + UTC_FORMATTER.format(date) + "] in UTC, local time is [" + LOCAL_FORMATTER.format(date) + "]" + ); - } - terminal.println("Here are the next " + count + " times this cron expression will trigger:"); - - Cron cron = new Cron(expression); - long time = date.toInstant().toEpochMilli(); - - for (int i = 0; i < count; i++) { - long prevTime = time; - time = cron.getNextValidTimeAfter(time); - if (time < 0) { - if (i == 0) { - throw new UserException(ExitCodes.OK, "Could not compute future times since [" - + UTC_FORMATTER.format(Instant.ofEpochMilli(prevTime)) + "] " + "(perhaps the cron expression only points to " + - "times in the" + - " " + - "past?)"); - } - break; } + terminal.println("Here are the next " + count + " times this cron expression will trigger:"); + + Cron cron = new Cron(expression); + long time = date.toInstant().toEpochMilli(); + + for (int i = 0; i < count; i++) { + long prevTime = time; + time = cron.getNextValidTimeAfter(time); + if (time < 0) { + if (i == 0) { + throw new UserException( + ExitCodes.OK, + "Could not compute future times since [" + + UTC_FORMATTER.format(Instant.ofEpochMilli(prevTime)) + + "] " + + "(perhaps the cron expression only points to " + + "times in the" + + " " + + "past?)" + ); + } + break; + } - if (isLocalTimeUTC) { - terminal.println((i + 1) + ".\t" + UTC_FORMATTER.format(Instant.ofEpochMilli(time))); + if (isLocalTimeUTC) { + terminal.println((i + 1) + ".\t" + UTC_FORMATTER.format(Instant.ofEpochMilli(time))); + } else { + terminal.println((i + 1) + ".\t" + UTC_FORMATTER.format(Instant.ofEpochMilli(time))); + terminal.println("\t" + LOCAL_FORMATTER.format(Instant.ofEpochMilli(time))); + } + } + } catch (Exception e) { + if (printDetail) { + throw e; } else { - terminal.println((i + 1) + ".\t" + UTC_FORMATTER.format(Instant.ofEpochMilli(time))); - terminal.println("\t" + LOCAL_FORMATTER.format(Instant.ofEpochMilli(time))); + throw new UserException(ExitCodes.OK, e.getMessage() + (e.getCause() == null ? "" : ": " + e.getCause().getMessage())); } + } } }