diff --git a/doc/configuration.txt b/doc/configuration.txt index 5034b45ee..00981cc5e 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -3119,15 +3119,10 @@ timeout client ---------- Proxy configuration can be located in a set of sections : - - defaults [] - - frontend - - backend - - listen - -A "defaults" section sets default parameters for all other sections following -its declaration. Those default parameters are reset by the next "defaults" -section. See below for the list of parameters which can be set in a "defaults" -section. The name is optional but its use is encouraged for better readability. + - defaults [] [ from ] + - frontend [ from ] + - backend [ from ] + - listen [ from ] A "frontend" section describes a set of listening sockets accepting client connections. @@ -3138,6 +3133,29 @@ to forward incoming connections. A "listen" section defines a complete proxy with its frontend and backend parts combined in one section. It is generally useful for TCP-only traffic. +A "defaults" section resets all settings to the documented ones and presets new +ones for use by subsequent sections. All of "frontend", "backend" and "listen" +sections always take their initial settings from a defaults section, by default +the latest one that appears before the newly created section. It is possible to +explicitly designate a specific "defaults" section to load the initial settings +from by indicating its name on the section line after the optional keyword +"from". While "defaults" section do not impose a name, this use is encouraged +for better readability. It is also the only way to designate a specific section +to use instead of the default previous one. Since "defaults" section names are +optional, by default a very permissive check is applied on their name and these +are even permitted to overlap. However if a "defaults" section is referenced by +any other section, its name must comply with the syntax imposed on all proxy +names, and this name must be unique among the defaults sections. Please note +that regardless of what is currently permitted, it is recommended to avoid +duplicate section names in general and to respect the same syntax as for proxy +names. This rule might be enforced in a future version. + +Note that it is even possible for a defaults section to take its initial +settings from another one, and as such, inherit settings across multiple levels +of defaults sections. This can be convenient to establish certain configuration +profiles to carry groups of default settings (e.g. TCP vs HTTP or short vs long +timeouts) but can quickly become confusing to follow. + All proxy names must be formed from upper and lower case letters, digits, '-' (dash), '_' (underscore) , '.' (dot) and ':' (colon). ACL names are case-sensitive, which means that "www" and "WWW" are two different proxies. diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index a87358a76..bb57be995 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -237,7 +237,8 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) err_code |= ERR_ALERT | ERR_FATAL; } - if (alertif_too_many_args(1, file, linenum, args, &err_code)) { + if ((*args[2] && (!*args[3] || strcmp(args[2], "from") != 0)) || + alertif_too_many_args(3, file, linenum, args, &err_code)) { if (rc & PR_CAP_FE) ha_alert("parsing [%s:%d] : please use the 'bind' keyword for listening addresses.\n", file, linenum); goto out; @@ -245,7 +246,46 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) } if (rc & PR_CAP_LISTEN) { /* new proxy or defaults section */ - curproxy = alloc_new_proxy(args[1], rc, file, linenum, curr_defproxy, &errmsg); + const char *name = args[1]; + int arg = 2; + + if (rc & PR_CAP_DEF && strcmp(args[1], "from") == 0 && *args[2] && !*args[3]) { + // also support "defaults from blah" (no name then) + arg = 1; + name = ""; + } + + /* only regular proxies inherit from the previous defaults section */ + if (!(rc & PR_CAP_DEF)) + curr_defproxy = last_defproxy; + + if (strcmp(args[arg], "from") == 0) { + curr_defproxy = proxy_find_by_name(args[arg+1], PR_CAP_DEF, 0); + + if (!curr_defproxy) { + ha_alert("parsing [%s:%d] : defaults section '%s' not found for %s '%s'.\n", file, linenum, args[arg+1], proxy_cap_str(rc), name); + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + + if (ebpt_next_dup(&curr_defproxy->conf.by_name)) { + struct proxy *px2 = container_of(ebpt_next_dup(&curr_defproxy->conf.by_name), struct proxy, conf.by_name); + + ha_alert("parsing [%s:%d] : ambiguous defaults section name '%s' referenced by %s '%s' exists at least at %s:%d and %s:%d.\n", + file, linenum, args[arg+1], proxy_cap_str(rc), name, + curr_defproxy->conf.file, curr_defproxy->conf.line, px2->conf.file, px2->conf.line); + err_code |= ERR_ALERT | ERR_FATAL; + } + + err = invalid_char(args[arg+1]); + if (err) { + ha_alert("parsing [%s:%d] : character '%c' is not permitted in defaults section name '%s' when designated by its name (section found at %s:%d).\n", + file, linenum, *err, args[arg+1], curr_defproxy->conf.file, curr_defproxy->conf.line); + err_code |= ERR_ALERT | ERR_FATAL; + } + } + + curproxy = alloc_new_proxy(name, rc, file, linenum, curr_defproxy, &errmsg); if (!curproxy) { ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg); err_code |= ERR_ALERT | ERR_ABORT;