MINOR: config: add predicate "feature" to detect certain built-in features

The "feature(name)" predicate will return true if <name> corresponds to
a name listed after a '+' in the features list, that is it was enabled at
build time with USE_<name>=1. Typical use cases will include OPENSSL, LUA
and LINUX_SPLICE. But maybe it will also be convenient to use with optional
addons such as PROMEX and the device detection modules to help keeping the
same configs across various deployments.
This commit is contained in:
Willy Tarreau 2021-05-06 16:34:23 +02:00
parent 6492e87b0e
commit 58ca706e16
2 changed files with 29 additions and 0 deletions

View File

@ -814,6 +814,10 @@ The list of currently supported predicates is the following:
- defined(<name>) : returns true if an environment variable <name>
exists, regardless of its contents
- feature(<name>) : returns true if feature <name> is listed as present
in the features list reported by "haproxy -vv"
(which means a <name> appears after a '+')
- streq(<str1>,<str2>) : returns true only if the two strings are equal
- strneq(<str1>,<str2>) : returns true only if the two strings differ
@ -830,7 +834,9 @@ Example:
.endif
.if streq("$WITH_SSL",yes)
.if feature(OPENSSL)
bind :443 ssl crt ...
.endif
.endif
Three other directives are provided to report some status:

View File

@ -137,6 +137,7 @@ enum nested_cond_state {
enum cond_predicate {
CFG_PRED_NONE, // none
CFG_PRED_DEFINED, // "defined"
CFG_PRED_FEATURE, // "feature"
CFG_PRED_STREQ, // "streq"
CFG_PRED_STRNEQ, // "strneq"
};
@ -150,6 +151,7 @@ struct cond_pred_kw {
/* supported condition predicates */
const struct cond_pred_kw cond_predicates[] = {
{ "defined", CFG_PRED_DEFINED, ARG1(1, STR) },
{ "feature", CFG_PRED_FEATURE, ARG1(1, STR) },
{ "streq", CFG_PRED_STREQ, ARG2(2, STR, STR) },
{ "strneq", CFG_PRED_STRNEQ, ARG2(2, STR, STR) },
{ NULL, CFG_PRED_NONE, 0 }
@ -1722,6 +1724,27 @@ static int cfg_eval_condition(char **args, char **err, const char **errptr)
ret = getenv(argp[0].data.str.area) != NULL;
goto done;
case CFG_PRED_FEATURE: { // checks if the arg matches an enabled feature
const char *p;
for (p = build_features; (p = strstr(p, argp[0].data.str.area)); p++) {
if ((p[argp[0].data.str.data] == ' ' || p[argp[0].data.str.data] == 0) &&
p > build_features) {
if (*(p-1) == '+') { // "+OPENSSL"
ret = 1;
goto done;
}
else if (*(p-1) == '-') { // "-OPENSSL"
ret = 0;
goto done;
}
/* it was a sub-word, let's restart from next place */
}
}
/* not found */
ret = 0;
goto done;
}
case CFG_PRED_STREQ: // checks if the two arg are equal
ret = strcmp(argp[0].data.str.area, argp[1].data.str.area) == 0;
goto done;