]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: cfgparse: implement experimental config keywords
authorAmaury Denoyelle <adenoyelle@haproxy.com>
Thu, 6 May 2021 14:21:39 +0000 (16:21 +0200)
committerAmaury Denoyelle <adenoyelle@haproxy.com>
Fri, 7 May 2021 12:34:41 +0000 (14:34 +0200)
Add a new flag to mark a keyword as experimental. An experimental
keyword cannot be used if the global 'expose-experimental-directives' is
not present first.

Only keywords parsed through a standard cfg_keywords lists in
global/proxies section will be automatically detected if declared
experimental. To support a keyword outside of these lists,
check_kw_experimental must be called manually during its parsing.

If an experimental keyword is present in the config, the tainted flag is
updated.

For the moment, no keyword is marked as experimental.

doc/configuration.txt
include/haproxy/cfgparse.h
include/haproxy/global.h
src/cfgparse-global.c
src/cfgparse-listen.c
src/haproxy.c

index e37f84cf6b05beb43ae260a7603a522529cf10e1..19f180884f1c1539501229733f343f26b6a753c4 100644 (file)
@@ -969,6 +969,7 @@ The following keywords are supported in the "global" section :
    - deviceatlas-log-level
    - deviceatlas-separator
    - deviceatlas-properties-cookie
+   - expose-experimental-directives
    - external-check
    - gid
    - group
@@ -1274,6 +1275,10 @@ deviceatlas-properties-cookie <name>
   Client-side component was used during the request. This directive is optional
   and set to DAPROPS by default if not set.
 
+expose-experimental-directives
+  This statement must appear before using directives tagged as experimental or
+  the config file will be rejected.
+
 external-check
   Allows the use of an external agent to perform health checks. This is
   disabled by default as a security precaution, and even when enabled, checks
index b32c90dca7cde6aa5b8b1595b1a85b8a2a9b16aa..83c031db8fd49c72af659867bb8784ecc4bbd760 100644 (file)
@@ -43,7 +43,7 @@ enum kw_mod {
 };
 
 enum cfg_keyword_flags {
-       KWF_UNIMPLEMENTED,  // TO REMOVE once an enum value is implemented
+       KWF_EXPERIMENTAL = 0x1,
 };
 
 struct cfg_keyword {
index 20a0950ea25e2823a0f47dad8aa5a73a3ec03659..fb7b62b6c8ca92dfd003033422ffe20a2b4fcfcd 100644 (file)
@@ -98,11 +98,17 @@ static inline unsigned long thread_mask(unsigned long mask)
 
 /* handle 'tainted' status */
 enum tainted_flags {
-       TAINTED_UNIMPLEMENTED,  // TO REMOVE once an enum value is implemented
+       TAINTED_CONFIG_EXP_KW_DECLARED = 0x1,
 };
 void mark_tainted(const enum tainted_flags flag);
 unsigned int get_tainted();
 
+extern unsigned int experimental_directives_allowed;
+
+struct cfg_keyword;
+int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
+                          char **errmsg);
+
 /* simplified way to declare static build options in a file */
 #define REGISTER_BUILD_OPTS(str) \
        INITCALL2(STG_REGISTER, hap_register_build_opts, (str), 0)
index 384ad3c960db23908b15becad0605caa530fe0f0..98012d1645c7545404fbcd0e5ad76f4319a843e8 100644 (file)
@@ -70,6 +70,9 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
                alertif_too_many_args(0, file, linenum, args, &err_code);
                goto out;
        }
+       else if (strcmp(args[0], "expose-experimental-directives") == 0) {
+               experimental_directives_allowed = 1;
+       }
        else if (strcmp(args[0], "daemon") == 0) {
                if (alertif_too_many_args(0, file, linenum, args, &err_code))
                        goto out;
@@ -1306,6 +1309,12 @@ int cfg_parse_global(const char *file, int linenum, char **args, int kwm)
                                if (kwl->kw[index].section != CFG_GLOBAL)
                                        continue;
                                if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
+                                       if (check_kw_experimental(&kwl->kw[index], file, linenum, &errmsg)) {
+                                               ha_alert(errmsg);
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
+                                       }
+
                                        rc = kwl->kw[index].parse(args, CFG_GLOBAL, NULL, NULL, file, linenum, &errmsg);
                                        if (rc < 0) {
                                                ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg);
index 8a81b442d773eeed9c647c3f06068c52eb55e0de..78f1a5875ea06fa315afc283d0915a1cc35a81fa 100644 (file)
@@ -3040,6 +3040,12 @@ stats_error_parsing:
                                if (kwl->kw[index].section != CFG_LISTEN)
                                        continue;
                                if (strcmp(kwl->kw[index].kw, args[0]) == 0) {
+                                       if (check_kw_experimental(&kwl->kw[index], file, linenum, &errmsg)) {
+                                               ha_alert(errmsg);
+                                               err_code |= ERR_ALERT | ERR_FATAL;
+                                               goto out;
+                                       }
+
                                        /* prepare error message just in case */
                                        rc = kwl->kw[index].parse(args, CFG_LISTEN, curproxy, curr_defproxy, file, linenum, &errmsg);
                                        if (rc < 0) {
index 4c7ff556eab5b98ce7efd210f2e12b32ad35e97b..0ca87802e1501f1d0a28c4a1f6176d8bcb71918f 100644 (file)
@@ -262,6 +262,23 @@ unsigned int warned = 0;
 /* set if experimental features have been used for the current process */
 static unsigned int tainted = 0;
 
+unsigned int experimental_directives_allowed = 0;
+
+int check_kw_experimental(struct cfg_keyword *kw, const char *file, int linenum,
+                          char **errmsg)
+{
+       if (kw->flags & KWF_EXPERIMENTAL) {
+               if (!experimental_directives_allowed) {
+                       memprintf(errmsg, "parsing [%s:%d] : '%s' directive is experimental, must be allowed via a global 'expose-experimental-directives'\n",
+                                 file, linenum, kw->kw);
+                       return 1;
+               }
+               mark_tainted(TAINTED_CONFIG_EXP_KW_DECLARED);
+       }
+
+       return 0;
+}
+
 /* master CLI configuration (-S flag) */
 struct list mworker_cli_conf = LIST_HEAD_INIT(mworker_cli_conf);