[tool] Added a `croneval` command line tool
Super useful when dealing with the `cron` schedule. It enables to: 1. validate a cron expression. If the cron expression is incorrect it will try to output a descriptive/guiding error message 2. show future times in which the cron expression will be triggered (based on the current time) When deployed, once can access this tool from ES_HOME by `bin/watcher/croneval` Also updated the docs Original commit: elastic/x-pack-elasticsearch@2666c32a69
This commit is contained in:
parent
b2586bc7c1
commit
cfc8b81cea
|
@ -5,6 +5,13 @@
|
|||
<format>zip</format>
|
||||
</formats>
|
||||
<includeBaseDirectory>false</includeBaseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<filtered>false</filtered>
|
||||
<directory>bin/watcher</directory>
|
||||
<outputDirectory>bin</outputDirectory>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.watcher.trigger.schedule.tool;
|
||||
|
||||
import org.elasticsearch.common.cli.CliTool;
|
||||
import org.elasticsearch.common.cli.CliToolConfig;
|
||||
import org.elasticsearch.common.cli.Terminal;
|
||||
import org.elasticsearch.common.cli.commons.CommandLine;
|
||||
import org.elasticsearch.common.settings.Settings;
|
||||
import org.elasticsearch.env.Environment;
|
||||
import org.quartz.CronExpression;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import static org.elasticsearch.common.cli.CliToolConfig.Builder.cmd;
|
||||
import static org.elasticsearch.common.cli.CliToolConfig.Builder.option;
|
||||
import static org.elasticsearch.common.cli.CliToolConfig.config;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class CronEvalTool extends CliTool {
|
||||
|
||||
private static final CliToolConfig CONFIG = config("croneval", CronEvalTool.class)
|
||||
.cmds(Eval.CMD)
|
||||
.build();
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int status = new CronEvalTool().execute(args);
|
||||
System.exit(status);
|
||||
}
|
||||
|
||||
public CronEvalTool() {
|
||||
super(CONFIG);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Command parse(String s, CommandLine cli) throws Exception {
|
||||
return Eval.parse(terminal, cli);
|
||||
}
|
||||
|
||||
static class Eval extends Command {
|
||||
|
||||
private static final CliToolConfig.Cmd CMD = cmd("eval", Eval.class)
|
||||
.options(option("c", "count").hasArg(false).required(false))
|
||||
.build();
|
||||
|
||||
private static final SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss", Locale.ROOT);
|
||||
|
||||
final String expression;
|
||||
final int count;
|
||||
|
||||
Eval(Terminal terminal, String expression, int count) {
|
||||
super(terminal);
|
||||
this.expression = expression;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
public static Command parse(Terminal terminal, CommandLine cli) {
|
||||
String[] args = cli.getArgs();
|
||||
if (args.length != 1) {
|
||||
return exitCmd(ExitStatus.USAGE, terminal, "expecting a single argument that is the cron expression to evaluate");
|
||||
}
|
||||
String count = cli.getOptionValue("count", "10");
|
||||
try {
|
||||
return new Eval(terminal, args[0], Integer.parseInt(count));
|
||||
} catch (NumberFormatException nfe) {
|
||||
return exitCmd(ExitStatus.USAGE, terminal, "passed in count [%s] cannot be converted to a number", count);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExitStatus execute(Settings settings, Environment env) throws Exception {
|
||||
|
||||
// when invalid, a parse expression will be thrown with a descriptive error message
|
||||
// the cli infra handles such exceptions and hows the exceptions' message
|
||||
CronExpression.validateExpression(expression);
|
||||
|
||||
terminal.println("Valid!");
|
||||
|
||||
Date date = new Date();
|
||||
|
||||
terminal.println("Now is [" + format.format(date) + "]");
|
||||
terminal.println("Here are the next " + count + " times this cron expression will trigger:");
|
||||
|
||||
CronExpression cron = new CronExpression(expression);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
date = cron.getNextValidTimeAfter(date);
|
||||
terminal.println((i+1) + ".\t" + format.format(date));
|
||||
}
|
||||
return ExitStatus.OK;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
NAME
|
||||
|
||||
croneval - Validates and evaluates a cron expression
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
croneval "<expression>" [-c count]
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
Validates a given cron expression and if valid, presents the the future
|
||||
times that this cron expression will be triggered.
|
||||
|
||||
It is possible to control the number of future times that will be presented
|
||||
using the `-n` option (defaults to 10).
|
||||
|
||||
ARGUMENTS
|
||||
|
||||
<expression> The cron expression to evaluate. Note that since the
|
||||
expression contains white spaces it must be quoted
|
||||
in order for it to be passed in as a single argument
|
||||
to the tool.
|
||||
|
||||
OPTIONS
|
||||
|
||||
-c,--count <count> The number of future times this expression will be
|
||||
triggered at.
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.watcher.trigger.schedule.tool;
|
||||
|
||||
import com.carrotsearch.randomizedtesting.annotations.Repeat;
|
||||
import org.elasticsearch.common.cli.CliTool;
|
||||
import org.elasticsearch.common.cli.CliToolTestCase;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public class CronEvalToolTests extends CliToolTestCase {
|
||||
|
||||
@Test @Repeat(iterations = 10)
|
||||
public void testParse() throws Exception {
|
||||
String countOption = randomBoolean() ? "-c" : "--count";
|
||||
int count = randomIntBetween(1, 100);
|
||||
CliTool.Command command = new CronEvalTool().parse("eval", new String[] { "0 0 0 1-6 * ?", countOption, String.valueOf(count) });
|
||||
assertThat(command, instanceOf(CronEvalTool.Eval.class));
|
||||
CronEvalTool.Eval eval = (CronEvalTool.Eval) command;
|
||||
assertThat(eval.expression, is("0 0 0 1-6 * ?"));
|
||||
assertThat(eval.count, is(count));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
package org.elasticsearch.watcher.trigger.schedule.tool;
|
||||
|
||||
import org.elasticsearch.common.cli.Terminal;
|
||||
|
||||
/**
|
||||
* A small executable tool that can eval crons
|
||||
*/
|
||||
public class EvalCron {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
String expression = Terminal.DEFAULT.readText("cron: ");
|
||||
CronEvalTool.main(new String[] { expression });
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue