ignored. The directives are tokenized like other configuration directives, and
as such it is possible to use environment variables in conditions.
+Conditions can also be evaluated on startup with the -cc parameter.
+See "3. Starting HAProxy" in the management doc.
+
The conditions are currently limited to:
- an empty string, always returns "false"
to bind. The exit status is zero if everything is OK, or non-zero if an
error is encountered. Presence of warnings will be reported if any.
+ -cc : evaluates a condition as used within a conditional block of the
+ configuration. The exit status is zero if the condition is true, 1 if the
+ condition is false or 2 if an error is encountered.
+
-d : enable debug mode. This disables daemon mode, forces the process to stay
in foreground and to show incoming and outgoing events. It must never be
used in an init script.
const char *cfg_find_best_match(const char *word, const struct list *list, int section, const char **extra);
int warnifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint);
int failifnotcap(struct proxy *proxy, int cap, const char *file, int line, const char *arg, const char *hint);
+int cfg_eval_condition(char **args, char **err, const char **errptr);
/* simplified way to define a section parser */
#define REGISTER_CONFIG_SECTION(name, parse, post) \
#define MODE_MWORKER_WAIT 0x100 /* Master Worker wait mode */
#define MODE_ZERO_WARNING 0x200 /* warnings cause a failure */
#define MODE_DIAG 0x400 /* extra warnings */
+#define MODE_CHECK_CONDITION 0x800 /* -cc mode */
/* list of last checks to perform, depending on config options */
#define LSTCHK_CAP_BIND 0x00000001 /* check that we can bind to any port */
--- /dev/null
+varnishtest "Tests the -cc argument"
+
+#REQUIRE_VERSION=2.5
+feature cmd "$HAPROXY_PROGRAM -cc 'version_atleast(2.5-dev0)'"
+
+shell {
+ $HAPROXY_PROGRAM -cc "version_atleast(2.4)"
+ ! $HAPROXY_PROGRAM -cc "version_atleast(1024)"
+
+ $HAPROXY_PROGRAM -cc "streq(foo,'foo')"
+ $HAPROXY_PROGRAM -cc "streq(\"foo bar\",'foo bar')"
+ ! $HAPROXY_PROGRAM -cc "streq(foo,bar)"
+} -run
* and only in this case), 0 if the condition is false, 1 if it's true. If
* <errptr> is not NULL, it's set to the first invalid character on error.
*/
-static int cfg_eval_condition(char **args, char **err, const char **errptr)
+int cfg_eval_condition(char **args, char **err, const char **errptr)
{
const struct cond_pred_kw *cond_pred = NULL;
const char *end_ptr;
#endif
" -q quiet mode : don't display messages\n"
" -c check mode : only check config files and exit\n"
+ " -cc check condition : evaluate a condition and exit\n"
" -n sets the maximum total # of connections (uses ulimit -n)\n"
" -m limits the usable amount of memory (in MB)\n"
" -N sets the default, per-proxy maximum # of connections (%d)\n"
struct proxy *px;
struct post_check_fct *pcf;
int ideal_maxconn;
+ char *check_condition = NULL;
global.mode = MODE_STARTING;
old_argv = copy_argv(argc, argv);
global.tune.options |= GTUNE_RESOLVE_DONTFAIL;
else if (*flag == 'd')
arg_mode |= MODE_DEBUG;
+ else if (*flag == 'c' && flag[1] == 'c') {
+ arg_mode |= MODE_CHECK_CONDITION;
+ argv++;
+ argc--;
+ check_condition = *argv;
+ }
else if (*flag == 'c')
arg_mode |= MODE_CHECK;
else if (*flag == 'D')
global.mode |= (arg_mode & (MODE_DAEMON | MODE_MWORKER | MODE_FOREGROUND | MODE_VERBOSE
| MODE_QUIET | MODE_CHECK | MODE_DEBUG | MODE_ZERO_WARNING
- | MODE_DIAG));
+ | MODE_DIAG | MODE_CHECK_CONDITION));
if (getenv("HAPROXY_MWORKER_WAIT_ONLY")) {
unsetenv("HAPROXY_MWORKER_WAIT_ONLY");
usermsgs_clr("config");
+ if (global.mode & MODE_CHECK_CONDITION) {
+ int result;
+
+ uint32_t err;
+ const char *errptr;
+ char *errmsg = NULL;
+
+ char *args[MAX_LINE_ARGS+1];
+ int arg = sizeof(args) / sizeof(*args);
+ size_t outlen = strlen(check_condition) + 1;
+
+ err = parse_line(check_condition, check_condition, &outlen, args, &arg,
+ PARSE_OPT_DQUOTE | PARSE_OPT_SQUOTE | PARSE_OPT_BKSLASH,
+ &errptr);
+
+ if (err & PARSE_ERR_QUOTE) {
+ ha_alert("Syntax Error in condition: Unmatched quote.\n");
+ exit(2);
+ }
+
+ if (err & PARSE_ERR_HEX) {
+ ha_alert("Syntax Error in condition: Truncated or invalid hexadecimal sequence.\n");
+ exit(2);
+ }
+
+ if (err & (PARSE_ERR_TOOLARGE|PARSE_ERR_OVERLAP)) {
+ ha_alert("Error in condition: Line too long.\n");
+ exit(2);
+ }
+
+ if (err & PARSE_ERR_TOOMANY) {
+ ha_alert("Error in condition: Too many words.\n");
+ exit(2);
+ }
+
+ if (err) {
+ ha_alert("Unhandled error in condition, please report this to the developers.\n");
+ exit(2);
+ }
+
+ result = cfg_eval_condition(args, &errmsg, &errptr);
+
+ if (result < 0) {
+ if (errmsg)
+ ha_alert("Failed to evaluate condition: %s\n", errmsg);
+
+ exit(2);
+ }
+
+ exit(result ? 0 : 1);
+ }
+
/* in wait mode, we don't try to read the configuration files */
if (!(global.mode & MODE_MWORKER_WAIT)) {
char *env_cfgfiles = NULL;