mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-01-15 13:51:00 +01:00
MEDIUM: proxy: implement publish/unpublish backend CLI
Define a new set of CLI commands publish/unpublish backend <be>. The objective is to be able to change the status of a backend to unpublished. Such a backend is considered ineligible to traffic : this allows to skip use_backend rules which target it. Note that contrary to disabled/stopped proxies, an unpublished backend still has server checks running on it. Internally, a new proxy flags PR_FL_BE_UNPUBLISHED is defined. CLI commands handler "publish backend" and "unpublish backend" are executed under thread isolation. This guarantees that the flag can safely be set or remove in the CLI handlers, and read during content-switching processing.
This commit is contained in:
parent
21fb0a3f58
commit
797ec6ede5
@ -7103,8 +7103,8 @@ default_backend <backend>
|
||||
used when no rule has matched. It generally is the dynamic backend which
|
||||
will catch all undetermined requests.
|
||||
|
||||
If a backend used as default is disabled, no traffic will be redirected to
|
||||
it.
|
||||
If a backend is disabled or unpublished, default_backend rules targetting it
|
||||
will be ignored and stream processing will remain on the original proxy.
|
||||
|
||||
Example :
|
||||
|
||||
@ -14756,16 +14756,16 @@ use_backend <backend> [{if | unless} <condition>]
|
||||
There may be as many "use_backend" rules as desired. All of these rules are
|
||||
evaluated in their declaration order, and the first one which matches will
|
||||
assign the backend. This is even the case if the backend is considered as
|
||||
down. However, if a matching rule targets a disabled backend, it is ignored
|
||||
instead and rules evaluation continue.
|
||||
down. However, if a matching rule targets a disabled or unpublished backend,
|
||||
it is ignored instead and rules evaluation continue.
|
||||
|
||||
In the first form, the backend will be used if the condition is met. In the
|
||||
second form, the backend will be used if the condition is not met. If no
|
||||
condition is valid, the backend defined with "default_backend" will be used
|
||||
unless it is disabled. If no default backend is defined, either the servers
|
||||
in the same section are used (in case of a "listen" section) or, in case of a
|
||||
frontend, no server is used and a 503 service unavailable response is
|
||||
returned.
|
||||
unless it is disabled or unpublished. If no default backend is available,
|
||||
either the servers in the same section are used (in case of a "listen"
|
||||
section) or, in case of a frontend, no server is used and a 503 service
|
||||
unavailable response is returned.
|
||||
|
||||
Note that it is possible to switch from a TCP frontend to an HTTP backend. In
|
||||
this case, either the frontend has already checked that the protocol is HTTP,
|
||||
|
||||
@ -2474,6 +2474,11 @@ prompt [help | n | i | p | timed]*
|
||||
advanced scripts, and the non-interactive mode (default) to basic scripts.
|
||||
Note that the non-interactive mode is not available for the master socket.
|
||||
|
||||
publish backend <backend>
|
||||
Activates content switching to a backend instance. This is the reverse
|
||||
operation of "unpublish backend" command. This command is restricted and can
|
||||
only be issued on sockets configured for levels "operator" or "admin".
|
||||
|
||||
quit
|
||||
Close the connection when in interactive mode.
|
||||
|
||||
@ -2842,6 +2847,13 @@ operator
|
||||
increased. It also drops expert and experimental mode. See also "show cli
|
||||
level".
|
||||
|
||||
unpublish backend <backend>
|
||||
Marks the backend as unqualified for future traffic selection. In effect,
|
||||
use_backend / default_backend rules which reference it are ignored and the
|
||||
next content switching rules are evaluated. Contrary to disabled backends,
|
||||
servers health checks remain active. This command is restricted and can only
|
||||
be issued on sockets configured for levels "operator" or "admin".
|
||||
|
||||
user
|
||||
Decrease the CLI level of the current CLI session to user. It can't be
|
||||
increased. It also drops expert and experimental mode. See also "show cli
|
||||
|
||||
@ -88,11 +88,11 @@ static inline int be_usable_srv(struct proxy *be)
|
||||
/* Returns true if <be> backend can be used as target to a switching rules. */
|
||||
static inline int be_is_eligible(const struct proxy *be)
|
||||
{
|
||||
/* A disabled backend cannot be selected for traffic. Note that STOPPED
|
||||
* state is ignored as there is a risk of breaking requests during
|
||||
* soft-stop.
|
||||
/* A disabled or unpublished backend cannot be selected for traffic.
|
||||
* Note that STOPPED state is ignored as there is a risk of breaking
|
||||
* requests during soft-stop.
|
||||
*/
|
||||
return !(be->flags & PR_FL_DISABLED);
|
||||
return !(be->flags & (PR_FL_DISABLED|PR_FL_BE_UNPUBLISHED));
|
||||
}
|
||||
|
||||
/* set the time of last session on the backend */
|
||||
|
||||
@ -247,6 +247,7 @@ enum PR_SRV_STATE_FILE {
|
||||
#define PR_FL_IMPLICIT_REF 0x10 /* The default proxy is implicitly referenced by another proxy */
|
||||
#define PR_FL_PAUSED 0x20 /* The proxy was paused at run time (reversible) */
|
||||
#define PR_FL_CHECKED 0x40 /* The proxy configuration was fully checked (including postparsing checks) */
|
||||
#define PR_FL_BE_UNPUBLISHED 0x80 /* The proxy cannot be targetted by content switching rules */
|
||||
|
||||
struct stream;
|
||||
|
||||
|
||||
@ -42,6 +42,7 @@ haproxy h1 -conf {
|
||||
use_backend %[req.hdr("x-target")] if { req.hdr("x-dyn") "1" }
|
||||
use_backend be_disabled if { req.hdr("x-target") "be_disabled" }
|
||||
use_backend be
|
||||
use_backend be2
|
||||
default_backend be_default
|
||||
|
||||
listen li
|
||||
@ -52,6 +53,9 @@ haproxy h1 -conf {
|
||||
backend be
|
||||
http-request return status 200 hdr "x-be" %[be_name]
|
||||
|
||||
backend be2
|
||||
http-request return status 200 hdr "x-be" %[be_name]
|
||||
|
||||
backend be_disabled
|
||||
disabled
|
||||
http-request return status 200 hdr "x-be" %[be_name]
|
||||
@ -108,3 +112,47 @@ client c3 -connect ${h1_liS_sock} {
|
||||
expect resp.status == 200
|
||||
expect resp.http.x-be == "li"
|
||||
} -run
|
||||
|
||||
haproxy h1 -cli {
|
||||
send "unpublish backend be_unknown"
|
||||
expect ~ "No such backend."
|
||||
|
||||
send "unpublish backend be_disabled"
|
||||
expect ~ "No effect on a disabled backend."
|
||||
|
||||
send "unpublish backend be"
|
||||
expect ~ "Backend unpublished."
|
||||
}
|
||||
|
||||
client c4 -connect ${h1_fe2S_sock} {
|
||||
# Static rule on unpublished backend -> continue to next rule
|
||||
txreq
|
||||
rxresp
|
||||
expect resp.status == 200
|
||||
expect resp.http.x-be == "be2"
|
||||
|
||||
# Dynamic rule on unpublished backend -> continue to next rule
|
||||
txreq -hdr "x-dyn: 1" -hdr "x-target: be"
|
||||
rxresp
|
||||
expect resp.status == 200
|
||||
expect resp.http.x-be == "be2"
|
||||
} -run
|
||||
|
||||
haproxy h1 -cli {
|
||||
send "publish backend be"
|
||||
expect ~ "Backend published."
|
||||
}
|
||||
|
||||
client c5 -connect ${h1_fe2S_sock} {
|
||||
# Static rule matching on republished backend
|
||||
txreq -hdr "x-target: be"
|
||||
rxresp
|
||||
expect resp.status == 200
|
||||
expect resp.http.x-be == "be"
|
||||
|
||||
# Dynamic rule matching on republished backend
|
||||
txreq -hdr "x-dyn: 1" -hdr "x-target: be"
|
||||
rxresp
|
||||
expect resp.status == 200
|
||||
expect resp.http.x-be == "be"
|
||||
} -run
|
||||
|
||||
50
src/proxy.c
50
src/proxy.c
@ -3360,6 +3360,54 @@ static int cli_parse_enable_frontend(char **args, char *payload, struct appctx *
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int cli_parse_publish_backend(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct proxy *px;
|
||||
|
||||
usermsgs_clr("CLI");
|
||||
|
||||
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
|
||||
return 1;
|
||||
|
||||
px = cli_find_backend(appctx, args[2]);
|
||||
if (!px)
|
||||
return cli_err(appctx, "No such backend.\n");
|
||||
|
||||
if (px->flags & PR_FL_DISABLED)
|
||||
return cli_err(appctx, "No effect on a disabled backend.\n");
|
||||
|
||||
thread_isolate();
|
||||
px->flags &= ~PR_FL_BE_UNPUBLISHED;
|
||||
thread_release();
|
||||
|
||||
ha_notice("Backend published.\n");
|
||||
return cli_umsg(appctx, LOG_INFO);
|
||||
}
|
||||
|
||||
static int cli_parse_unpublish_backend(char **args, char *payload, struct appctx *appctx, void *private)
|
||||
{
|
||||
struct proxy *px;
|
||||
|
||||
usermsgs_clr("CLI");
|
||||
|
||||
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
|
||||
return 1;
|
||||
|
||||
px = cli_find_backend(appctx, args[2]);
|
||||
if (!px)
|
||||
return cli_err(appctx, "No such backend.\n");
|
||||
|
||||
if (px->flags & PR_FL_DISABLED)
|
||||
return cli_err(appctx, "No effect on a disabled backend.\n");
|
||||
|
||||
thread_isolate();
|
||||
px->flags |= PR_FL_BE_UNPUBLISHED;
|
||||
thread_release();
|
||||
|
||||
ha_notice("Backend unpublished.\n");
|
||||
return cli_umsg(appctx, LOG_INFO);
|
||||
}
|
||||
|
||||
/* appctx context used during "show errors" */
|
||||
struct show_errors_ctx {
|
||||
struct proxy *px; /* current proxy being dumped, NULL = not started yet. */
|
||||
@ -3574,12 +3622,14 @@ static int cli_io_handler_show_errors(struct appctx *appctx)
|
||||
static struct cli_kw_list cli_kws = {{ },{
|
||||
{ { "disable", "frontend", NULL }, "disable frontend <frontend> : temporarily disable specific frontend", cli_parse_disable_frontend, NULL, NULL },
|
||||
{ { "enable", "frontend", NULL }, "enable frontend <frontend> : re-enable specific frontend", cli_parse_enable_frontend, NULL, NULL },
|
||||
{ { "publish", "backend", NULL }, "publish backend <backend> : mark backend as ready for traffic", cli_parse_publish_backend, NULL, NULL },
|
||||
{ { "set", "maxconn", "frontend", NULL }, "set maxconn frontend <frontend> <value> : change a frontend's maxconn setting", cli_parse_set_maxconn_frontend, NULL },
|
||||
{ { "show","servers", "conn", NULL }, "show servers conn [<backend>] : dump server connections status (all or for a single backend)", cli_parse_show_servers, cli_io_handler_servers_state },
|
||||
{ { "show","servers", "state", NULL }, "show servers state [<backend>] : dump volatile server information (all or for a single backend)", cli_parse_show_servers, cli_io_handler_servers_state },
|
||||
{ { "show", "backend", NULL }, "show backend : list backends in the current running config", NULL, cli_io_handler_show_backend },
|
||||
{ { "shutdown", "frontend", NULL }, "shutdown frontend <frontend> : stop a specific frontend", cli_parse_shutdown_frontend, NULL, NULL },
|
||||
{ { "set", "dynamic-cookie-key", "backend", NULL }, "set dynamic-cookie-key backend <bk> <k> : change a backend secret key for dynamic cookies", cli_parse_set_dyncookie_key_backend, NULL },
|
||||
{ { "unpublish", "backend", NULL }, "unpublish backend <backend> : remove backend for traffic processing", cli_parse_unpublish_backend, NULL, NULL },
|
||||
{ { "enable", "dynamic-cookie", "backend", NULL }, "enable dynamic-cookie backend <bk> : enable dynamic cookies on a specific backend", cli_parse_enable_dyncookie_backend, NULL },
|
||||
{ { "disable", "dynamic-cookie", "backend", NULL }, "disable dynamic-cookie backend <bk> : disable dynamic cookies on a specific backend", cli_parse_disable_dyncookie_backend, NULL },
|
||||
{ { "show", "errors", NULL }, "show errors [<px>] [request|response] : report last request and/or response errors for each proxy", cli_parse_show_errors, cli_io_handler_show_errors, NULL },
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user