[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:
uboness 2015-04-08 11:15:44 +02:00
parent b2586bc7c1
commit cfc8b81cea
5 changed files with 184 additions and 0 deletions

View File

@ -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>

View File

@ -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;
}
}
}

View File

@ -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.

View File

@ -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));
}
}

View File

@ -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 });
}
}