diff --git a/cts/cli/regression.rules.exp b/cts/cli/regression.rules.exp
index cdfb5d1e24..a439773cfe 100644
--- a/cts/cli/regression.rules.exp
+++ b/cts/cli/regression.rules.exp
@@ -1,289 +1,285 @@
Created new pacemaker configuration
A new shadow instance was created. To begin using it, enter the following into your shell:
export CIB_shadow=cts-cli
=#=#=#= Begin test: crm_rule given no arguments =#=#=#=
crm_rule: No mode operation given
=#=#=#= End test: crm_rule given no arguments - Incorrect usage (64) =#=#=#=
* Passed: crm_rule - crm_rule given no arguments
=#=#=#= Begin test: crm_rule given no arguments (XML) =#=#=#=
crm_rule: No mode operation given
=#=#=#= End test: crm_rule given no arguments (XML) - Incorrect usage (64) =#=#=#=
* Passed: crm_rule - crm_rule given no arguments (XML)
=#=#=#= Begin test: crm_rule given no rule to check =#=#=#=
crm_rule: --check requires use of --rule=
=#=#=#= End test: crm_rule given no rule to check - Incorrect usage (64) =#=#=#=
* Passed: crm_rule - crm_rule given no rule to check
=#=#=#= Begin test: crm_rule given no rule to check (XML) =#=#=#=
crm_rule: --check requires use of --rule=
=#=#=#= End test: crm_rule given no rule to check (XML) - Incorrect usage (64) =#=#=#=
* Passed: crm_rule - crm_rule given no rule to check (XML)
=#=#=#= Begin test: crm_rule given invalid input XML =#=#=#=
log_xmllib_err error: XML Error: Entity: line 1: parser error : Start tag expected, '<' not found
log_xmllib_err error: XML Error: invalidxml
log_xmllib_err error: XML Error: ^
log_xmllib_err error: XML Error: Entity: line 1: parser error : Start tag expected, '<' not found
log_xmllib_err error: XML Error: invalidxml
log_xmllib_err error: XML Error: ^
crm_rule: Couldn't parse input string: invalidxml
-
=#=#=#= End test: crm_rule given invalid input XML - Invalid data given (65) =#=#=#=
* Passed: crm_rule - crm_rule given invalid input XML
=#=#=#= Begin test: crm_rule given invalid input XML (XML) =#=#=#=
log_xmllib_err error: XML Error: Entity: line 1: parser error : Start tag expected, '<' not found
log_xmllib_err error: XML Error: invalidxml
log_xmllib_err error: XML Error: ^
log_xmllib_err error: XML Error: Entity: line 1: parser error : Start tag expected, '<' not found
log_xmllib_err error: XML Error: invalidxml
log_xmllib_err error: XML Error: ^
- crm_rule: Couldn't parse input string: invalidxml
-
+ crm_rule: Couldn't parse input string: invalidxml
=#=#=#= End test: crm_rule given invalid input XML (XML) - Invalid data given (65) =#=#=#=
* Passed: crm_rule - crm_rule given invalid input XML (XML)
=#=#=#= Begin test: crm_rule given invalid input XML on stdin =#=#=#=
log_xmllib_err error: XML Error: Entity: line 1: parser error : Start tag expected, '<' not found
log_xmllib_err error: XML Error: invalidxml
log_xmllib_err error: XML Error: ^
log_xmllib_err error: XML Error: Entity: line 1: parser error : Start tag expected, '<' not found
log_xmllib_err error: XML Error: invalidxml
log_xmllib_err error: XML Error: ^
crm_rule: Couldn't parse input from STDIN
-
=#=#=#= End test: crm_rule given invalid input XML on stdin - Invalid data given (65) =#=#=#=
* Passed: echo - crm_rule given invalid input XML on stdin
=#=#=#= Begin test: crm_rule given invalid input XML on stdin (XML) =#=#=#=
log_xmllib_err error: XML Error: Entity: line 1: parser error : Start tag expected, '<' not found
log_xmllib_err error: XML Error: invalidxml
log_xmllib_err error: XML Error: ^
log_xmllib_err error: XML Error: Entity: line 1: parser error : Start tag expected, '<' not found
log_xmllib_err error: XML Error: invalidxml
log_xmllib_err error: XML Error: ^
- crm_rule: Couldn't parse input from STDIN
-
+ crm_rule: Couldn't parse input from STDIN
=#=#=#= End test: crm_rule given invalid input XML on stdin (XML) - Invalid data given (65) =#=#=#=
* Passed: echo - crm_rule given invalid input XML on stdin (XML)
=#=#=#= Begin test: Try to check a rule that doesn't exist =#=#=#=
Could not determine whether rule blahblah is in effect: Rule not found
=#=#=#= Current cib after: Try to check a rule that doesn't exist =#=#=#=
=#=#=#= End test: Try to check a rule that doesn't exist - No such object (105) =#=#=#=
* Passed: crm_rule - Try to check a rule that doesn't exist
=#=#=#= Begin test: Try to check a rule that doesn't exist, with XML output =#=#=#=
Could not determine whether rule blahblah is in effect: Rule not found
=#=#=#= End test: Try to check a rule that doesn't exist, with XML output - No such object (105) =#=#=#=
* Passed: crm_rule - Try to check a rule that doesn't exist, with XML output
=#=#=#= Begin test: Try to check a rule that has too many date_expressions =#=#=#=
Could not determine whether rule cli-rule-too-many-date-expressions is in effect: Rule has more than one date expression
=#=#=#= End test: Try to check a rule that has too many date_expressions - Unimplemented (3) =#=#=#=
* Passed: crm_rule - Try to check a rule that has too many date_expressions
=#=#=#= Begin test: Try to check a rule that has too many date_expressions (XML) =#=#=#=
Could not determine whether rule cli-rule-too-many-date-expressions is in effect: Rule has more than one date expression
=#=#=#= End test: Try to check a rule that has too many date_expressions (XML) - Unimplemented (3) =#=#=#=
* Passed: crm_rule - Try to check a rule that has too many date_expressions (XML)
=#=#=#= Begin test: Verify basic rule is expired =#=#=#=
Rule cli-prefer-rule-dummy-expired is expired
=#=#=#= End test: Verify basic rule is expired - Requested item has expired (110) =#=#=#=
* Passed: crm_rule - Verify basic rule is expired
=#=#=#= Begin test: Verify basic rule is expired, with XML output =#=#=#=
=#=#=#= End test: Verify basic rule is expired, with XML output - Requested item has expired (110) =#=#=#=
* Passed: crm_rule - Verify basic rule is expired, with XML output
=#=#=#= Begin test: Verify basic rule worked in the past =#=#=#=
Rule cli-prefer-rule-dummy-expired is still in effect
=#=#=#= End test: Verify basic rule worked in the past - OK (0) =#=#=#=
* Passed: crm_rule - Verify basic rule worked in the past
=#=#=#= Begin test: Verify basic rule worked in the past (XML) =#=#=#=
=#=#=#= End test: Verify basic rule worked in the past (XML) - OK (0) =#=#=#=
* Passed: crm_rule - Verify basic rule worked in the past (XML)
=#=#=#= Begin test: Verify basic rule is not yet in effect =#=#=#=
Rule cli-prefer-rule-dummy-not-yet has not yet taken effect
=#=#=#= End test: Verify basic rule is not yet in effect - Requested item is not yet in effect (111) =#=#=#=
* Passed: crm_rule - Verify basic rule is not yet in effect
=#=#=#= Begin test: Verify basic rule is not yet in effect (XML) =#=#=#=
=#=#=#= End test: Verify basic rule is not yet in effect (XML) - Requested item is not yet in effect (111) =#=#=#=
* Passed: crm_rule - Verify basic rule is not yet in effect (XML)
=#=#=#= Begin test: Verify date_spec rule with years has expired =#=#=#=
Rule cli-prefer-rule-dummy-date_spec-only-years is expired
=#=#=#= End test: Verify date_spec rule with years has expired - Requested item has expired (110) =#=#=#=
* Passed: crm_rule - Verify date_spec rule with years has expired
=#=#=#= Begin test: Verify date_spec rule with years has expired (XML) =#=#=#=
=#=#=#= End test: Verify date_spec rule with years has expired (XML) - Requested item has expired (110) =#=#=#=
* Passed: crm_rule - Verify date_spec rule with years has expired (XML)
=#=#=#= Begin test: Verify multiple rules at once =#=#=#=
Rule cli-prefer-rule-dummy-not-yet has not yet taken effect
Rule cli-prefer-rule-dummy-date_spec-only-years is expired
=#=#=#= End test: Verify multiple rules at once - Requested item has expired (110) =#=#=#=
* Passed: crm_rule - Verify multiple rules at once
=#=#=#= Begin test: Verify multiple rules at once, with XML output =#=#=#=
=#=#=#= End test: Verify multiple rules at once, with XML output - Requested item has expired (110) =#=#=#=
* Passed: crm_rule - Verify multiple rules at once, with XML output
=#=#=#= Begin test: Verify date_spec rule with years is in effect =#=#=#=
Rule cli-prefer-rule-dummy-date_spec-only-years satisfies conditions
=#=#=#= End test: Verify date_spec rule with years is in effect - OK (0) =#=#=#=
* Passed: crm_rule - Verify date_spec rule with years is in effect
=#=#=#= Begin test: Verify date_spec rule with years is in effect (XML) =#=#=#=
=#=#=#= End test: Verify date_spec rule with years is in effect (XML) - OK (0) =#=#=#=
* Passed: crm_rule - Verify date_spec rule with years is in effect (XML)
=#=#=#= Begin test: Try to check a rule whose date_spec does not contain years= =#=#=#=
Could not determine whether rule cli-prefer-rule-dummy-date_spec-without-years is in effect: Rule must either not use date_spec, or use date_spec with years= but not moon=
=#=#=#= End test: Try to check a rule whose date_spec does not contain years= - Unimplemented (3) =#=#=#=
* Passed: crm_rule - Try to check a rule whose date_spec does not contain years=
=#=#=#= Begin test: Try to check a rule whose date_spec does not contain years= (XML) =#=#=#=
Could not determine whether rule cli-prefer-rule-dummy-date_spec-without-years is in effect: Rule must either not use date_spec, or use date_spec with years= but not moon=
=#=#=#= End test: Try to check a rule whose date_spec does not contain years= (XML) - Unimplemented (3) =#=#=#=
* Passed: crm_rule - Try to check a rule whose date_spec does not contain years= (XML)
=#=#=#= Begin test: Try to check a rule whose date_spec contains years= and moon= =#=#=#=
Could not determine whether rule cli-prefer-rule-dummy-date_spec-years-moon is in effect: Rule must either not use date_spec, or use date_spec with years= but not moon=
=#=#=#= End test: Try to check a rule whose date_spec contains years= and moon= - Unimplemented (3) =#=#=#=
* Passed: crm_rule - Try to check a rule whose date_spec contains years= and moon=
=#=#=#= Begin test: Try to check a rule whose date_spec contains years= and moon= (XML) =#=#=#=
Could not determine whether rule cli-prefer-rule-dummy-date_spec-years-moon is in effect: Rule must either not use date_spec, or use date_spec with years= but not moon=
=#=#=#= End test: Try to check a rule whose date_spec contains years= and moon= (XML) - Unimplemented (3) =#=#=#=
* Passed: crm_rule - Try to check a rule whose date_spec contains years= and moon= (XML)
=#=#=#= Begin test: Try to check a rule with no date_expression =#=#=#=
Could not determine whether rule cli-no-date_expression-rule is in effect: Rule does not have a date expression
=#=#=#= End test: Try to check a rule with no date_expression - Unimplemented (3) =#=#=#=
* Passed: crm_rule - Try to check a rule with no date_expression
=#=#=#= Begin test: Try to check a rule with no date_expression (XML) =#=#=#=
Could not determine whether rule cli-no-date_expression-rule is in effect: Rule does not have a date expression
=#=#=#= End test: Try to check a rule with no date_expression (XML) - Unimplemented (3) =#=#=#=
* Passed: crm_rule - Try to check a rule with no date_expression (XML)
diff --git a/tools/crm_rule.c b/tools/crm_rule.c
index eb8f3f0765..2a735c1352 100644
--- a/tools/crm_rule.c
+++ b/tools/crm_rule.c
@@ -1,227 +1,228 @@
/*
* Copyright 2019-2024 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
* This source code is licensed under the GNU General Public License version 2
* or later (GPLv2+) WITHOUT ANY WARRANTY.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define SUMMARY "evaluate rules from the Pacemaker configuration"
static pcmk__supported_format_t formats[] = {
PCMK__SUPPORTED_FORMAT_NONE,
PCMK__SUPPORTED_FORMAT_TEXT,
PCMK__SUPPORTED_FORMAT_XML,
{ NULL, NULL, NULL }
};
enum crm_rule_mode {
crm_rule_mode_none,
crm_rule_mode_check
};
struct {
char *date;
char *input_xml;
enum crm_rule_mode mode;
gchar **rules;
} options = {
.mode = crm_rule_mode_none
};
static gboolean mode_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error);
static GOptionEntry mode_entries[] = {
{ "check", 'c', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, mode_cb,
"Check whether a rule is in effect",
NULL },
{ NULL }
};
static GOptionEntry data_entries[] = {
{ "xml-text", 'X', 0, G_OPTION_ARG_STRING, &options.input_xml,
"Use argument for XML (or stdin if '-')",
NULL },
{ NULL }
};
static GOptionEntry addl_entries[] = {
{ "date", 'd', 0, G_OPTION_ARG_STRING, &options.date,
"Whether the rule is in effect on a given date",
NULL },
{ "rule", 'r', 0, G_OPTION_ARG_STRING_ARRAY, &options.rules,
"The ID of the rule to check (may be specified multiple times)",
NULL },
{ NULL }
};
static gboolean
mode_cb(const gchar *option_name, const gchar *optarg, gpointer data, GError **error) {
if (strcmp(option_name, "c")) {
options.mode = crm_rule_mode_check;
}
return TRUE;
}
static GOptionContext *
build_arg_context(pcmk__common_args_t *args, GOptionGroup **group) {
GOptionContext *context = NULL;
context = pcmk__build_arg_context(args, "text (default), xml", group, NULL);
pcmk__add_arg_group(context, "modes", "Modes (mutually exclusive):",
"Show modes of operation", mode_entries);
pcmk__add_arg_group(context, "data", "Data:",
"Show data options", data_entries);
pcmk__add_arg_group(context, "additional", "Additional Options:",
"Show additional options", addl_entries);
return context;
}
int
main(int argc, char **argv)
{
crm_time_t *rule_date = NULL;
xmlNode *input = NULL;
int rc = pcmk_rc_ok;
crm_exit_t exit_code = CRM_EX_OK;
GError *error = NULL;
pcmk__output_t *out = NULL;
GOptionGroup *output_group = NULL;
pcmk__common_args_t *args = pcmk__new_common_args(SUMMARY);
GOptionContext *context = build_arg_context(args, &output_group);
gchar **processed_args = pcmk__cmdline_preproc(argv, "drX");
pcmk__register_formats(output_group, formats);
if (!g_option_context_parse_strv(context, &processed_args, &error)) {
exit_code = CRM_EX_USAGE;
goto done;
}
pcmk__cli_init_logging("crm_rule", args->verbosity);
rc = pcmk__output_new(&out, args->output_ty, args->output_dest, argv);
if (rc != pcmk_rc_ok) {
exit_code = CRM_EX_ERROR;
g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Error creating output format %s: %s",
args->output_ty, pcmk_rc_str(rc));
goto done;
}
pcmk__register_lib_messages(out);
if (args->version) {
out->version(out, false);
goto done;
}
/* Check command line arguments before opening a connection to
* the CIB manager or doing anything else important.
*/
switch(options.mode) {
case crm_rule_mode_check:
if (options.rules == NULL) {
exit_code = CRM_EX_USAGE;
g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "--check requires use of --rule=");
goto done;
}
break;
default:
exit_code = CRM_EX_USAGE;
g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "No mode operation given");
goto done;
break;
}
/* Set up some defaults. */
rule_date = crm_time_new(options.date);
if (rule_date == NULL) {
if (options.date != NULL) {
exit_code = CRM_EX_DATAERR;
g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
"Invalid date specified: '%s'", options.date);
} else {
// Should never happen
exit_code = CRM_EX_OSERR;
g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
"No --date given and can't determine current date");
}
goto done;
}
// Parse the input XML specified by the command-line options, if any
if (pcmk__str_eq(options.input_xml, "-", pcmk__str_casei)) {
input = stdin2xml();
if (input == NULL) {
exit_code = CRM_EX_DATAERR;
- g_set_error(&error, PCMK__EXITC_ERROR, exit_code, "Couldn't parse input from STDIN\n");
+ g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
+ "Couldn't parse input from STDIN");
goto done;
}
} else if (options.input_xml != NULL) {
input = string2xml(options.input_xml);
if (input == NULL) {
exit_code = CRM_EX_DATAERR;
g_set_error(&error, PCMK__EXITC_ERROR, exit_code,
- "Couldn't parse input string: %s\n", options.input_xml);
+ "Couldn't parse input string: %s", options.input_xml);
goto done;
}
}
/* Now do whichever operation mode was asked for. There's only one at the
* moment so this looks a little silly, but I expect there will be more
* modes in the future.
*/
switch(options.mode) {
case crm_rule_mode_check:
rc = pcmk__check_rules(out, input, rule_date,
(const char **) options.rules);
exit_code = pcmk_rc2exitc(rc);
break;
default:
break;
}
done:
g_strfreev(processed_args);
pcmk__free_arg_context(context);
crm_time_free(rule_date);
free_xml(input);
pcmk__output_and_clear_error(&error, out);
if (out != NULL) {
out->finish(out, exit_code, true, NULL);
pcmk__output_free(out);
}
pcmk__unregister_formats();
return crm_exit(exit_code);
}