[PATCH 0/1] reg-tests fix.
From: Frédéric Lécaille Hi ML, Here is a little patch to fix the reg tests with missing REQUIRE_VERSION declarations. Fred. Frédéric Lécaille (1): REGTEST: Missing REQUIRE_VERSION declarations. reg-tests/checks/s1.vtc | 1 + reg-tests/peers/s_basic_sync.vtc | 2 ++ reg-tests/peers/s_tls_basic_sync.vtc | 1 + 3 files changed, 4 insertions(+) -- 2.11.0
[PATCH 1/1] REGTEST: Missing REQUIRE_VERSION declarations.
From: Frédéric Lécaille checks/s1.vtc needs support for "srvrecord" which came with 1.8 version. peers/s_basic_sync.vtc and s_tls_basic_sync.vtc need support for "server" keyword usage in "peers" section which came with 2.0 version. --- reg-tests/checks/s1.vtc | 1 + reg-tests/peers/s_basic_sync.vtc | 2 ++ reg-tests/peers/s_tls_basic_sync.vtc | 1 + 3 files changed, 4 insertions(+) diff --git a/reg-tests/checks/s1.vtc b/reg-tests/checks/s1.vtc index abb0f2fc1..2e38867c8 100644 --- a/reg-tests/checks/s1.vtc +++ b/reg-tests/checks/s1.vtc @@ -6,6 +6,7 @@ feature ignore_unknown_macro # The first health-checks passed tests are checked for all these servers # thanks to syslog messages. +#REQUIRE_VERSION=1.8 #EXCLUDE_TARGETS=freebsd # Note that the first syslog message received is: "Proxy started." diff --git a/reg-tests/peers/s_basic_sync.vtc b/reg-tests/peers/s_basic_sync.vtc index 4e35054b3..ecf8fd059 100644 --- a/reg-tests/peers/s_basic_sync.vtc +++ b/reg-tests/peers/s_basic_sync.vtc @@ -1,6 +1,8 @@ vtest "Basic test for peers protocol" feature ignore_unknown_macro +#REQUIRE_VERSION=2.0 + haproxy h1 -arg "-L A" -conf { defaults timeout client 1s diff --git a/reg-tests/peers/s_tls_basic_sync.vtc b/reg-tests/peers/s_tls_basic_sync.vtc index 6710d3196..41e874b4d 100644 --- a/reg-tests/peers/s_tls_basic_sync.vtc +++ b/reg-tests/peers/s_tls_basic_sync.vtc @@ -1,5 +1,6 @@ vtest "Basic test for peers protocol over SSL/TLS" #REQUIRE_OPTIONS=OPENSSL +#REQUIRE_VERSION=2.0 feature ignore_unknown_macro haproxy h1 -arg "-L A" -conf { -- 2.11.0
[PATCH 1/1] REGTEST: Peers reg tests.
This is a better patch to update only reg-tests/peers/s_tls_basic_sync.vtc: We add a 4th haproxy process seen as peer D, without any encryption enabled for all the four peers A,B,C and D. On the three first haproxy instances side A,B, C, we declare D with ssl/tls activated. Consequently D cannot be synched with A or B or C. This is what is checked with D CLI: no stick-table entry may have been synchronized with A, B and C. Fred.
[PATCH] REGTEST: Peers reg tests.
From: Frédéric Lécaille --- reg-tests/peers/common.pem | 1 + reg-tests/peers/s_basic_sync.vtc | 115 +++ reg-tests/peers/s_tls_basic_sync.vtc | 150 +++ 3 files changed, 266 insertions(+) create mode 12 reg-tests/peers/common.pem create mode 100644 reg-tests/peers/s_basic_sync.vtc create mode 100644 reg-tests/peers/s_tls_basic_sync.vtc diff --git a/reg-tests/peers/common.pem b/reg-tests/peers/common.pem new file mode 12 index ..a4433d56 --- /dev/null +++ b/reg-tests/peers/common.pem @@ -0,0 +1 @@ +../ssl/common.pem \ No newline at end of file diff --git a/reg-tests/peers/s_basic_sync.vtc b/reg-tests/peers/s_basic_sync.vtc new file mode 100644 index ..4e35054b --- /dev/null +++ b/reg-tests/peers/s_basic_sync.vtc @@ -0,0 +1,115 @@ +vtest "Basic test for peers protocol" +feature ignore_unknown_macro + +haproxy h1 -arg "-L A" -conf { +defaults +timeout client 1s +timeout connect 1s +timeout server 1s + +backend stkt +stick-table type string size 10m store server_id,gpc0,conn_cur,conn_rate(5) peers peers + +peers peers +bind "fd@${A}" +server A +server B ${h2_B_addr}:${h2_B_port} +server C ${h3_C_addr}:${h3_C_port} + +frontend fe +bind "fd@${fe}" +tcp-request content track-sc0 url table stkt +tcp-request content sc-inc-gpc0(0) +} + +haproxy h2 -arg "-L B" -conf { +defaults +timeout client 1s +timeout connect 1s +timeout server 1s + +backend stkt +stick-table type string size 10m store server_id,gpc0,conn_cur,conn_rate(5) peers peers + +peers peers +bind "fd@${B}" +server A ${h1_A_addr}:${h1_A_port} +server B +server C ${h3_C_addr}:${h3_C_port} + +frontend fe +bind "fd@${fe}" +http-request track-sc0 url table stkt +http-request sc-inc-gpc0(0) +} + +haproxy h3 -arg "-L C" -conf { +defaults +timeout client 1s +timeout connect 1s +timeout server 1s + +backend stkt +stick-table type string size 10m store server_id,gpc0,conn_cur,conn_rate(5) peers peers + +peers peers +bind "fd@${C}" +server A ${h1_A_addr}:${h1_A_port} +server B ${h2_B_addr}:${h2_B_port} +server C + +frontend fe +bind "fd@${fe}" +http-request track-sc0 url table stkt +http-request sc-inc-gpc0(0) +} + +client c1 -connect ${h1_fe_sock} { +txreq -url "c1_client" +expect_close +} -start + +client c2 -connect ${h1_fe_sock} { +txreq -url "c2_client" +expect_close +} -start + +client c3 -connect ${h1_fe_sock} { +txreq -url "c3_client" +expect_close +} -start + +client c4 -connect ${h1_fe_sock} { +txreq -url "c4_client" +expect_close +} -start + +haproxy h1 -start +delay 0.2 +haproxy h2 -start +delay 0.2 +haproxy h3 -start +delay 0.2 + +client c1 -wait +client c2 -wait +client c3 -wait +client c4 -wait + +delay 2 + +haproxy h1 -cli { +send "show table stkt" +expect ~ "# table: stkt, type: string, size:1048[0-9]{4}, used:4(\n0x[0-9a-f]*: key=c[1-4]_client use=0 exp=0 server_id=0 gpc0=1 conn_rate\\(5\\)=1 conn_cur=0){4}" +} + +haproxy h2 -cli { +send "show table stkt" +expect ~ "# table: stkt, type: string, size:1048[0-9]{4}, used:4(\n0x[0-9a-f]*: key=c[1-4]_client use=0 exp=0 server_id=0 gpc0=1 conn_rate\\(5\\)=1 conn_cur=0){4}" +} + +haproxy h3 -cli { +send "show table stkt" +expect ~ "# table: stkt, type: string, size:1048[0-9]{4}, used:4(\n0x[0-9a-f]*: key=c[1-4]_client use=0 exp=0 server_id=0 gpc0=1 conn_rate\\(5\\)=1 conn_cur=0){4}" +} + diff --git a/reg-tests/peers/s_tls_basic_sync.vtc b/reg-tests/peers/s_tls_basic_sync.vtc new file mode 100644 index ..81ab7ba1 --- /dev/null +++ b/reg-tests/peers/s_tls_basic_sync.vtc @@ -0,0 +1,150 @@ +vtest "Basic test for peers protocol over SSL/TLS" +feature ignore_unknown_macro + +haproxy h1 -arg "-L A" -conf { +defaults +timeout client 1s +timeout connect 1s +timeout server 1s + +backend stkt +stick-table type string size 10m store server_id,gpc0,conn_cur,conn_rate(5) peers peers + +peers peers +default-server ssl crt ${testdir}/common.pem verify none +bind "fd@${A}" ssl crt ${testdir}/common.pem +server A +server B ${h2_B_addr}:${h2_B_port} +server C ${h3_C_addr}:${h3_C_port} +server D ${h4_D_addr}:${h4_D_port} + +frontend fe +bind "fd@${fe}" +tcp-request content track-sc0 url table stkt +tcp-request content sc-inc-gpc0(0) +} + +haproxy h2 -arg "-L B" -conf { +defaults +timeout client 1s +timeout connect 1s +timeout server 1s + +backend stkt +stick-table type string size 10m store server_id,gpc0,conn_cur,conn_rate(5) peers peers + +
[PATCH 0/1] Peers reg tests.
From: Frédéric Lécaille Hi ML, Here are new reg tests for peers. They are supposed to test the SSL/TLS support for haproxy peer protocol. (see https://www.mail-archive.com/haproxy@formilux.org/msg32438.html). Furthermore, vtest fixes are required: https://github.com/vtest/VTest/pull/9 Let's wait for PHK validation. Fred. Frédéric Lécaille (1): REGTEST: Peers reg tests. reg-tests/peers/common.pem | 1 + reg-tests/peers/s_basic_sync.vtc | 115 ++ reg-tests/peers/s_tls_basic_sync.vtc | 118 +++ 3 files changed, 234 insertions(+) create mode 12 reg-tests/peers/common.pem create mode 100644 reg-tests/peers/s_basic_sync.vtc create mode 100644 reg-tests/peers/s_tls_basic_sync.vtc -- 2.11.0
[PATCH 1/1] REGTEST: Peers reg tests.
From: Frédéric Lécaille --- reg-tests/peers/common.pem | 1 + reg-tests/peers/s_basic_sync.vtc | 115 ++ reg-tests/peers/s_tls_basic_sync.vtc | 118 +++ 3 files changed, 234 insertions(+) create mode 12 reg-tests/peers/common.pem create mode 100644 reg-tests/peers/s_basic_sync.vtc create mode 100644 reg-tests/peers/s_tls_basic_sync.vtc diff --git a/reg-tests/peers/common.pem b/reg-tests/peers/common.pem new file mode 12 index ..a4433d56 --- /dev/null +++ b/reg-tests/peers/common.pem @@ -0,0 +1 @@ +../ssl/common.pem \ No newline at end of file diff --git a/reg-tests/peers/s_basic_sync.vtc b/reg-tests/peers/s_basic_sync.vtc new file mode 100644 index ..4e35054b --- /dev/null +++ b/reg-tests/peers/s_basic_sync.vtc @@ -0,0 +1,115 @@ +vtest "Basic test for peers protocol" +feature ignore_unknown_macro + +haproxy h1 -arg "-L A" -conf { +defaults +timeout client 1s +timeout connect 1s +timeout server 1s + +backend stkt +stick-table type string size 10m store server_id,gpc0,conn_cur,conn_rate(5) peers peers + +peers peers +bind "fd@${A}" +server A +server B ${h2_B_addr}:${h2_B_port} +server C ${h3_C_addr}:${h3_C_port} + +frontend fe +bind "fd@${fe}" +tcp-request content track-sc0 url table stkt +tcp-request content sc-inc-gpc0(0) +} + +haproxy h2 -arg "-L B" -conf { +defaults +timeout client 1s +timeout connect 1s +timeout server 1s + +backend stkt +stick-table type string size 10m store server_id,gpc0,conn_cur,conn_rate(5) peers peers + +peers peers +bind "fd@${B}" +server A ${h1_A_addr}:${h1_A_port} +server B +server C ${h3_C_addr}:${h3_C_port} + +frontend fe +bind "fd@${fe}" +http-request track-sc0 url table stkt +http-request sc-inc-gpc0(0) +} + +haproxy h3 -arg "-L C" -conf { +defaults +timeout client 1s +timeout connect 1s +timeout server 1s + +backend stkt +stick-table type string size 10m store server_id,gpc0,conn_cur,conn_rate(5) peers peers + +peers peers +bind "fd@${C}" +server A ${h1_A_addr}:${h1_A_port} +server B ${h2_B_addr}:${h2_B_port} +server C + +frontend fe +bind "fd@${fe}" +http-request track-sc0 url table stkt +http-request sc-inc-gpc0(0) +} + +client c1 -connect ${h1_fe_sock} { +txreq -url "c1_client" +expect_close +} -start + +client c2 -connect ${h1_fe_sock} { +txreq -url "c2_client" +expect_close +} -start + +client c3 -connect ${h1_fe_sock} { +txreq -url "c3_client" +expect_close +} -start + +client c4 -connect ${h1_fe_sock} { +txreq -url "c4_client" +expect_close +} -start + +haproxy h1 -start +delay 0.2 +haproxy h2 -start +delay 0.2 +haproxy h3 -start +delay 0.2 + +client c1 -wait +client c2 -wait +client c3 -wait +client c4 -wait + +delay 2 + +haproxy h1 -cli { +send "show table stkt" +expect ~ "# table: stkt, type: string, size:1048[0-9]{4}, used:4(\n0x[0-9a-f]*: key=c[1-4]_client use=0 exp=0 server_id=0 gpc0=1 conn_rate\\(5\\)=1 conn_cur=0){4}" +} + +haproxy h2 -cli { +send "show table stkt" +expect ~ "# table: stkt, type: string, size:1048[0-9]{4}, used:4(\n0x[0-9a-f]*: key=c[1-4]_client use=0 exp=0 server_id=0 gpc0=1 conn_rate\\(5\\)=1 conn_cur=0){4}" +} + +haproxy h3 -cli { +send "show table stkt" +expect ~ "# table: stkt, type: string, size:1048[0-9]{4}, used:4(\n0x[0-9a-f]*: key=c[1-4]_client use=0 exp=0 server_id=0 gpc0=1 conn_rate\\(5\\)=1 conn_cur=0){4}" +} + diff --git a/reg-tests/peers/s_tls_basic_sync.vtc b/reg-tests/peers/s_tls_basic_sync.vtc new file mode 100644 index ..3c1428e3 --- /dev/null +++ b/reg-tests/peers/s_tls_basic_sync.vtc @@ -0,0 +1,118 @@ +vtest "Basic test for peers protocol over SSL/TLS" +feature ignore_unknown_macro + +haproxy h1 -arg "-L A" -conf { +defaults +timeout client 1s +timeout connect 1s +timeout server 1s + +backend stkt +stick-table type string size 10m store server_id,gpc0,conn_cur,conn_rate(5) peers peers + +peers peers +default-server ssl crt ${testdir}/common.pem verify none +bind "fd@${A}" ssl crt ${testdir}/common.pem +server A +server B ${h2_B_addr}:${h2_B_port} +server C ${h3_C_addr}:${h3_C_port} + +frontend fe +bind "fd@${fe}" +tcp-request content track-sc0 url table stkt +tcp-request content sc-inc-gpc0(0) +} + +haproxy h2 -arg "-L B" -conf { +defaults +timeout client 1s +timeout connect 1s +timeout server 1s + +backend stkt +stick-table type string size 10m store server_id,gpc0,conn_cur,conn_rate(5) peers peers + +peers peers +default-serve
[PATCH 08/12] MINOR: peers: Make outgoing connection to SSL/TLS peers work.
From: Frédéric Lécaille This patch adds pointer to a struct server to peer structure which is initialized after having parsed a remote "peer" line. After having parsed all peers section we run ->prepare_srv to initialize all SSL/TLS stuff of remote perr (or server). Remaining thing to do to completely support peer protocol over SSL/TLS: make "bind" keyword be supported in "peers" sections to make SSL/TLS incoming connections to local peers work. May be backported to 1.5 and newer. --- include/proto/peers.h | 26 ++ include/types/peers.h | 1 + src/cfgparse.c| 13 +++-- src/peers.c | 5 +++-- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/include/proto/peers.h b/include/proto/peers.h index 9d4aaff2..ce4feaa4 100644 --- a/include/proto/peers.h +++ b/include/proto/peers.h @@ -25,9 +25,35 @@ #include #include #include +#include #include #include +#if defined(USE_OPENSSL) +static inline enum obj_type *peer_session_target(struct peer *p, struct stream *s) +{ + if (p->srv->use_ssl) + return &p->srv->obj_type; + else + return &s->be->obj_type; +} + +static inline struct xprt_ops *peer_xprt(struct peer *p) +{ + return p->srv->use_ssl ? xprt_get(XPRT_SSL) : xprt_get(XPRT_RAW); +} +#else +static inline enum obj_type *peer_session_target(struct peer *p, struct stream *s) +{ + return &s->be->obj_type; +} + +static inline struct xprt_ops *peer_xprt(struct peer *p) +{ + return xprt_get(XPRT_RAW); +} +#endif + int peers_init_sync(struct peers *peers); void peers_register_table(struct peers *, struct stktable *table); void peers_setup_frontend(struct proxy *fe); diff --git a/include/types/peers.h b/include/types/peers.h index 58c8c4ee..5200d56b 100644 --- a/include/types/peers.h +++ b/include/types/peers.h @@ -67,6 +67,7 @@ struct peer { struct shared_table *remote_table; struct shared_table *last_local_table; struct shared_table *tables; + struct server *srv; __decl_hathreads(HA_SPINLOCK_T lock); /* lock used to handle this peer section */ struct peer *next;/* next peer in the list */ }; diff --git a/src/cfgparse.c b/src/cfgparse.c index 6d199c97..f6f25143 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -514,6 +514,7 @@ static int init_peers_frontend(const char *file, int linenum, out: if (id && !p->id) p->id = strdup(id); + free(p->conf.file); p->conf.args.file = p->conf.file = strdup(file); p->conf.args.line = p->conf.line = linenum; @@ -624,9 +625,10 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) newpeer->sock_init_arg = NULL; HA_SPIN_INIT(&newpeer->lock); - if (strcmp(newpeer->id, localpeer) != 0) - /* We are done. */ + if (strcmp(newpeer->id, localpeer) != 0) { + newpeer->srv = curpeers->peers_fe->srv; goto out; + } if (cfg_peers->local) { ha_alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n", @@ -3634,6 +3636,13 @@ out_uri_auth_compat: curpeers->peers_fe = NULL; } else { + p = curpeers->remote; + while (p) { + if (p->srv && p->srv->use_ssl && + xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv) + cfgerr += xprt_get(XPRT_SSL)->prepare_srv(p->srv); + p = p->next; + } if (!peers_init_sync(curpeers)) { ha_alert("Peers section '%s': out of memory, giving up on peers.\n", curpeers->id); diff --git a/src/peers.c b/src/peers.c index e580f2ca..d4d3859e 100644 --- a/src/peers.c +++ b/src/peers.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -1996,10 +1997,10 @@ static struct appctx *peer_session_create(struct peers *peers, struct peer *peer if (unlikely((cs = cs_new(conn)) == NULL)) goto out_free_conn; - conn->target = s->target = &s->be->obj_type; + conn->target = s->target = peer_session_target(peer, s); memcpy(&conn->addr.to, &peer->addr, sizeof(conn->addr.to)); - conn_prepare(conn, peer->proto, peer->xprt); + conn_prepare(conn, peer->proto, peer_xprt(peer)); conn_install_mux(conn, &mux_pt_ops, cs, s->be, NULL); si_attach_cs(&s->si[1], cs); -- 2.11.0
[PATCH 11/12] MINOR: peers: Less confusing peer binding parsing.
From: Frédéric Lécaille With this patch the "server" lines do not parse anymore the bind address for local peers. We do not use anymore list_for_each_entry() to set the "peers" section listeners parameter because there is only one listener by "peers" section. --- include/proto/server.h | 2 +- src/cfgparse-listen.c | 2 +- src/cfgparse.c | 58 -- src/server.c | 10 ++--- 4 files changed, 46 insertions(+), 26 deletions(-) diff --git a/include/proto/server.h b/include/proto/server.h index b3a9b877..436ffb5d 100644 --- a/include/proto/server.h +++ b/include/proto/server.h @@ -39,7 +39,7 @@ int srv_downtime(const struct server *s); int srv_lastsession(const struct server *s); int srv_getinter(const struct check *check); -int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, struct proxy *defproxy); +int parse_server(const char *file, int linenum, char **args, struct proxy *curproxy, struct proxy *defproxy, int parse_addr); int update_server_addr(struct server *s, void *ip, int ip_sin_family, const char *updater); const char *update_server_addr_port(struct server *s, const char *addr, const char *port, char *updater); struct server *server_find_by_id(struct proxy *bk, int id); diff --git a/src/cfgparse-listen.c b/src/cfgparse-listen.c index aa2d8608..fdbdfd34 100644 --- a/src/cfgparse-listen.c +++ b/src/cfgparse-listen.c @@ -677,7 +677,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm) if (!strcmp(args[0], "server") || !strcmp(args[0], "default-server") || !strcmp(args[0], "server-template")) { - err_code |= parse_server(file, linenum, args, curproxy, &defproxy); + err_code |= parse_server(file, linenum, args, curproxy, &defproxy, 1); if (err_code & ERR_FATAL) goto out; } diff --git a/src/cfgparse.c b/src/cfgparse.c index 2a6a4839..4d0a9ade 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -623,8 +623,7 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, linenum, NULL, xprt_get(XPRT_RAW)); if (*args[0] == 'b') { - struct sockaddr_storage *sk; - int port, port1, port2; + struct listener *l; if (peer_line) { ha_alert("parsing [%s:%d] : mixing \"peer\" and \"bind\" line is forbidden\n", file, linenum); @@ -632,13 +631,26 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) goto out; } - sk = str2sa_range(args[1], &port, &port1, &port2, &errmsg, NULL, NULL, 0); - if (!sk) { - ha_alert("parsing [%s:%d]: '%s %s': %s\n", -file, linenum, args[0], args[1], errmsg); - err_code |= ERR_ALERT | ERR_FATAL; + if (!str2listener(args[1], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { + if (errmsg && *errmsg) { + indent_msg(&errmsg, 2); + ha_alert("parsing +[%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); + } + else + ha_alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n", +file, linenum, args[0], args[1], args[2]); + err_code |= ERR_FATAL; goto out; } + l = LIST_ELEM(bind_conf->listeners.n, typeof(l), by_bind); + l->maxaccept = 1; + l->maxconn = curpeers->peers_fe->maxconn; + l->backlog = curpeers->peers_fe->backlog; + l->accept = session_accept_fd; + l->analysers |= curpeers->peers_fe->fe_req_ana; + l->default_target = curpeers->peers_fe->default_target; + l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */ + global.maxsock += l->maxconn; bind_line = 1; if (cfg_peers->local) { @@ -655,7 +667,7 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) goto out; } } - newpeer->addr = *sk; +
[PATCH 01/12] MINOR: cfgparse: Extract some code to be re-used.
From: Frédéric Lécaille Create init_peers_frontend() function to allocate and initialize the frontend of "peers" sections (->peers_fe) so that to reuse it later. May be backported to 1.5 and newer. --- src/cfgparse.c | 34 ++ 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index 7c316df0..6fde7c9f 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -483,6 +483,31 @@ void init_default_instance() defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC; } +/* Allocate and initialize the frontend of a "peers" section found in + * file at line with as ID. + * Return 0 if succeeded, -1 if not. + */ +static int init_peers_frontend(const char *file, int linenum, + const char *id, struct peers *peers) +{ + struct proxy *p; + + p = calloc(1, sizeof *p); + if (!p) { + ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); + return -1; + } + + init_new_proxy(p); + p->parent = peers; + p->id = strdup(id); + p->conf.args.file = p->conf.file = strdup(file); + p->conf.args.line = p->conf.line = linenum; + peers_setup_frontend(p); + peers->peers_fe = p; + + return 0; +} /* * Parse a line in a , or section. @@ -625,19 +650,12 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) cfg_peers->local = newpeer; if (!curpeers->peers_fe) { - if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) { + if (init_peers_frontend(file, linenum, args[1], curpeers) != 0) { ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); err_code |= ERR_ALERT | ERR_ABORT; goto out; } - init_new_proxy(curpeers->peers_fe); - curpeers->peers_fe->parent = curpeers; - curpeers->peers_fe->id = strdup(args[1]); - curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file); - curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum; - peers_setup_frontend(curpeers->peers_fe); - bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { -- 2.11.0
[PATCH 07/12] MINOR: cfgparse: Make "peer" lines be parsed as "server" lines.
From: Frédéric Lécaille With this patch "default-server" lines are supported in "peers" sections to setup the default settings of peers which are from now setup when parsing both "peer" and "server" lines. May be backported to 1.5 and newer. --- src/cfgparse.c | 88 +++--- src/peers.c| 2 +- src/server.c | 3 +- 3 files changed, 32 insertions(+), 61 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index 715faaef..6d199c97 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -486,15 +486,18 @@ void init_default_instance() /* Allocate and initialize the frontend of a "peers" section found in * file at line with as ID. * Return 0 if succeeded, -1 if not. + * Note that this function may be called from "default-server" + * or "peer" lines. */ static int init_peers_frontend(const char *file, int linenum, const char *id, struct peers *peers) { struct proxy *p; - if (peers->peers_fe) - /* Nothing to do */ - return 0; + if (peers->peers_fe) { + p = peers->peers_fe; + goto out; + } p = calloc(1, sizeof *p); if (!p) { @@ -503,12 +506,16 @@ static int init_peers_frontend(const char *file, int linenum, } init_new_proxy(p); + peers_setup_frontend(p); p->parent = peers; - p->id = strdup(id); + /* Finally store this frontend. */ + peers->peers_fe = p; + + out: + if (id && !p->id) + p->id = strdup(id); p->conf.args.file = p->conf.file = strdup(file); p->conf.args.line = p->conf.line = linenum; - peers_setup_frontend(p); - peers->peers_fe = p; return 0; } @@ -533,7 +540,14 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) int err_code = 0; char *errmsg = NULL; - if (strcmp(args[0], "peers") == 0) { /* new peers section */ + if (strcmp(args[0], "default-server") == 0) { + if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) { + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + err_code |= parse_server(file, linenum, args, curpeers->peers_fe, NULL); + } + else if (strcmp(args[0], "peers") == 0) { /* new peers section */ if (!*args[1]) { ha_alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum); err_code |= ERR_ALERT | ERR_ABORT; @@ -577,26 +591,8 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) curpeers->id = strdup(args[1]); curpeers->state = PR_STNEW; } - else if (strcmp(args[0], "peer") == 0) { /* peer definition */ - struct sockaddr_storage *sk; - int port1, port2; - struct protocol *proto; - - if (!*args[2]) { - ha_alert("parsing [%s:%d] : '%s' expects and [:] as arguments.\n", -file, linenum, args[0]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - - err = invalid_char(args[1]); - if (err) { - ha_alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n", -file, linenum, *err, args[1]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - + else if (strcmp(args[0], "peer") == 0 || +strcmp(args[0], "server") == 0) { /* peer or server definition */ if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) { ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); err_code |= ERR_ALERT | ERR_ABORT; @@ -613,37 +609,17 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) newpeer->last_change = now.tv_sec; newpeer->id = strdup(args[1]); - sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1); - if (!sk) { - ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - - proto = protocol_by_family(sk->ss_family); - if (!proto || !proto->connect) { - ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n", -file, linenum, args[0], args[1]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - - if (port1 != port
[PATCH 09/12] MINOR: cfgparse: SSL/TLS binding in "peers" sections.
From: Frédéric Lécaille This patch makes "bind" work in "peers" sections. All "bind" settings are supported, excepted ip:port parameters which are provided on "peer" (or server) line matching the local peer. After having parsed the configuration files ->prepare_bind_conf is run to initialize all SSL/TLS stuff for the local peer. May be backported to 1.5 and newer. --- src/cfgparse.c | 95 ++ 1 file changed, 90 insertions(+), 5 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index f6f25143..ef69b37d 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -521,6 +521,31 @@ static int init_peers_frontend(const char *file, int linenum, return 0; } +/* Only change ->file, ->line and ->arg struct bind_conf member values + * if already present. + */ +static struct bind_conf *bind_conf_uniq_alloc(struct proxy *p, + const char *file, int line, + const char *arg, struct xprt_ops *xprt) +{ + struct bind_conf *bind_conf; + + if (!LIST_ISEMPTY(&p->conf.bind)) { + bind_conf = LIST_ELEM((&p->conf.bind)->n, typeof(bind_conf), by_fe); + free(bind_conf->file); + bind_conf->file = strdup(file); + bind_conf->line = line; + if (arg) { + free(bind_conf->arg); + bind_conf->arg = strdup(arg); + } + } + else { + bind_conf = bind_conf_alloc(p, file, line, arg, xprt); + } + + return bind_conf; +} /* * Parse a line in a , or section. * Returns the error code, 0 if OK, or any combination of : @@ -541,7 +566,56 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) int err_code = 0; char *errmsg = NULL; - if (strcmp(args[0], "default-server") == 0) { + if (strcmp(args[0], "bind") == 0) { + int cur_arg; + static int kws_dumped; + struct bind_conf *bind_conf; + struct bind_kw *kw; + char *kws; + + cur_arg = 1; + + if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) { + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + + bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, linenum, +NULL, xprt_get(XPRT_RAW)); + while (*args[cur_arg] && (kw = bind_find_kw(args[cur_arg]))) { + int ret; + + ret = kw->parse(args, cur_arg, curpeers->peers_fe, bind_conf, &errmsg); + err_code |= ret; + if (ret) { + if (errmsg && *errmsg) { + indent_msg(&errmsg, 2); + ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg); + } + else + ha_alert("parsing [%s:%d]: error encountered while processing '%s'\n", +file, linenum, args[cur_arg]); + if (ret & ERR_FATAL) + goto out; + } + cur_arg += 1 + kw->skip; + } + kws = NULL; + if (!kws_dumped) { + kws_dumped = 1; + bind_dump_kws(&kws); + indent_msg(&kws, 4); + } + if (*args[cur_arg] != 0) { + ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section.%s%s\n", +file, linenum, args[cur_arg], cursection, +kws ? " Registered keywords :" : "", kws ? kws: ""); + free(kws); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + } + else if (strcmp(args[0], "default-server") == 0) { if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) { err_code |= ERR_ALERT | ERR_ABORT; goto out; @@ -641,7 +715,7 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) /* Current is local peer, it define a frontend */ newpeer->local = 1; - bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); + bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { if (errmsg && *errmsg) {
[PATCH 05/12] MINOR: cfgparse: Rework peers frontend init.
From: Frédéric Lécaille Even if not already the case, we suppose that the frontend "peers" section may have been already initialized outside of "peer" line, we seperate their initializations from their binding initializations. May be backported to 1.5 and newer. --- src/cfgparse.c | 50 -- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index e3e96b51..22a3da72 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -659,39 +659,37 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) /* Current is local peer, it define a frontend */ newpeer->local = 1; - if (!curpeers->peers_fe) { - if (init_peers_frontend(file, linenum, args[1], curpeers) != 0) { + if (!curpeers->peers_fe && + init_peers_frontend(file, linenum, args[1], curpeers) != 0) { ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); err_code |= ERR_ALERT | ERR_ABORT; goto out; - } - - bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); + } - if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { - if (errmsg && *errmsg) { - indent_msg(&errmsg, 2); - ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); - } - else - ha_alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n", -file, linenum, args[0], args[1], args[2]); - err_code |= ERR_FATAL; - goto out; - } + bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); - list_for_each_entry(l, &bind_conf->listeners, by_bind) { - l->maxaccept = 1; - l->maxconn = curpeers->peers_fe->maxconn; - l->backlog = curpeers->peers_fe->backlog; - l->accept = session_accept_fd; - l->analysers |= curpeers->peers_fe->fe_req_ana; - l->default_target = curpeers->peers_fe->default_target; - l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */ - global.maxsock += l->maxconn; + if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { + if (errmsg && *errmsg) { + indent_msg(&errmsg, 2); + ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); } - cfg_peers->local = newpeer; + else + ha_alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n", +file, linenum, args[0], args[1], args[2]); + err_code |= ERR_FATAL; + goto out; } + list_for_each_entry(l, &bind_conf->listeners, by_bind) { + l->maxaccept = 1; + l->maxconn = curpeers->peers_fe->maxconn; + l->backlog = curpeers->peers_fe->backlog; + l->accept = session_accept_fd; + l->analysers |= curpeers->peers_fe->fe_req_ana; + l->default_target = curpeers->peers_fe->default_target; + l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */ + global.maxsock += l->maxconn; + } + cfg_peers->local = newpeer; } /* neither "peer" nor "peers" */ else if (!strcmp(args[0], "disabled")) { /* disables this peers section */ curpeers->state = PR_STSTOPPED; -- 2.11.0
[PATCH 12/12] DOC: peers: SSL/TLS documentation for "peers"
From: Frédéric Lécaille --- doc/configuration.txt | 40 +++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 888515fb..960f1948 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1928,15 +1928,34 @@ peers Creates a new peer list with name . It is an independent section, which is referenced by one or more stick-tables. +bind []: [, ...] [param*] + Defines the binding parameters of the local peer of this "peers" section. + Such lines are not supported with "peer" line in the same "peers" section. + disabled Disables a peers section. It disables both listening and any synchronization related to this section. This is provided to disable synchronization of stick tables without having to comment out all "peers" references. +default-bind [param*] + Defines the binding parameters for the local peer, excepted its address. + +default-server [param*] + Change default options for a server in a "peers" section. + + Arguments: + is a list of parameters for this server. The "default-server" + keyword accepts an important number of options and has a complete + section dedicated to it. Please refer to section 5 for more + details. + + + See also: "server" and section 5 about server options + enable This re-enables a disabled peers section which was previously disabled. -peer : +peer : [param*] Defines a peer inside a peers section. If is set to the local peer name (by default hostname, or forced using "-L" command line option), haproxy will listen for incoming remote peer @@ -1955,7 +1974,20 @@ peer : You may want to reference some environment variables in the address parameter, see section 2.3 about environment variables. + Note: "peer" keyword may transparently be replaced by "server" keyword (see + "server" keyword explanation below). + +server [:] [param*] + As previously mentionned, "peer" keyword may be replaced by "server" keyword + with a support for all "server" parameters found in 5.2 paragraph. + If the underlying peer is local, : parameters must not be present. + These parameters must be provided on a "bind" line (see "bind" keyword + of this "peers" section). + Some of these parameters are irrelevant for "peers" sections. + + Example: +# The old way. peers mypeers peer haproxy1 192.168.0.1:1024 peer haproxy2 192.168.0.2:1024 @@ -1970,6 +2002,12 @@ peer : server srv1 192.168.0.30:80 server srv2 192.168.0.31:80 + Example: + peers mypeers + bind 127.0.0.11:10001 ssl crt mycerts/pem + default-server ssl verify none + server hostA 127.0.0.10:1 + server hostB #local peer 3.6. Mailers -- 2.11.0
[PATCH 03/12] CLEANUP: cfgparse: Code reindentation.
From: Frédéric Lécaille May help the series of patches to be reviewed. May be backported to 1.5 and newer. --- src/cfgparse.c | 72 +- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index 6670a861..04e36e8c 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -648,49 +648,49 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) /* We are done. */ goto out; - /* Current is local peer, it define a frontend */ - newpeer->local = 1; - cfg_peers->local = newpeer; - - if (!curpeers->peers_fe) { - if (init_peers_frontend(file, linenum, args[1], curpeers) != 0) { - ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); - err_code |= ERR_ALERT | ERR_ABORT; - goto out; - } + /* Current is local peer, it define a frontend */ + newpeer->local = 1; + cfg_peers->local = newpeer; - bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); + if (!curpeers->peers_fe) { + if (init_peers_frontend(file, linenum, args[1], curpeers) != 0) { + ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } - if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { - if (errmsg && *errmsg) { - indent_msg(&errmsg, 2); - ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); - } - else - ha_alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n", -file, linenum, args[0], args[1], args[2]); - err_code |= ERR_FATAL; - goto out; - } + bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); - list_for_each_entry(l, &bind_conf->listeners, by_bind) { - l->maxaccept = 1; - l->maxconn = curpeers->peers_fe->maxconn; - l->backlog = curpeers->peers_fe->backlog; - l->accept = session_accept_fd; - l->analysers |= curpeers->peers_fe->fe_req_ana; - l->default_target = curpeers->peers_fe->default_target; - l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */ - global.maxsock += l->maxconn; + if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { + if (errmsg && *errmsg) { + indent_msg(&errmsg, 2); + ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); } - } - else { - ha_alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n", -file, linenum, args[0], args[1], -curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line); + else + ha_alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n", +file, linenum, args[0], args[1], args[2]); err_code |= ERR_FATAL; goto out; } + + list_for_each_entry(l, &bind_conf->listeners, by_bind) { + l->maxaccept = 1; + l->maxconn = curpeers->peers_fe->maxconn; + l->backlog = curpeers->peers_fe->backlog; + l->accept = session_accep
[PATCH 06/12] MINOR: cfgparse: Simplication.
From: Frédéric Lécaille Make init_peers_frontend() be callable without having to check if there is something to do or not. May be backported to 1.5 and newer. --- src/cfgparse.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index 22a3da72..715faaef 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -492,6 +492,10 @@ static int init_peers_frontend(const char *file, int linenum, { struct proxy *p; + if (peers->peers_fe) + /* Nothing to do */ + return 0; + p = calloc(1, sizeof *p); if (!p) { ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); @@ -659,8 +663,7 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) /* Current is local peer, it define a frontend */ newpeer->local = 1; - if (!curpeers->peers_fe && - init_peers_frontend(file, linenum, args[1], curpeers) != 0) { + if (init_peers_frontend(file, linenum, args[1], curpeers) != 0) { ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); err_code |= ERR_ALERT | ERR_ABORT; goto out; -- 2.11.0
[PATCH 04/12] MINOR: cfgparse: Useless frontend initialization in "peers" sections.
From: Frédéric Lécaille Use ->local "peers" struct member to flag a "peers" section frontend has being initialized. This is to be able to initialize the frontend of "peers" sections on lines different from "peer" lines. May be backported to 1.5 and newer. --- src/cfgparse.c | 17 + 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index 04e36e8c..e3e96b51 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -648,9 +648,16 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) /* We are done. */ goto out; + if (cfg_peers->local) { + ha_alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n", +file, linenum, args[0], args[1], +curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line); + err_code |= ERR_FATAL; + goto out; + } + /* Current is local peer, it define a frontend */ newpeer->local = 1; - cfg_peers->local = newpeer; if (!curpeers->peers_fe) { if (init_peers_frontend(file, linenum, args[1], curpeers) != 0) { @@ -683,13 +690,7 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */ global.maxsock += l->maxconn; } - } - else { - ha_alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n", -file, linenum, args[0], args[1], -curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line); - err_code |= ERR_FATAL; - goto out; + cfg_peers->local = newpeer; } } /* neither "peer" nor "peers" */ else if (!strcmp(args[0], "disabled")) { /* disables this peers section */ -- 2.11.0
[PATCH 02/12] CLEANUP: cfgparse: Return asap from cfg_parse_peers().
From: Frédéric Lécaille Avoid useless code indentation. May be backported to 1.5 and newer. --- src/cfgparse.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index 6fde7c9f..6670a861 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -644,7 +644,10 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) newpeer->sock_init_arg = NULL; HA_SPIN_INIT(&newpeer->lock); - if (strcmp(newpeer->id, localpeer) == 0) { + if (strcmp(newpeer->id, localpeer) != 0) + /* We are done. */ + goto out; + /* Current is local peer, it define a frontend */ newpeer->local = 1; cfg_peers->local = newpeer; @@ -688,7 +691,6 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) err_code |= ERR_FATAL; goto out; } - } } /* neither "peer" nor "peers" */ else if (!strcmp(args[0], "disabled")) { /* disables this peers section */ curpeers->state = PR_STSTOPPED; -- 2.11.0
[PATCH 10/12] MINOR: cfgparse: peers: Be less confusing.
From: Frédéric Lécaille Make "bind" line also parse the local peer bind address. Add "default-bind" option to parse the binding options excepted the bind address. Prevent "bind" lines to be mixed with "peer" line to help in handling the migration. --- src/cfgparse.c | 153 + 1 file changed, 122 insertions(+), 31 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index ef69b37d..2a6a4839 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -516,7 +516,8 @@ static int init_peers_frontend(const char *file, int linenum, p->id = strdup(id); free(p->conf.file); p->conf.args.file = p->conf.file = strdup(file); - p->conf.args.line = p->conf.line = linenum; + if (linenum != -1) + p->conf.args.line = p->conf.line = linenum; return 0; } @@ -546,6 +547,44 @@ static struct bind_conf *bind_conf_uniq_alloc(struct proxy *p, return bind_conf; } + +/* + * Allocate a new struct peer parsed at line in file + * to be added to . + * Returns the new allocated structure if succeeded, NULL if not. + */ +static struct peer *cfg_peers_add_peer(struct peers *peers, + const char *file, int linenum, + const char *id, int local) +{ + struct peer *p; + + p = calloc(1, sizeof *p); + if (!p) { + ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); + return NULL; + } + + /* the peers are linked backwards first */ + peers->count++; + p->next = peers->remote; + peers->remote = p; + p->conf.file = strdup(file); + p->conf.line = linenum; + p->last_change = now.tv_sec; + p->xprt = xprt_get(XPRT_RAW); + p->sock_init_arg = NULL; + HA_SPIN_INIT(&p->lock); + if (id) + p->id = strdup(id); + if (local) { + p->local = 1; + peers->local = p; + } + + return p; +} + /* * Parse a line in a , or section. * Returns the error code, 0 if OK, or any combination of : @@ -565,8 +604,9 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) struct listener *l; int err_code = 0; char *errmsg = NULL; + static int bind_line, peer_line; - if (strcmp(args[0], "bind") == 0) { + if (strcmp(args[0], "bind") == 0 || strcmp(args[0], "default-bind") == 0) { int cur_arg; static int kws_dumped; struct bind_conf *bind_conf; @@ -582,6 +622,44 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, linenum, NULL, xprt_get(XPRT_RAW)); + if (*args[0] == 'b') { + struct sockaddr_storage *sk; + int port, port1, port2; + + if (peer_line) { + ha_alert("parsing [%s:%d] : mixing \"peer\" and \"bind\" line is forbidden\n", file, linenum); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + + sk = str2sa_range(args[1], &port, &port1, &port2, &errmsg, NULL, NULL, 0); + if (!sk) { + ha_alert("parsing [%s:%d]: '%s %s': %s\n", +file, linenum, args[0], args[1], errmsg); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + + bind_line = 1; + if (cfg_peers->local) { + newpeer = cfg_peers->local; + } + else { + /* This peer is local. +* Note that we do not set the peer ID. This latter is initialized +* when parsing "peer" or "server" line. +*/ + newpeer = cfg_peers_add_peer(curpeers, file, linenum, NULL, 1); + if (!newpeer) { + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + } + newpeer->addr = *sk; + newpeer->proto = protocol_by_family(newpeer->addr.ss_family); + cur_arg++; + } + while (*args[cur_arg] && (kw = bind_find_kw(args[cur_arg]))) { int ret; @@ -616,13 +694,15 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) } }
[PATCH 00/12] Peers SSL/TSL support
From: Frédéric Lécaille Hi ML, Willy, Here is a new series of patches for this feature with Willy's remarks taken into an account. Was easy to break something ;) but I think this series does not break the current usage of "peers" section. I prefered work from the previous series without rebasing anything excepted for the doc patch. So, the first nine patches #1 up to #9 included are the same as in the first series. Then come the three last patches with the patch for the doc as the last one. I will check how to test all this asap. I think we have to modify vtest/varnishtest to resolve macros created by different haproxy processes. The expansion must be done at the very last time: when all the macros have been created. Fred. Frédéric Lécaille (12): MINOR: cfgparse: Extract some code to be re-used. CLEANUP: cfgparse: Return asap from cfg_parse_peers(). CLEANUP: cfgparse: Code reindentation. MINOR: cfgparse: Useless frontend initialization in "peers" sections. MINOR: cfgparse: Rework peers frontend init. MINOR: cfgparse: Simplication. MINOR: cfgparse: Make "peer" lines be parsed as "server" lines. MINOR: peers: Make outgoing connection to SSL/TLS peers work. MINOR: cfgparse: SSL/TLS binding in "peers" sections. MINOR: cfgparse: peers: Be less confusing. MINOR: peers: Less confusing peer binding parsing. DOC: peers: SSL/TLS documentation for "peers" doc/configuration.txt | 40 - include/proto/peers.h | 26 include/proto/server.h | 2 +- include/types/peers.h | 1 + src/cfgparse-listen.c | 2 +- src/cfgparse.c | 405 - src/peers.c| 7 +- src/server.c | 13 +- 8 files changed, 380 insertions(+), 116 deletions(-) -- 2.11.0
[PATCH 01/10] MINOR: cfgparse: Extract some code to be re-used.
From: Frédéric Lécaille Create init_peers_frontend() function to allocate and initialize the frontend of "peers" sections (->peers_fe) so that to reuse it later. May be backported to 1.5 and newer. --- src/cfgparse.c | 34 ++ 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index 7c316df0..6fde7c9f 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -483,6 +483,31 @@ void init_default_instance() defproxy.load_server_state_from_file = PR_SRV_STATE_FILE_UNSPEC; } +/* Allocate and initialize the frontend of a "peers" section found in + * file at line with as ID. + * Return 0 if succeeded, -1 if not. + */ +static int init_peers_frontend(const char *file, int linenum, + const char *id, struct peers *peers) +{ + struct proxy *p; + + p = calloc(1, sizeof *p); + if (!p) { + ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); + return -1; + } + + init_new_proxy(p); + p->parent = peers; + p->id = strdup(id); + p->conf.args.file = p->conf.file = strdup(file); + p->conf.args.line = p->conf.line = linenum; + peers_setup_frontend(p); + peers->peers_fe = p; + + return 0; +} /* * Parse a line in a , or section. @@ -625,19 +650,12 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) cfg_peers->local = newpeer; if (!curpeers->peers_fe) { - if ((curpeers->peers_fe = calloc(1, sizeof(struct proxy))) == NULL) { + if (init_peers_frontend(file, linenum, args[1], curpeers) != 0) { ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); err_code |= ERR_ALERT | ERR_ABORT; goto out; } - init_new_proxy(curpeers->peers_fe); - curpeers->peers_fe->parent = curpeers; - curpeers->peers_fe->id = strdup(args[1]); - curpeers->peers_fe->conf.args.file = curpeers->peers_fe->conf.file = strdup(file); - curpeers->peers_fe->conf.args.line = curpeers->peers_fe->conf.line = linenum; - peers_setup_frontend(curpeers->peers_fe); - bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { -- 2.11.0
[PATCH 06/10] MINOR: cfgparse: Simplication.
From: Frédéric Lécaille Make init_peers_frontend() be callable without having to check if there is something to do or not. May be backported to 1.5 and newer. --- src/cfgparse.c | 7 +-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index 22a3da72..715faaef 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -492,6 +492,10 @@ static int init_peers_frontend(const char *file, int linenum, { struct proxy *p; + if (peers->peers_fe) + /* Nothing to do */ + return 0; + p = calloc(1, sizeof *p); if (!p) { ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); @@ -659,8 +663,7 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) /* Current is local peer, it define a frontend */ newpeer->local = 1; - if (!curpeers->peers_fe && - init_peers_frontend(file, linenum, args[1], curpeers) != 0) { + if (init_peers_frontend(file, linenum, args[1], curpeers) != 0) { ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); err_code |= ERR_ALERT | ERR_ABORT; goto out; -- 2.11.0
[PATCH 05/10] MINOR: cfgparse: Rework peers frontend init.
From: Frédéric Lécaille Even if not already the case, we suppose that the frontend "peers" section may have been already initialized outside of "peer" line, we seperate their initializations from their binding initializations. May be backported to 1.5 and newer. --- src/cfgparse.c | 50 -- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index e3e96b51..22a3da72 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -659,39 +659,37 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) /* Current is local peer, it define a frontend */ newpeer->local = 1; - if (!curpeers->peers_fe) { - if (init_peers_frontend(file, linenum, args[1], curpeers) != 0) { + if (!curpeers->peers_fe && + init_peers_frontend(file, linenum, args[1], curpeers) != 0) { ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); err_code |= ERR_ALERT | ERR_ABORT; goto out; - } - - bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); + } - if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { - if (errmsg && *errmsg) { - indent_msg(&errmsg, 2); - ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); - } - else - ha_alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n", -file, linenum, args[0], args[1], args[2]); - err_code |= ERR_FATAL; - goto out; - } + bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); - list_for_each_entry(l, &bind_conf->listeners, by_bind) { - l->maxaccept = 1; - l->maxconn = curpeers->peers_fe->maxconn; - l->backlog = curpeers->peers_fe->backlog; - l->accept = session_accept_fd; - l->analysers |= curpeers->peers_fe->fe_req_ana; - l->default_target = curpeers->peers_fe->default_target; - l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */ - global.maxsock += l->maxconn; + if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { + if (errmsg && *errmsg) { + indent_msg(&errmsg, 2); + ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); } - cfg_peers->local = newpeer; + else + ha_alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n", +file, linenum, args[0], args[1], args[2]); + err_code |= ERR_FATAL; + goto out; } + list_for_each_entry(l, &bind_conf->listeners, by_bind) { + l->maxaccept = 1; + l->maxconn = curpeers->peers_fe->maxconn; + l->backlog = curpeers->peers_fe->backlog; + l->accept = session_accept_fd; + l->analysers |= curpeers->peers_fe->fe_req_ana; + l->default_target = curpeers->peers_fe->default_target; + l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */ + global.maxsock += l->maxconn; + } + cfg_peers->local = newpeer; } /* neither "peer" nor "peers" */ else if (!strcmp(args[0], "disabled")) { /* disables this peers section */ curpeers->state = PR_STSTOPPED; -- 2.11.0
[PATCH 10/10] DOC: peers: SSL/TLS documentation for "peers"
From: Frédéric Lécaille --- doc/configuration.txt | 23 ++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index 888515fb..d55e4bd3 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -1928,6 +1928,12 @@ peers Creates a new peer list with name . It is an independent section, which is referenced by one or more stick-tables. +bind [param*] + Defines the binding parameters of the local peer of this "peers" section. + To avoid some redundancy, and as the and parameters + are already provided on "peer" (or "server") lines, they are not supported + by "bind" keyword in "peers" sections. + disabled Disables a peers section. It disables both listening and any synchronization related to this section. This is provided to disable synchronization of stick @@ -1936,7 +1942,7 @@ disabled enable This re-enables a disabled peers section which was previously disabled. -peer : +peer : [param*] Defines a peer inside a peers section. If is set to the local peer name (by default hostname, or forced using "-L" command line option), haproxy will listen for incoming remote peer @@ -1955,6 +1961,15 @@ peer : You may want to reference some environment variables in the address parameter, see section 2.3 about environment variables. + Note: "peer" keyword may transparently be replaced by "server" keyword (see + "server" keyword explanation below). + +server : [param*] + As previously mentionned, "peer" keyword may be replaced by "server" keyword + with a support for all "server" parameters found in 5.2 paragraph. + Some of these parameters are irrelevant for "peers" sections. + + Example: peers mypeers peer haproxy1 192.168.0.1:1024 @@ -1970,6 +1985,12 @@ peer : server srv1 192.168.0.30:80 server srv2 192.168.0.31:80 + Example: + peers mypeers + bind ssl crt mycerts/pem + default-server ssl verify none + server hostA 127.0.0.10:1 + server hostB 127.0.0.11:10001 3.6. Mailers -- 2.11.0
[PATCH 04/10] MINOR: cfgparse: Useless frontend initialization in "peers" sections.
From: Frédéric Lécaille Use ->local "peers" struct member to flag a "peers" section frontend has being initialized. This is to be able to initialize the frontend of "peers" sections on lines different from "peer" lines. May be backported to 1.5 and newer. --- src/cfgparse.c | 17 + 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index 04e36e8c..e3e96b51 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -648,9 +648,16 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) /* We are done. */ goto out; + if (cfg_peers->local) { + ha_alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n", +file, linenum, args[0], args[1], +curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line); + err_code |= ERR_FATAL; + goto out; + } + /* Current is local peer, it define a frontend */ newpeer->local = 1; - cfg_peers->local = newpeer; if (!curpeers->peers_fe) { if (init_peers_frontend(file, linenum, args[1], curpeers) != 0) { @@ -683,13 +690,7 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */ global.maxsock += l->maxconn; } - } - else { - ha_alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n", -file, linenum, args[0], args[1], -curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line); - err_code |= ERR_FATAL; - goto out; + cfg_peers->local = newpeer; } } /* neither "peer" nor "peers" */ else if (!strcmp(args[0], "disabled")) { /* disables this peers section */ -- 2.11.0
[PATCH 07/10] MINOR: cfgparse: Make "peer" lines be parsed as "server" lines.
From: Frédéric Lécaille With this patch "default-server" lines are supported in "peers" sections to setup the default settings of peers which are from now setup when parsing both "peer" and "server" lines. May be backported to 1.5 and newer. --- src/cfgparse.c | 88 +++--- src/peers.c| 2 +- src/server.c | 3 +- 3 files changed, 32 insertions(+), 61 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index 715faaef..6d199c97 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -486,15 +486,18 @@ void init_default_instance() /* Allocate and initialize the frontend of a "peers" section found in * file at line with as ID. * Return 0 if succeeded, -1 if not. + * Note that this function may be called from "default-server" + * or "peer" lines. */ static int init_peers_frontend(const char *file, int linenum, const char *id, struct peers *peers) { struct proxy *p; - if (peers->peers_fe) - /* Nothing to do */ - return 0; + if (peers->peers_fe) { + p = peers->peers_fe; + goto out; + } p = calloc(1, sizeof *p); if (!p) { @@ -503,12 +506,16 @@ static int init_peers_frontend(const char *file, int linenum, } init_new_proxy(p); + peers_setup_frontend(p); p->parent = peers; - p->id = strdup(id); + /* Finally store this frontend. */ + peers->peers_fe = p; + + out: + if (id && !p->id) + p->id = strdup(id); p->conf.args.file = p->conf.file = strdup(file); p->conf.args.line = p->conf.line = linenum; - peers_setup_frontend(p); - peers->peers_fe = p; return 0; } @@ -533,7 +540,14 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) int err_code = 0; char *errmsg = NULL; - if (strcmp(args[0], "peers") == 0) { /* new peers section */ + if (strcmp(args[0], "default-server") == 0) { + if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) { + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + err_code |= parse_server(file, linenum, args, curpeers->peers_fe, NULL); + } + else if (strcmp(args[0], "peers") == 0) { /* new peers section */ if (!*args[1]) { ha_alert("parsing [%s:%d] : missing name for peers section.\n", file, linenum); err_code |= ERR_ALERT | ERR_ABORT; @@ -577,26 +591,8 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) curpeers->id = strdup(args[1]); curpeers->state = PR_STNEW; } - else if (strcmp(args[0], "peer") == 0) { /* peer definition */ - struct sockaddr_storage *sk; - int port1, port2; - struct protocol *proto; - - if (!*args[2]) { - ha_alert("parsing [%s:%d] : '%s' expects and [:] as arguments.\n", -file, linenum, args[0]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - - err = invalid_char(args[1]); - if (err) { - ha_alert("parsing [%s:%d] : character '%c' is not permitted in server name '%s'.\n", -file, linenum, *err, args[1]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - + else if (strcmp(args[0], "peer") == 0 || +strcmp(args[0], "server") == 0) { /* peer or server definition */ if ((newpeer = calloc(1, sizeof(*newpeer))) == NULL) { ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); err_code |= ERR_ALERT | ERR_ABORT; @@ -613,37 +609,17 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) newpeer->last_change = now.tv_sec; newpeer->id = strdup(args[1]); - sk = str2sa_range(args[2], NULL, &port1, &port2, &errmsg, NULL, NULL, 1); - if (!sk) { - ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - - proto = protocol_by_family(sk->ss_family); - if (!proto || !proto->connect) { - ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n", -file, linenum, args[0], args[1]); - err_code |= ERR_ALERT | ERR_FATAL; - goto out; - } - - if (port1 != port
[PATCH 03/10] CLEANUP: cfgparse: Code reindentation.
From: Frédéric Lécaille May help the series of patches to be reviewed. May be backported to 1.5 and newer. --- src/cfgparse.c | 72 +- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index 6670a861..04e36e8c 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -648,49 +648,49 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) /* We are done. */ goto out; - /* Current is local peer, it define a frontend */ - newpeer->local = 1; - cfg_peers->local = newpeer; - - if (!curpeers->peers_fe) { - if (init_peers_frontend(file, linenum, args[1], curpeers) != 0) { - ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); - err_code |= ERR_ALERT | ERR_ABORT; - goto out; - } + /* Current is local peer, it define a frontend */ + newpeer->local = 1; + cfg_peers->local = newpeer; - bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); + if (!curpeers->peers_fe) { + if (init_peers_frontend(file, linenum, args[1], curpeers) != 0) { + ha_alert("parsing [%s:%d] : out of memory.\n", file, linenum); + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } - if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { - if (errmsg && *errmsg) { - indent_msg(&errmsg, 2); - ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); - } - else - ha_alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n", -file, linenum, args[0], args[1], args[2]); - err_code |= ERR_FATAL; - goto out; - } + bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); - list_for_each_entry(l, &bind_conf->listeners, by_bind) { - l->maxaccept = 1; - l->maxconn = curpeers->peers_fe->maxconn; - l->backlog = curpeers->peers_fe->backlog; - l->accept = session_accept_fd; - l->analysers |= curpeers->peers_fe->fe_req_ana; - l->default_target = curpeers->peers_fe->default_target; - l->options |= LI_O_UNLIMITED; /* don't make the peers subject to global limits */ - global.maxsock += l->maxconn; + if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { + if (errmsg && *errmsg) { + indent_msg(&errmsg, 2); + ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg); } - } - else { - ha_alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n", -file, linenum, args[0], args[1], -curpeers->peers_fe->conf.file, curpeers->peers_fe->conf.line); + else + ha_alert("parsing [%s:%d] : '%s %s' : error encountered while parsing listening address %s.\n", +file, linenum, args[0], args[1], args[2]); err_code |= ERR_FATAL; goto out; } + + list_for_each_entry(l, &bind_conf->listeners, by_bind) { + l->maxaccept = 1; + l->maxconn = curpeers->peers_fe->maxconn; + l->backlog = curpeers->peers_fe->backlog; + l->accept = session_accep
[PATCH 08/10] MINOR: peers: Make outgoing connection to SSL/TLS peers work.
From: Frédéric Lécaille This patch adds pointer to a struct server to peer structure which is initialized after having parsed a remote "peer" line. After having parsed all peers section we run ->prepare_srv to initialize all SSL/TLS stuff of remote perr (or server). Remaining thing to do to completely support peer protocol over SSL/TLS: make "bind" keyword be supported in "peers" sections to make SSL/TLS incoming connections to local peers work. May be backported to 1.5 and newer. --- include/proto/peers.h | 26 ++ include/types/peers.h | 1 + src/cfgparse.c| 13 +++-- src/peers.c | 5 +++-- 4 files changed, 41 insertions(+), 4 deletions(-) diff --git a/include/proto/peers.h b/include/proto/peers.h index 9d4aaff2..ce4feaa4 100644 --- a/include/proto/peers.h +++ b/include/proto/peers.h @@ -25,9 +25,35 @@ #include #include #include +#include #include #include +#if defined(USE_OPENSSL) +static inline enum obj_type *peer_session_target(struct peer *p, struct stream *s) +{ + if (p->srv->use_ssl) + return &p->srv->obj_type; + else + return &s->be->obj_type; +} + +static inline struct xprt_ops *peer_xprt(struct peer *p) +{ + return p->srv->use_ssl ? xprt_get(XPRT_SSL) : xprt_get(XPRT_RAW); +} +#else +static inline enum obj_type *peer_session_target(struct peer *p, struct stream *s) +{ + return &s->be->obj_type; +} + +static inline struct xprt_ops *peer_xprt(struct peer *p) +{ + return xprt_get(XPRT_RAW); +} +#endif + int peers_init_sync(struct peers *peers); void peers_register_table(struct peers *, struct stktable *table); void peers_setup_frontend(struct proxy *fe); diff --git a/include/types/peers.h b/include/types/peers.h index 58c8c4ee..5200d56b 100644 --- a/include/types/peers.h +++ b/include/types/peers.h @@ -67,6 +67,7 @@ struct peer { struct shared_table *remote_table; struct shared_table *last_local_table; struct shared_table *tables; + struct server *srv; __decl_hathreads(HA_SPINLOCK_T lock); /* lock used to handle this peer section */ struct peer *next;/* next peer in the list */ }; diff --git a/src/cfgparse.c b/src/cfgparse.c index 6d199c97..f6f25143 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -514,6 +514,7 @@ static int init_peers_frontend(const char *file, int linenum, out: if (id && !p->id) p->id = strdup(id); + free(p->conf.file); p->conf.args.file = p->conf.file = strdup(file); p->conf.args.line = p->conf.line = linenum; @@ -624,9 +625,10 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) newpeer->sock_init_arg = NULL; HA_SPIN_INIT(&newpeer->lock); - if (strcmp(newpeer->id, localpeer) != 0) - /* We are done. */ + if (strcmp(newpeer->id, localpeer) != 0) { + newpeer->srv = curpeers->peers_fe->srv; goto out; + } if (cfg_peers->local) { ha_alert("parsing [%s:%d] : '%s %s' : local peer name already referenced at %s:%d.\n", @@ -3634,6 +3636,13 @@ out_uri_auth_compat: curpeers->peers_fe = NULL; } else { + p = curpeers->remote; + while (p) { + if (p->srv && p->srv->use_ssl && + xprt_get(XPRT_SSL) && xprt_get(XPRT_SSL)->prepare_srv) + cfgerr += xprt_get(XPRT_SSL)->prepare_srv(p->srv); + p = p->next; + } if (!peers_init_sync(curpeers)) { ha_alert("Peers section '%s': out of memory, giving up on peers.\n", curpeers->id); diff --git a/src/peers.c b/src/peers.c index e580f2ca..d4d3859e 100644 --- a/src/peers.c +++ b/src/peers.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -1996,10 +1997,10 @@ static struct appctx *peer_session_create(struct peers *peers, struct peer *peer if (unlikely((cs = cs_new(conn)) == NULL)) goto out_free_conn; - conn->target = s->target = &s->be->obj_type; + conn->target = s->target = peer_session_target(peer, s); memcpy(&conn->addr.to, &peer->addr, sizeof(conn->addr.to)); - conn_prepare(conn, peer->proto, peer->xprt); + conn_prepare(conn, peer->proto, peer_xprt(peer)); conn_install_mux(conn, &mux_pt_ops, cs, s->be, NULL); si_attach_cs(&s->si[1], cs); -- 2.11.0
[PATCH 02/10] CLEANUP: cfgparse: Return asap from cfg_parse_peers().
From: Frédéric Lécaille Avoid useless code indentation. May be backported to 1.5 and newer. --- src/cfgparse.c | 6 -- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index 6fde7c9f..6670a861 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -644,7 +644,10 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) newpeer->sock_init_arg = NULL; HA_SPIN_INIT(&newpeer->lock); - if (strcmp(newpeer->id, localpeer) == 0) { + if (strcmp(newpeer->id, localpeer) != 0) + /* We are done. */ + goto out; + /* Current is local peer, it define a frontend */ newpeer->local = 1; cfg_peers->local = newpeer; @@ -688,7 +691,6 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) err_code |= ERR_FATAL; goto out; } - } } /* neither "peer" nor "peers" */ else if (!strcmp(args[0], "disabled")) { /* disables this peers section */ curpeers->state = PR_STSTOPPED; -- 2.11.0
[PATCH 00/10] Peers SSL/TLS support
From: Frédéric Lécaille Hi ML, With this series of patches we add the SSL/TLS support to haproxy peers. Regards, Fred. Frédéric Lécaille (10): MINOR: cfgparse: Extract some code to be re-used. CLEANUP: cfgparse: Return asap from cfg_parse_peers(). CLEANUP: cfgparse: Code reindentation. MINOR: cfgparse: Useless frontend initialization in "peers" sections. MINOR: cfgparse: Rework peers frontend init. MINOR: cfgparse: Simplication. MINOR: cfgparse: Make "peer" lines be parsed as "server" lines. MINOR: peers: Make outgoing connection to SSL/TLS peers work. MINOR: cfgparse: SSL/TLS binding in "peers" sections. DOC: peers: SSL/TLS documentation for "peers" doc/configuration.txt | 23 - include/proto/peers.h | 26 + include/types/peers.h | 1 + src/cfgparse.c| 272 +- src/peers.c | 7 +- src/server.c | 3 +- 6 files changed, 234 insertions(+), 98 deletions(-) -- 2.11.0
[PATCH 09/10] MINOR: cfgparse: SSL/TLS binding in "peers" sections.
From: Frédéric Lécaille This patch makes "bind" work in "peers" sections. All "bind" settings are supported, excepted ip:port parameters which are provided on "peer" (or server) line matching the local peer. After having parsed the configuration files ->prepare_bind_conf is run to initialize all SSL/TLS stuff for the local peer. May be backported to 1.5 and newer. --- src/cfgparse.c | 95 ++ 1 file changed, 90 insertions(+), 5 deletions(-) diff --git a/src/cfgparse.c b/src/cfgparse.c index f6f25143..ef69b37d 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -521,6 +521,31 @@ static int init_peers_frontend(const char *file, int linenum, return 0; } +/* Only change ->file, ->line and ->arg struct bind_conf member values + * if already present. + */ +static struct bind_conf *bind_conf_uniq_alloc(struct proxy *p, + const char *file, int line, + const char *arg, struct xprt_ops *xprt) +{ + struct bind_conf *bind_conf; + + if (!LIST_ISEMPTY(&p->conf.bind)) { + bind_conf = LIST_ELEM((&p->conf.bind)->n, typeof(bind_conf), by_fe); + free(bind_conf->file); + bind_conf->file = strdup(file); + bind_conf->line = line; + if (arg) { + free(bind_conf->arg); + bind_conf->arg = strdup(arg); + } + } + else { + bind_conf = bind_conf_alloc(p, file, line, arg, xprt); + } + + return bind_conf; +} /* * Parse a line in a , or section. * Returns the error code, 0 if OK, or any combination of : @@ -541,7 +566,56 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) int err_code = 0; char *errmsg = NULL; - if (strcmp(args[0], "default-server") == 0) { + if (strcmp(args[0], "bind") == 0) { + int cur_arg; + static int kws_dumped; + struct bind_conf *bind_conf; + struct bind_kw *kw; + char *kws; + + cur_arg = 1; + + if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) { + err_code |= ERR_ALERT | ERR_ABORT; + goto out; + } + + bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, linenum, +NULL, xprt_get(XPRT_RAW)); + while (*args[cur_arg] && (kw = bind_find_kw(args[cur_arg]))) { + int ret; + + ret = kw->parse(args, cur_arg, curpeers->peers_fe, bind_conf, &errmsg); + err_code |= ret; + if (ret) { + if (errmsg && *errmsg) { + indent_msg(&errmsg, 2); + ha_alert("parsing [%s:%d] : %s\n", file, linenum, errmsg); + } + else + ha_alert("parsing [%s:%d]: error encountered while processing '%s'\n", +file, linenum, args[cur_arg]); + if (ret & ERR_FATAL) + goto out; + } + cur_arg += 1 + kw->skip; + } + kws = NULL; + if (!kws_dumped) { + kws_dumped = 1; + bind_dump_kws(&kws); + indent_msg(&kws, 4); + } + if (*args[cur_arg] != 0) { + ha_alert("parsing [%s:%d] : unknown keyword '%s' in '%s' section.%s%s\n", +file, linenum, args[cur_arg], cursection, +kws ? " Registered keywords :" : "", kws ? kws: ""); + free(kws); + err_code |= ERR_ALERT | ERR_FATAL; + goto out; + } + } + else if (strcmp(args[0], "default-server") == 0) { if (init_peers_frontend(file, linenum, NULL, curpeers) != 0) { err_code |= ERR_ALERT | ERR_ABORT; goto out; @@ -641,7 +715,7 @@ int cfg_parse_peers(const char *file, int linenum, char **args, int kwm) /* Current is local peer, it define a frontend */ newpeer->local = 1; - bind_conf = bind_conf_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); + bind_conf = bind_conf_uniq_alloc(curpeers->peers_fe, file, linenum, args[2], xprt_get(XPRT_RAW)); if (!str2listener(args[2], curpeers->peers_fe, bind_conf, file, linenum, &errmsg)) { if (errmsg && *errmsg) {
[PATCH 2/2] REGTEST: Adapt reg test doc files to vtest.
From: Frédéric Lécaille This is a first patch to switch from varnishtest to new standalone varnish cache reg testing program: vtest. More information may be found here: https://github.com/vtest/VTest https://varnish-cache.org/docs/trunk/reference/varnishtest.html https://varnish-cache.org/docs/trunk/reference/vtc.html --- doc/regression-testing.txt | 78 +- reg-tests/README | 69 2 files changed, 78 insertions(+), 69 deletions(-) diff --git a/doc/regression-testing.txt b/doc/regression-testing.txt index 2a96b0cd..77ebaecb 100644 --- a/doc/regression-testing.txt +++ b/doc/regression-testing.txt @@ -1,74 +1,82 @@ - +-+ - | HAProxy regression testing with varnishtest | - +-+ + +---+ + | HAProxy regression testing with vtest | + +---+ The information found in this file are a short starting guide to help you to write VTC (Varnish Test Case) scripts (or VTC files) for haproxy regression testing. Such VTC files are currently used to test Varnish cache application developed by Poul-Henning Kamp. A very big thanks you to him for having helped you to add -our haproxy C modules to varnishtest tool. +our haproxy C modules to vtest tool. Note that vtest was formally developed for +varnish cache reg testing and was named varnishtest. vtest is an haproxy specific +version of varnishtest program which reuses the non varnish cache specific code. A lot of general information about how to write VTC files may be found in 'man/vtc.7' -manual. It is *highly* recommended to read this manual before asking. This -documentation only deals with the varnishtest support for haproxy. +manual of varnish cache sources directory or directly on the web here: +https://varnish-cache.org/docs/trunk/reference/vtc.html -varnishtest installation +It is *highly* recommended to read this manual before asking to haproxy ML. This +documentation only deals with the vtest support for haproxy. + + +vtest installation -To use varnishtest you will have to download and compile the recent Varnish cache -sources found at https://github.com/varnishcache/varnish-cache. +To use vtest you will have to download and compile the recent vtest +sources found at https://github.com/vtest/VTest. -To compile Varnish cache : +To compile vtest: -$ ./autogen.sh -$ ./configure -$ make +$ cd VTest +$ make vtest -The varnishtest sources may be found in 'bin/varnishtest' directory. -'bin/varnishtest/tests' is plenty of VTC files for Varnish cache. After having -compiled these sources, the varnishtest executable location is -'bin/varnishtest/varnishtest'. +Note that varnishtest may be also compiled but not without the varnish cache +sources already compiled: -varnishtest is able to search for the haproxy executable file it is supposed to -launch in the PATH environment variable. To force the executable to be used by -varnishtest, the HAPROXY_PROGRAM environment variable for varnishtest may be -typically set as follows: +$ VARNISH_SRC=<...> make varnishtest - $ HAPROXY_PROGRAM=~/srcs/haproxy/haproxy varnishtest ... +After having compiled these sources, the vtest executable location is at the +root of the vtest sources directory. -varnistest exectution +vtest exectution - -varnishtest program comes with interesting options. The most interesting are: +vtest is able to search for the haproxy executable file it is supposed to +launch thanks to the PATH environment variable. To force the executable to be used by +vtest, the HAPROXY_PROGRAM environment variable for vtest may be +typically set as follows: + + $ HAPROXY_PROGRAM=~/srcs/haproxy/haproxy vtest ... + +vtest program comes with interesting options. The most interesting are: -t Timeout in seconds to abort the test if some launched program --v By default, varnishtest does not dump the outputs of processus it launched +-v By default, vtest does not dump the outputs of processus it launched when the test passes. With this option the outputs are dumped even when the test passes. -L to always keep the temporary VTC directories. -l to keep the temporary VTC directories only when the test fails. -About haproxy when launched by varnishtest, -d option is enabled by default. +About haproxy, when launched by vtest, -d option is enabled by default. How to write VTC files -- -A VTC file must start with a "varnishtest" command line followed by a descriptive -line enclosed by double quotes. This is not specific to the VTC files for haproxy. +A VTC file must start with a "varnishtest" or "vtest" command
[PATCH 0/2] Switch to vtest.
From: Frédéric Lécaille Hi ML, With these patches, haproxy switches to the new varnish cache reg testing tool named vtest, formerly known as varnishtest. From the user point of view, there is no very much differences compared to the usage of varnishtest. Before we started the reg testing process as follows: $ VARNISTEST_PROGRAM=<...> make reg-tests now we have to run: $ VTEST_PROGRAM=<...> make reg-tests More information may be found here: https://github.com/vtest/VTest Fred. Frédéric Lécaille (2): REGTEST: Adapt reg test doc files to vtest. REGTEST: Switch to vtest. doc/regression-testing.txt | 78 +- reg-tests/README | 67 ++- scripts/run-regtests.sh| 28 - 3 files changed, 96 insertions(+), 77 deletions(-) -- 2.11.0
[PATCH 1/2] REGTEST: Switch to vtest.
From: Frédéric Lécaille This patch replace the usage of the formerly varnish cache reg testing program, name varnishtest by the new standalone one: vtest. --- Makefile| 10 +- scripts/run-regtests.sh | 28 ++-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/Makefile b/Makefile index 6e77b073..10be7cc3 100644 --- a/Makefile +++ b/Makefile @@ -101,7 +101,7 @@ # SUBVERS: add a sub-version (eg: platform, model, ...). # VERDATE: force haproxy's release date. # -# VARNISHTEST_PROGRAM : location of the varnishtest program to run reg-tests. +# VTEST_PROGRAM : location of the vtest program to run reg-tests. # verbosity: pass V=1 for verbose shell invocation V = 0 @@ -1113,10 +1113,10 @@ reg-tests: reg-tests-help: @echo - @echo "To launch the reg tests for haproxy, first export to your environment VARNISHTEST_PROGRAM variable to point to your varnishtest program:" - @echo "$$ export VARNISHTEST_PROGRAM=/opt/local/bin/varnishtest" + @echo "To launch the reg tests for haproxy, first export to your environment VTEST_PROGRAM variable to point to your vtest program:" + @echo "$$ export VTEST_PROGRAM=/opt/local/bin/vtest" @echo "or" - @echo "$$ setenv VARNISHTEST_PROGRAM /opt/local/bin/varnishtest" + @echo "$$ setenv VTEST_PROGRAM /opt/local/bin/vtest" @echo @echo "The same thing may be done to set your haproxy program with HAPROXY_PROGRAM but with ./haproxy as default value." @echo @@ -1124,7 +1124,7 @@ reg-tests-help: @echo "$$ make reg-tests" @echo @echo "You can also set the programs to be used on the command line:" - @echo "$$ VARNISHTEST_PROGRAM=<...> HAPROXY_PROGRAM=<...> make reg-tests" + @echo "$$ VTEST_PROGRAM=<...> HAPROXY_PROGRAM=<...> make reg-tests" @echo @echo "To run tests with specific levels:" @echo "$$ LEVEL=1,3,4 make reg-tests #list of levels" diff --git a/scripts/run-regtests.sh b/scripts/run-regtests.sh index e648fa0a..8469163b 100755 --- a/scripts/run-regtests.sh +++ b/scripts/run-regtests.sh @@ -13,11 +13,11 @@ _help() run-regtests.sh ./tests1 ./tests2 Parameters: ---j , To run varnishtest with multiple jobs / threads for a faster overall result +--j , To run vtest with multiple jobs / threads for a faster overall result run-regtests.sh ./fasttest --j 16 --v, to run verbose - run-regtests.sh --v, disables the default varnishtest 'quiet' parameter + run-regtests.sh --v, disables the default vtest 'quiet' parameter --debug to show test logs on standard ouput (implies --v) run-regtests.sh --debug @@ -25,8 +25,8 @@ _help() --keep-logs to keep all log directories (by default kept if test fails) run-regtests.sh --keep-logs ---varnishtestparams , passes custom ARGS to varnishtest - run-regtests.sh --varnishtestparams "-n 10" +--vtestparams , passes custom ARGS to vtest + run-regtests.sh --vtestparams "-n 10" --clean to cleanup previous reg-tests log directories and exit run-regtests.sh --clean @@ -54,12 +54,12 @@ _help() #REQUIRE_VERSION=0.0 #REQUIRE_VERSION_BELOW=99.9 - Configure environment variables to set the haproxy and varnishtest binaries to use + Configure environment variables to set the haproxy and vtest binaries to use setenv HAPROXY_PROGRAM /usr/local/sbin/haproxy -setenv VARNISHTEST_PROGRAM /usr/local/bin/varnishtest +setenv VTEST_PROGRAM /usr/local/bin/vtest or export HAPROXY_PROGRAM=/usr/local/sbin/haproxy -export VARNISHTEST_PROGRAM=/usr/local/bin/varnishtest +export VTEST_PROGRAM=/usr/local/bin/vtest EOF exit 0 } @@ -248,8 +248,8 @@ _process() { jobcount="$2" shift ;; ---varnishtestparams) - varnishtestparams="$2" +--vtestparams) + vtestparams="$2" shift ;; --v) @@ -294,7 +294,7 @@ _version() { HAPROXY_PROGRAM="${HAPROXY_PROGRAM:-${PWD}/haproxy}" -VARNISHTEST_PROGRAM="${VARNISHTEST_PROGRAM:-varnishtest}" +VTEST_PROGRAM="${VTEST_PROGRAM:-vtest}" TESTDIR="${TMPDIR:-/tmp}" REGTESTS="" @@ -315,8 +315,8 @@ if ! [ -x "$(command -v $HAPROXY_PROGRAM)" ]; then echo "haproxy not found in path, please specify HAPROXY_PROGRAM environment variable" preparefailed=1 fi -if ! [ -x "$(command -v $VARNISHTEST_PROGRAM)" ]; then - echo "varnishtest not found in path, please specify VARNISHTEST_PROGRAM environment variable" +if ! [ -x "$(command -v $VTEST_PROGRAM)" ]; then + echo "vtest not found in path, please specify VTEST_PROGRAM environment variable" preparefailed=1 fi if [ $preparefailed ]; then @@ -424,14 +424,14 @@ else done fi -echo "## Starting varnishtest ##" +echo "## Starti
[PATCH 0/1] Be more verbous when reg tests fail.
From: Frédéric Lécaille With this patch when the test fails it may be useful to collect additional information coming from varnishtes especially when this latter aborts. For instance without this patch reg-tests/mailers/k_healthcheckmail.vtc does not produce relevant information. $ VARNISHTEST_PROGRAM=<...> make reg-tests reg-tests/mailers/k_healthcheckmail.vtc ## test results in: ... With this patch these following lines are added to the test results output: *diag 0.0 Assert error in vtc_log_emit(), vtc_log.c line 157: *diag 0.0 Condition(vtclog_left > l) not true. (errno=0 Success) In this case varnishtest aborts because its logging buffer is full. We can make it use a 32MB buffer as follows: $ VARNISHTEST_PROGRAM=<...> make reg-tests reg-tests/mailers/k_healthcheckmail.vtc -- \ --varnishtestparams "-b$((32<<20))" with more relevant results: ## test results in: ... c27.1 EXPECT resp.http.mailsreceived (11858) == "16" failed Frédéric Lécaille (1): REGTEST: Add some informatoin to test results. scripts/run-regtests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) -- 2.11.0
[PATCH 1/1] REGTEST: Add some informatoin to test results.
From: Frédéric Lécaille When the reg tests fail, it may be useful to display additional information coming from varnishtest, especially when this latter aborts. In such case, the test output may be made of lines prefixed by "* diag" string. --- scripts/run-regtests.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/run-regtests.sh b/scripts/run-regtests.sh index 80353de9..e648fa0a 100755 --- a/scripts/run-regtests.sh +++ b/scripts/run-regtests.sh @@ -454,7 +454,7 @@ if [ -d "${TESTDIR}" ]; then cat <<- EOF | tee -a "$TESTDIR/failedtests.log" $(echo "## $(cat "$i/INFO") ##") $(echo "## test results in: \"$i\"") -$(grep -- ^ "$i/LOG") +$(grep -E -- "^(|\*diag)" "$i/LOG") EOF done' sh {} + fi -- 2.11.0
[PATCH 1/1] REGTEST: "capture (request|response)" regtest.
From: Frédéric Lécaille --- reg-tests/http-capture/h0.vtc | 92 +++ 1 file changed, 92 insertions(+) create mode 100644 reg-tests/http-capture/h0.vtc diff --git a/reg-tests/http-capture/h0.vtc b/reg-tests/http-capture/h0.vtc new file mode 100644 index ..9f6ec8c5 --- /dev/null +++ b/reg-tests/http-capture/h0.vtc @@ -0,0 +1,92 @@ +varnishtest "Tests for 'capture (request|response) header" +feature ignore_unknown_macro + +# This script checks that the last occurrences of "fooresp" and "fooreq" header +# are correctly captured and added to the logs. +# Note that varnishtest does not support more than MAX_HDR header. + +syslog S -level info { +recv +expect ~ "[^:\\[ ]\\[${h_pid}\\]: .* .* fe be/srv .* 200 17641 - - .* .* {HPhx8n59qjjNBLjP} {htb56qDdCcbRVTfS} \"GET / HTTP/1\\.1\"" +} -start + +server s { +rxreq +txresp -hdr "fooresp: HnFDGJ6KvhSG5QjX" -hdr "fooresp: 8dp7vBMQjTMkVwtG" \ + -hdr "fooresp: NTpxWmvsNKGxvH6K" -hdr "fooresp: sPKNNJ5VRBDz9qXP" \ + -hdr "fooresp: HnFDGJ6KvhSG5QjX" -hdr "fooresp: 8dp7vBMQjTMkVwtG" \ + -hdr "fooresp: VSNnccbGkvfM9JK9" -hdr "fooresp: 9D5cjwtK3LCxmg4F" \ + -hdr "fooresp: dsbxGqlBPRWGP3vX" -hdr "fooresp: xf6VK6GXlgdj5mwc" \ + -hdr "fooresp: 8jzM3clRKtdL2WWb" -hdr "fooresp: v7ZHrTPjDR6lm6Bg" \ + -hdr "fooresp: FQT6th9whMqQ7Z6C" -hdr "fooresp: KM22HH6lRBw6SHQT" \ + -hdr "fooresp: PmRHphHXmTV9kZNS" -hdr "fooresp: CkGRbTJrD5nSVpFk" \ + -hdr "fooresp: KQ9mzmMHpmmZ2SXP" -hdr "fooresp: W5FqfFDN6dqBxjK7" \ + -hdr "fooresp: bvcxNPK4gpnTvn3z" -hdr "fooresp: BSXRLSWMsgQN54cC" \ + -hdr "fooresp: ZX9ttTnlbXtJK55d" -hdr "fooresp: KH9StjMHF73NqzL8" \ + -hdr "fooresp: W2q2m6MvMLcnXsX7" -hdr "fooresp: wtrjnJgFzHDvMg5r" \ + -hdr "fooresp: Vpk2c2DsbWf2Gtwh" -hdr "fooresp: sCcW2qpRhFHHRDpH" \ + -hdr "fooresp: P4mltXtvxLsnPcNS" -hdr "fooresp: TXgdSKNMmsJ8x9zq" \ + -hdr "fooresp: n5t8pdZgnGFXZDd3" -hdr "fooresp: pD84GCtkWZqWbCM9" \ + -hdr "fooresp: wx2FPxsGqSRjNVws" -hdr "fooresp: TXmtBCqPTVGFc3NK" \ + -hdr "fooresp: 4DrFTLxpcPk2n3Zv" -hdr "fooresp: vrcFr9MWpqJWhK4h" \ + -hdr "fooresp: HMsCHMZnHT3q8qD2" -hdr "fooresp: HsCXQGTxDpsMf4z6" \ + -hdr "fooresp: 9rb2vjvvd2SzCQVT" -hdr "fooresp: qn5C2fZTWHVp7NkC" \ + -hdr "fooresp: ZVd5ltcngZFHXfvr" -hdr "fooresp: j6BZVdV8fkz5tgjR" \ + -hdr "fooresp: 6qfVwfHqdfntQjmP" -hdr "fooresp: RRr9nTnwjG6d2x7X" \ + -hdr "fooresp: RJXtWtdJRTss6JgZ" -hdr "fooresp: zzHZWm6bqXDN9k47" \ + -hdr "fooresp: htb56qDdCcbRVTfS" \ + -bodylen 16384 +} -start + +haproxy h -conf { +defaults +mode http +${no-htx} option http-use-htx +timeout client 1s +timeout server 1s +timeout connect 1s + +backend be +server srv ${s_addr}:${s_port} + +frontend fe +option httplog +log ${S_addr}:${S_port} local0 debug err +capture request header fooreq len 25 +capture response header fooresp len 25 + +bind "fd@${fe}" +use_backend be +} -start + +client c1 -connect ${h_fe_sock} { + txreq -hdr "fooreq: c8Ck8sx8qfXk5pSS" -hdr "fooreq: TGNXbG2DF3TmLWK3" \ + -hdr "fooreq: mBxq9Cgr8GN6hkt6" -hdr "fooreq: MHZ6VBCPgs564KfR" \ + -hdr "fooreq: BCCwX2kL9BSMCqvt" -hdr "fooreq: 8rXw87xVTphpRQb7" \ + -hdr "fooreq: gJ3Tp9kXQlqLC8Qp" -hdr "fooreq: dFnLs6wpMl2M5N7c" \ + -hdr "fooreq: r3f9WgQ8Brqw37Kj" -hdr "fooreq: dbJzSSdCqV3ZVtXK" \ + -hdr "fooreq: 5HxHd6g4n2Rj2CNG" -hdr "fooreq: HNqQSNfkt6q4zK26" \ + -hdr "fooreq: rzqNcfskPR7vW4jG" -hdr "fooreq: 9c7txWhsdrwmkR6d" \ + -hdr "fooreq: 3v8Nztg9l9vLSKJm" -hdr "fooreq: lh4WDxMX577h4z3l" \ + -hdr "fooreq: mFtHj5SKDvfcGzfq" -hdr "fooreq: PZ5B5wRM9D7GLm7W" \ + -hdr "fooreq: fFpN4zCkLTxzp5Dz" -hdr "fooreq: J5XMdfCCHmmwkr2f" \ + -hdr "fooreq: KqssZ3SkZnZJF8mz" -hdr "fooreq: HrGgsnBnslKN7Msz" \ + -hdr "fooreq: d8TQltZ39xFZBNx2" -hdr "fooreq: mwDt2k2tvqM8x5kQ" \ + -hdr "fooreq: 7Qh6tM7s7z3P8XCl" -hdr "fooreq: S3mTVbbPhJbLR7n2" \ + -hdr "fooreq: zr7hMDvrrwfvpmTT" -hdr "fooreq: lV9TnZX2CtSnr4k8" \ + -hdr "fooreq: bMdJx8pVDG2nWFNg" -hdr "fooreq: FkGvB2cBwNrB3cm4" \ + -hdr "fooreq: 5ckNn3m6m8r2CXLF" -hdr "fooreq: sk4pJGTSZ5HMPJP5" \ + -hdr "fooreq: HgVgQ73zhLwX6Wzq" -hdr "fooreq: T5k2QbFKvCVJlz4c" \ + -hdr "fooreq: SKcNPw8CXGKhtxNP" -hdr "fooreq: n9fFrcR2kRQJrCpZ" \ + -hdr "fooreq: hrJ2MXCdcSCDhQ6n" -hdr "fooreq: 9xsWQ8srzLDvG9F4" \ + -hdr "fooreq: GNcP9NBTFJkg4hbk" -hdr "fooreq: Vg8B8MNwz4T7q5Tj" \ + -hdr "fooreq: XXns3qPCzZmt9j4G" -hdr "fooreq: hD7TnP43bcPHm5g2" \ + -hdr "fooreq: wZbxVq7MwmfBSqb5" -hdr "fooreq: HPhx8n59qjjNBLjP" \ + -bod
[PATCH 0/1] A basic reg test for HTTP header captures
From: Frédéric Lécaille Hi ML, Here is a basic test to check that this is the last occurence of request/response headers which are sent to the logs. Fred. Frédéric Lécaille (1): REGTEST: "capture (request|response)" regtest. reg-tests/http-capture/h0.vtc | 92 +++ 1 file changed, 92 insertions(+) create mode 100644 reg-tests/http-capture/h0.vtc -- 2.11.0
[PATCH 1/1] REGTEST: A basic test for "http-buffer-request"
From: Frédéric Lécaille --- reg-tests/http-messaging/h3.vtc | 78 + 1 file changed, 78 insertions(+) create mode 100644 reg-tests/http-messaging/h3.vtc diff --git a/reg-tests/http-messaging/h3.vtc b/reg-tests/http-messaging/h3.vtc new file mode 100644 index ..2ce21408 --- /dev/null +++ b/reg-tests/http-messaging/h3.vtc @@ -0,0 +1,78 @@ +varnishtest "A test for http-request-buffer option" +feature ignore_unknown_macro + +#REQUIRE_VERSION=1.6 + +# This test checks HTTP request buffering feature. +# We run one server s1 which can serve only one client (no -repeat argument here). +# c1 client uses a malformed request which is not transferred to s1 server +# thanks to "http-buffer-request". If this was the case, c2 client +# could not connect to s1 server and this would lead to make this test fail. + +server s1 { + rxreq + expect req.bodylen == 257 + txresp +} -start + +syslog S -level info { + recv + expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe1 fe1/ .* 408 .* - - cD-- .* .* \"GET /this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url-this-is-a-long-url HTTP/1\\.1\"" + recv + expect ~ "[^:\\[ ]*\\[[0-9]*\\]: .* .* fe1 be1/srv1 0/0/0/0/0 200 .* - - .* .* \"GET / HTTP/1\\.1\"" +} -start + +haproxy h1 -conf { + defaults + mode http + ${no-htx} option http-use-htx + timeout client 100ms + timeout server 1s + timeout connect 1s + + backend be1 + server srv1 ${s1_addr}:${s1_port} + + frontend fe1 + option httplog + option http-buffer-request + log ${S_addr}:${S_port} local0 debug err + bind "fd@${fe1}" + use_backend be1 +} -start + +client c1 -connect ${h1_fe1_sock} { + send "GET" + send " " + send "/this-is-a-long-url" + send "-this-is-a-long-url" + send "-this-is-a-long-url" + send "-this-is-a-long-url" + send "-this-is-a-long-url" + send "-this-is-a-long-url" + send "-this-is-a-long-url" + send " HTT" + send "P/1.1" + send "\r" + send "\n" + send "Content-Length: 209\r\n\r\n" + send "abcdefghijklmnopqrstuvwxyz" + send "abcdefghijklmnopqrstuvwxyz" + send "abcdefghijklmnopqrstuvwxyz" + send "abcdefghijklmnopqrstuvwxyz" + send "abcdefghijklmnopqrstuvwxyz" + send "abcdefghijklmnopqrstuvwxyz" + send "abcdefghijklmnopqrstuvwxyz" + send "abcdefghijklmnopqrstuvwxyz" + rxresp + expect resp.status == 408 +} -run + +client c2 -connect ${h1_fe1_sock} { + txreq -bodylen 257 + rxresp + expect resp.status == 200 +} -run + +syslog S -wait + -- 2.11.0
[PATCH 0/1] A reg test for "http-buffer-request" option
From: Frédéric Lécaille Fred. Frédéric Lécaille (1): REGTEST: A basic test for "http-buffer-request" reg-tests/http-messaging/h3.vtc | 78 + 1 file changed, 78 insertions(+) create mode 100644 reg-tests/http-messaging/h3.vtc -- 2.11.0
[PATCH 2/4] REGTEST: Be less Linux specific with a syslog regex.
From: Frédéric Lécaille This patch makes at least this test pass on FreeBSD systems. The regex to be matched with syslog message was too much Linux specific. --- reg-tests/checks/s3.vtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg-tests/checks/s3.vtc b/reg-tests/checks/s3.vtc index b57b965f..6ce10b0e 100644 --- a/reg-tests/checks/s3.vtc +++ b/reg-tests/checks/s3.vtc @@ -27,7 +27,7 @@ syslog S3 -level notice { recv expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be3 started" recv -expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be3/srv3 failed, reason: Layer4 connection problem, info: \"General socket error \\(Network is unreachable\\)\", check duration: [[:digit:]]+ms, status: 0/1 DOWN." +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be3/srv3 failed, reason: Layer4 .* check duration: [[:digit:]]+ms, status: 0/1 DOWN." } -start syslog S4 -level notice { -- 2.11.0
[PATCH 4/4] REGTEST: Exclude freebsd target for some reg tests.
From: Frédéric Lécaille This patch excludes freebsd target for health-checks reg tests which rely on TCP_DEFER_ACCEPT usage. This is specific to Linux. --- reg-tests/checks/s0.vtc | 1 + reg-tests/checks/s1.vtc | 2 ++ reg-tests/checks/s2.vtc | 1 + 3 files changed, 4 insertions(+) diff --git a/reg-tests/checks/s0.vtc b/reg-tests/checks/s0.vtc index 0aae83a5..93575d34 100644 --- a/reg-tests/checks/s0.vtc +++ b/reg-tests/checks/s0.vtc @@ -2,6 +2,7 @@ varnishtest "Health-check test" feature ignore_unknown_macro #REQUIRE_VERSION=1.8 +#EXCLUDE_TARGETS=freebsd # This script test health-checks for four backends with one server by backend. # A syslog server is attached to each backend to check the syslog messages diff --git a/reg-tests/checks/s1.vtc b/reg-tests/checks/s1.vtc index ff972efd..abb0f2fc 100644 --- a/reg-tests/checks/s1.vtc +++ b/reg-tests/checks/s1.vtc @@ -6,6 +6,8 @@ feature ignore_unknown_macro # The first health-checks passed tests are checked for all these servers # thanks to syslog messages. +#EXCLUDE_TARGETS=freebsd + # Note that the first syslog message received is: "Proxy started." syslog S -repeat 21 -level notice { recv diff --git a/reg-tests/checks/s2.vtc b/reg-tests/checks/s2.vtc index 7246..2449ba75 100644 --- a/reg-tests/checks/s2.vtc +++ b/reg-tests/checks/s2.vtc @@ -2,6 +2,7 @@ varnishtest "Health-checks" feature ignore_unknown_macro #REQUIRE_VERSION=1.8 +#EXCLUDE_TARGETS=freebsd # This script start 40 servers named s0 up to s39. # For 0 <= i <= 19: -- 2.11.0
[PATCH 3/4] REGTEST: Missing enclosing quotes for ${tmpdir} macro.
From: Frédéric Lécaille --- reg-tests/connection/b0.vtc | 4 ++-- reg-tests/seamless-reload/b0.vtc | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/reg-tests/connection/b0.vtc b/reg-tests/connection/b0.vtc index 50bb7494..9b36c45a 100644 --- a/reg-tests/connection/b0.vtc +++ b/reg-tests/connection/b0.vtc @@ -36,14 +36,14 @@ haproxy h1 -conf { listen http bind-process 1 -bind unix@${tmpdir}/http.socket accept-proxy name ssl-offload-http +bind unix@"${tmpdir}/http.socket" accept-proxy name ssl-offload-http option forwardfor listen ssl-offload-http option httplog bind-process 2-4 bind "fd@${ssl}" ssl crt ${testdir}/common.pem ssl no-sslv3 alpn h2,http/1.1 -server http unix@${tmpdir}/http.socket send-proxy +server http unix@"${tmpdir}/http.socket" send-proxy } -start diff --git a/reg-tests/seamless-reload/b0.vtc b/reg-tests/seamless-reload/b0.vtc index 8f7acf64..779b2774 100644 --- a/reg-tests/seamless-reload/b0.vtc +++ b/reg-tests/seamless-reload/b0.vtc @@ -18,7 +18,7 @@ feature ignore_unknown_macro haproxy h1 -W -conf { global -stats socket ${tmpdir}/h1/stats level admin expose-fd listeners +stats socket "${tmpdir}/h1/stats" level admin expose-fd listeners defaults mode http @@ -38,7 +38,7 @@ haproxy h1 -W -conf { } -start shell { - kill -USR2 $(cat ${tmpdir}/h1/pid) + kill -USR2 $(cat "${tmpdir}/h1/pid") } client c1 -connect ${h1_testme_sock} { -- 2.11.0
[PATCH 0/4] A few fixes for reg tests.
From: Frédéric Lécaille Hi ML, Here is a series of patches to fix a few reg testing issues. Fred. Frédéric Lécaille (4): REGTEST: Fix a typo about barrier type. REGTEST: Be less Linux specific with a syslog regex. REGTEST: Missing enclosing quotes for ${tmpdir} macro. REGTEST: Exclude freebsd target for some reg tests. reg-tests/checks/s0.vtc | 3 ++- reg-tests/checks/s1.vtc | 2 ++ reg-tests/checks/s2.vtc | 1 + reg-tests/checks/s3.vtc | 2 +- reg-tests/connection/b0.vtc | 4 ++-- reg-tests/seamless-reload/b0.vtc | 4 ++-- 6 files changed, 10 insertions(+), 6 deletions(-) -- 2.11.0
[PATCH 1/4] REGTEST: Fix a typo about barrier type.
From: Frédéric Lécaille Fix a typo, furthermore there is no reason to use a barrier with "sock" as type which are more varnish cache specific: used to synchronize the VCL. --- reg-tests/checks/s0.vtc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/reg-tests/checks/s0.vtc b/reg-tests/checks/s0.vtc index 35d0a988..0aae83a5 100644 --- a/reg-tests/checks/s0.vtc +++ b/reg-tests/checks/s0.vtc @@ -18,7 +18,7 @@ feature ignore_unknown_macro # before enabling the servers. # Cyclic barrier to synchonize the CLI with the syslog servers -barrier b1 sock 5 -cyclic +barrier b1 cond 5 -cyclic # These servers are there only for the health-check test. server s1 { -- 2.11.0
[PATCH 1/1] REGTEST: Make reg-tests target support argument.
From: Frédéric Lécaille With this patch we can provide a list of argument to reg-tests target. Useful to run reg tests for a list of VTC files like that: $ VARNISHTEST_PROGRAM=<...> make reg-tests reg-tests/checks/*.vtc --- Makefile | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 47258511..450622ed 100644 --- a/Makefile +++ b/Makefile @@ -1092,9 +1092,15 @@ opts: @echo 'OPTIONS_OBJS="$(strip $(OPTIONS_OBJS))"' @echo 'OBJS="$(strip $(OBJS))"' +ifeq (reg-tests, $(firstword $(MAKECMDGOALS))) + REGTEST_ARGS := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS)) + $(eval $(REGTEST_ARGS):;@true) +endif + # Target to run the regression testing script files. reg-tests: - ./scripts/run-regtests.sh --LEVEL "$$LEVEL" $(REG_TEST_FILES) + @./scripts/run-regtests.sh --LEVEL "$$LEVEL" $(REGTEST_ARGS) $(REG_TEST_FILES) +.PHONY: $(REGTEST_ARGS) reg-tests-help: @echo -- 2.11.0
[PATCH 0/1] REGTEST: Reg testing improvement.
From: Frédéric Lécaille Here is a little patch to make reg-tests target able of taking arguments. May be useful during debugging steps. Thanks to https://stackoverflow.com/questions/2214575/passing-arguments-to-make-run for this recipe. Frédéric Lécaille (1): REGTEST: Make reg-tests target support argument. Makefile | 8 +++- 1 file changed, 7 insertions(+), 1 deletion(-) -- 2.11.0
[PATCH 1/1] REGTEST: Add a reg test for health-checks over SSL/TLS.
From: Frédéric Lécaille This script runs two tests. One with "httpchk" over SSL/TLS and another one with "check-ssl" option. As varnishtest does not support SSL/TLS we use two haproxy processes to run these tests. h2 haproxy process be2 and be4 backends declare one server each wich are the frontend of h1 haproxy process. We check the layer6/7 checks thanks to syslog messages. Signed-off-by: Frédéric Lécaille --- reg-tests/checks/common.pem | 1 + reg-tests/checks/s4.vtc | 99 + 2 files changed, 100 insertions(+) create mode 12 reg-tests/checks/common.pem create mode 100644 reg-tests/checks/s4.vtc diff --git a/reg-tests/checks/common.pem b/reg-tests/checks/common.pem new file mode 12 index ..a4433d56 --- /dev/null +++ b/reg-tests/checks/common.pem @@ -0,0 +1 @@ +../ssl/common.pem \ No newline at end of file diff --git a/reg-tests/checks/s4.vtc b/reg-tests/checks/s4.vtc new file mode 100644 index ..1caeea1b --- /dev/null +++ b/reg-tests/checks/s4.vtc @@ -0,0 +1,99 @@ +varnishtest "Health-check test over TLS/SSL" +feature ignore_unknown_macro + + +# This script tests health-checks for a TLS/SSL backend with "option httpchk" +# and "check-ssl" option enabled attached to h2 haproxy process. This haproxy +# h2 process is chained to h1 other one. +# +server s1 { +rxreq +expect req.method == OPTIONS +expect req.url == * +expect req.proto == HTTP/1.1 +txresp +} -start + +server s2 { +} -start + +syslog S1 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy fe1 started." +recv info +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: .* fe1~ be1/srv1 .* 200 [[:digit:]]+ - - .* \"OPTIONS \\* HTTP/1.1\"" +recv info +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: .* fe1~ be1/srv1 .* 504 [[:digit:]]+ - - sH-- .* \"OPTIONS \\* HTTP/1.1\"" +} -start + +haproxy h1 -conf { +global +tune.ssl.default-dh-param 2048 + +defaults +mode http +timeout client 1s +timeout server 1s +timeout connect 1s + +backend be1 +server srv1 ${s1_addr}:${s1_port} + +backend be2 +server srv2 ${s2_addr}:${s2_port} + +frontend fe1 +option httplog +log ${S1_addr}:${S1_port} len 2048 local0 debug err +bind "fd@${fe1}" ssl crt ${testdir}/common.pem +use_backend be1 + +frontend fe2 +option tcplog +bind "fd@${fe2}" ssl crt ${testdir}/common.pem +use_backend be2 +} -start + +syslog S2 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h2_pid}\\]: Proxy be2 started." +recv +expect ~ "[^:\\[ ]\\[${h2_pid}\\]: Health check for server be2/srv1 succeeded, reason: Layer7 check passed, code: 200, info: \"OK\", check duration: [[:digit:]]+ms, status: 1/1 UP." +recv +expect ~ "[^:\\[ ]\\[${h2_pid}\\]: Health check for server be2/srv1 failed, reason: Layer7 wrong status, code: 504, info: \"Gateway Time-out\", check duration: [[:digit:]]+ms, status: 0/1 DOWN." +} -start + +syslog S4 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h2_pid}\\]: Proxy be4 started." +recv +expect ~ "[^:\\[ ]\\[${h2_pid}\\]: Health check for server be4/srv2 succeeded, reason: Layer6 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP." +} -start + +haproxy h2 -conf { +global +tune.ssl.default-dh-param 2048 + +defaults +timeout client 1s +timeout server 1s +timeout connect 1s +default-server downinter 1s rise 1 fall 1 + +backend be2 +option log-health-checks +option httpchk OPTIONS * HTTP/1.1\r\nHost:\ www +log ${S2_addr}:${S2_port} daemon +server srv1 ${h1_fe1_addr}:${h1_fe1_port} ssl crt ${testdir}/common.pem verify none check + +backend be4 +option log-health-checks +log ${S4_addr}:${S4_port} daemon +server srv2 ${h1_fe2_addr}:${h1_fe2_port} ssl crt ${testdir}/common.pem verify none check-ssl check +} -start + +syslog S1 -wait + +syslog S2 -wait +syslog S4 -wait + -- 2.11.0
[PATCH 1/1] REGTEST: Add a reg test for HTTP cookies.
From: Frédéric Lécaille This script tests the "cookie insert indirect" directive with header checks on server and client side. syslog messages are also checked, especially --II (invalid, insert) flags logging. Signed-off-by: Frédéric Lécaille --- reg-tests/http-cookies/h0.vtc | 58 +++ 1 file changed, 58 insertions(+) create mode 100644 reg-tests/http-cookies/h0.vtc diff --git a/reg-tests/http-cookies/h0.vtc b/reg-tests/http-cookies/h0.vtc new file mode 100644 index ..3ea16acc --- /dev/null +++ b/reg-tests/http-cookies/h0.vtc @@ -0,0 +1,58 @@ +varnishtest "HTTP cookie basic test" +feature ignore_unknown_macro + +# This script tests "cookie insert indirect" directive. +# The client sends a wrong "SRVID=s2" cookie. +# haproxy removes it. +# The server replies with "SRVID=S1" after having checked that +# no cookies were sent by haproxy. +# haproxy replies "SRVID=server-one" to the client. +# We log the HTTP request to a syslog server and check their "--II" +# (invalid, insert) flags. + +syslog S1 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy (fe|be)1 started." +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy (fe|be)1 started." +recv info +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: .* fe1 be1/srv1 .* --II .* \"GET / HTTP/1\\.1\"" +} -start + +server s1 { + rxreq + expect req.http.cookie == +txresp -hdr "Cookie: SRVID=S1" +} -start + +haproxy h1 -conf { + global +log ${S1_addr}:${S1_port} len 2048 local0 debug err + +defaults +mode http + option httplog +timeout client 1s +timeout server 1s +timeout connect 1s +log global + +backend be1 +cookie SRVID insert indirect +server srv1 ${s1_addr}:${s1_port} cookie server-one + +frontend fe1 + option httplog +bind "fd@${fe1}" +use_backend be1 +} -start + +client c1 -connect ${h1_fe1_sock} { +txreq -hdr "Cookie: SRVID=s2" +rxresp +expect resp.http.Set-Cookie ~ "^SRVID=server-one;.*" +} -start + + +client c1 -wait +syslog S1 -wait -- 2.11.0
[PATCH 2/5] REGTEST: Add a first test for health-checks.
From: Frédéric Lécaille Signed-off-by: Frédéric Lécaille --- reg-tests/checks/s0.vtc | 207 1 file changed, 207 insertions(+) create mode 100644 reg-tests/checks/s0.vtc diff --git a/reg-tests/checks/s0.vtc b/reg-tests/checks/s0.vtc new file mode 100644 index ..35d0a988 --- /dev/null +++ b/reg-tests/checks/s0.vtc @@ -0,0 +1,207 @@ +varnishtest "Health-check test" +feature ignore_unknown_macro + +#REQUIRE_VERSION=1.8 + +# This script test health-checks for four backends with one server by backend. +# A syslog server is attached to each backend to check the syslog messages +# in the righ order. + +# First, we check a health-check has passed for all the servers thanks to the syslog +# messages. Then each server is disabled. The health-check status are checked. +# Then each server is re-enabled. Finally health-check status +# verifications for each server terminate the execution of this script. + +# Note that the CLI is synchronized with the syslog servers so that +# to be sure to receive the passed health-checks status messages before +# disabling the servers. Same thing, when we check that the servers are down +# before enabling the servers. + +# Cyclic barrier to synchonize the CLI with the syslog servers +barrier b1 sock 5 -cyclic + +# These servers are there only for the health-check test. +server s1 { +} -start + +server s2 { +} -start + +server s3 { +} -start + +server s4 { +} -start + +syslog S1 -level notice { +recv +expect ~ "Proxy be1 started" +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv1 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +barrier b1 sync +recv alert +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Server be1/srv1 is going DOWN for maintenance. 0 active and 0 backup servers left. [01] sessions active, 0 requeued, 0 remaining in queue." +recv emerg +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: backend be1 has no server available!" +barrier b1 sync +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: (Server be1/srv1 is UP/READY \\(leaving forced maintenance\\).|Health check for server be1/srv1 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP)" +barrier b1 sync +} -start + +syslog S2 -level notice { +recv +expect ~ "Proxy be2 started" +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be2/srv2 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +barrier b1 sync +recv alert +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Server be2/srv2 is going DOWN for maintenance. 0 active and 0 backup servers left. [01] sessions active, 0 requeued, 0 remaining in queue." +recv emerg +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: backend be2 has no server available!" +barrier b1 sync +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: (Server be2/srv2 is UP/READY \\(leaving forced maintenance\\).|Health check for server be2/srv2 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP)" +barrier b1 sync +} -start + +syslog S3 -level notice { +recv +expect ~ "Proxy be3 started" +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be3/srv3 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +barrier b1 sync +recv alert +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Server be3/srv3 is going DOWN for maintenance. 0 active and 0 backup servers left. [01] sessions active, 0 requeued, 0 remaining in queue." +recv emerg +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: backend be3 has no server available!" +barrier b1 sync +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: (Server be3/srv3 is UP/READY \\(leaving forced maintenance\\).|Health check for server be3/srv3 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP)" +barrier b1 sync +} -start + +syslog S4 -level notice { +recv +expect ~ "Proxy be4 started" +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be4/srv4 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +barrier b1 sync +recv alert +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Server be4/srv4 is going DOWN for maintenance. 0 active and 0 backup servers left. [01] sessions active, 0 requeued, 0 remaining in queue." +recv emerg +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: backend be4 has no server available!" +barrier b1 sync +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: (Server be4/srv4 is UP/READY \\(leaving forced maintenance\\).|Health check for server be4/srv4 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP)" +barrier b1 sync +} -start + + +haproxy h1 -conf { +defaults +timeout client 1s +timeout server 1s +timeout connect
[PATCH 1/5] REGTEST: Reg testing improvements.
From: Frédéric Lécaille Add a new target to the Makefile named "reg-tests-help" to have an idea about how to run the reg tests from haproxy Makefile. Handle list of levels and lists of level range passed to make with LEVEL variable. New supported syntax: LEVEL=1,4 make reg-tests LEVEL=1-2,5-6 make reg-tests Add two new levels 5 and 6. 5 is for broken script, 6 for experimental scripts. Signed-off-by: Frédéric Lécaille --- Makefile| 34 +++--- scripts/run-regtests.sh | 91 +++-- 2 files changed, 110 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 587bc048..ae2e75ea 100644 --- a/Makefile +++ b/Makefile @@ -1090,10 +1090,34 @@ opts: @echo 'OBJS="$(strip $(OBJS))"' # Target to run the regression testing script files. -# LEVEL 1 scripts are dedicated to pure haproxy compliance tests (prefixed with 'h' letter). -# LEVEL 2 scripts are slow scripts (prefixed with 's' letter). -# LEVEL 3 scripts are low interest scripts (prefixed with 'l' letter). -# LEVEL 4 scripts are in relation with bugs they help to reproduce (prefixed with 'b' letter). reg-tests: ./scripts/run-regtests.sh --LEVEL "$$LEVEL" $(REG_TEST_FILES) -.PHONY: reg-tests + +reg-tests-help: + @echo + @echo "To launch the reg tests for haproxy, first export to your environment VARNISHTEST_PROGRAM variable to point to your varnishtest program:" + @echo "$$ export VARNISHTEST_PROGRAM=/opt/local/bin/varnishtest" + @echo "or" + @echo "$$ setenv VARNISHTEST_PROGRAM /opt/local/bin/varnishtest" + @echo + @echo "The same thing may be done to set your haproxy program with HAPROXY_PROGRAM but with ./haproxy as default value." + @echo + @echo "To run all the tests:" + @echo "$$ make reg-tests" + @echo + @echo "You can also set the programs to be used on the command line:" + @echo "$$ VARNISHTEST_PROGRAM=<...> HAPROXY_PROGRAM=<...> make reg-tests" + @echo + @echo "To run tests with specific levels:" + @echo "$$ LEVEL=1,3,4 make reg-tests #list of levels" + @echo "$$ LEVEL=1-3,5-6 make reg-tests #list of range of levels" + @echo + @echo "About the levels:" + @echo "LEVEL 1 scripts are dedicated to pure haproxy compliance tests (prefixed with 'h' letter)." + @echo "LEVEL 2 scripts are slow scripts (prefixed with 's' letter)." + @echo "LEVEL 3 scripts are low interest scripts (prefixed with 'l' letter)." + @echo "LEVEL 4 scripts are in relation with bugs they help to reproduce (prefixed with 'b' letter)." + @echo "LEVEL 5 scripts are broken scripts, typically used to fastly disable broken scripts (prefixed with 'k' letter)." + @echo "LEVEL 6 scripts are experimental, typically used to develop new scripts (prefixed with 'e' lettre)." + +.PHONY: reg-tests reg-tests-help diff --git a/scripts/run-regtests.sh b/scripts/run-regtests.sh index 3034e363..3ed38062 100755 --- a/scripts/run-regtests.sh +++ b/scripts/run-regtests.sh @@ -40,10 +40,85 @@ if [ "$1" = "--help" ]; then Configure environment variables to set the haproxy and varnishtest binaries to use setenv HAPROXY_PROGRAM /usr/local/sbin/haproxy setenv VARNISHTEST_PROGRAM /usr/local/bin/varnishtest + or +export HAPROXY_PROGRAM=/usr/local/sbin/haproxy +export VARNISHTEST_PROGRAM=/usr/local/bin/varnishtest EOF return fi +add_range_to_test_list() +{ +level0="*.vtc" +level1="h*.vtc" +level2="s*.vtc" +level3="l*.vtc" +level4="b*.vtc" +level5="k*.vtc" +level6="e*.vtc" + +new_range=$(echo $1 | tr '-' ' ') +non_digit=$(echo $new_range | grep '[^0-9 ]') +if [ -n "$non_digit" ] ; then +return +fi +if [ "$new_range" = "$1" ] ; then +if [ $1 -gt 6 ] ; then +return +fi +eval echo '$'level$1 +return +fi +if [ -z "$new_range" ] ; then +return +fi +list= +for l in $(seq $new_range) ; do +if [ -n "l" ] ; then +if [ -z "$list" ] ; then +list="$(eval echo '$'level${l})" +else +list="$list $(eval echo '$'level${l})" +fi +fi +done + +echo $list +} + + +build_test_list() +{ +# Remove any spacing character +LEVEL="$(echo $LEVEL | tr -d ' ')" +# Replave any comma character by a space character +LEVEL="$(echo $LEVEL | tr ',' ' ')" +list= +for range in $LEVEL ; do +if [ -z "$list" ] ; then +list=$(add_range_to_test_list $range) +else +list="$list $(add_range_to_test_list $range)" +fi +done + +echo $list +} + +build_find_expr() +{ +expr= +for i in $@; do +if [ -z "$expr" ] ; then +expr="-name \"$i\"" +else +expr="$expr -o -name \"$i\"" +
[PATCH 4/5] REGTEST: level 1 health-check test 2.
From: Frédéric Lécaille With this test we check that the health-checks do not consume any connection on the backend side. Signed-off-by: Frédéric Lécaille --- reg-tests/checks/s2.vtc | 677 1 file changed, 677 insertions(+) create mode 100644 reg-tests/checks/s2.vtc diff --git a/reg-tests/checks/s2.vtc b/reg-tests/checks/s2.vtc new file mode 100644 index ..7246 --- /dev/null +++ b/reg-tests/checks/s2.vtc @@ -0,0 +1,677 @@ +varnishtest "Health-checks" +feature ignore_unknown_macro + +#REQUIRE_VERSION=1.8 + +# This script start 40 servers named s0 up to s39. +# For 0 <= i <= 19: +# - s(i) and s(i+1) belong to backend be(2*i+1), +# - fe(2*i+1) backend is configured to used be(2*i+1) backend. +# - only s(2*i+1) servers have health-checks enabled, +# - we start 20 clients named s(2*i+1) which connect to fe(2*i+1) frontend, +# - so that to ensure that health-checks do not consume any connection +# (any varnishtest server without -repeat with n > 1 accepts +# only one connection). + +# Note that the first syslog message received is: "Proxy started." +syslog S1 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be1 started." +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv1 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +} -start + +syslog S3 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be3 started." +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be3/srv3 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +} -start + +syslog S5 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be5 started." +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be5/srv5 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +} -start + +syslog S7 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be7 started." +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be7/srv7 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +} -start + +syslog S9 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be9 started." +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be9/srv9 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +} -start + +syslog S11 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be11 started." +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be11/srv11 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +} -start + +syslog S13 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be13 started." +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be13/srv13 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +} -start + +syslog S15 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be15 started." +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be15/srv15 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +} -start + +syslog S17 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be17 started." +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be17/srv17 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +} -start + +syslog S19 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be19 started." +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be19/srv19 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +} -start + +syslog S21 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be21 started." +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be21/srv21 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +} -start + +syslog S23 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be23 started." +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be23/srv23 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +} -start + +syslog S25 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be25 started." +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be25/srv25 succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP" +} -start + +syslog S27 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be27 started." +recv +expect ~ "[^:\\[ ]\\[${h
[PATCH 3/5] REGTEST: Reg test for "check" health-check option.
From: Frédéric Lécaille Signed-off-by: Frédéric Lécaille --- reg-tests/checks/s1.vtc | 114 1 file changed, 114 insertions(+) create mode 100644 reg-tests/checks/s1.vtc diff --git a/reg-tests/checks/s1.vtc b/reg-tests/checks/s1.vtc new file mode 100644 index ..ff972efd --- /dev/null +++ b/reg-tests/checks/s1.vtc @@ -0,0 +1,114 @@ +varnishtest "Health-checks: only for servers with 'check' set" +feature ignore_unknown_macro + +# This test start 40 servers in the same backend, named srv0 up to srv39. +# Only the odd servers have health-checks enabled. +# The first health-checks passed tests are checked for all these servers +# thanks to syslog messages. + +# Note that the first syslog message received is: "Proxy started." +syslog S -repeat 21 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: (Health check for server be1/srv([13579]|[123][13579]) succeeded, reason: Layer4 check passed, check duration: [[:digit:]]+ms, status: 1/1 UP|Proxy be1 started.)" +} -start + +server s0 {} -start +server s1 {} -start +server s2 {} -start +server s3 {} -start +server s4 {} -start +server s5 {} -start +server s6 {} -start +server s7 {} -start +server s8 {} -start +server s9 {} -start +server s10 {} -start +server s11 {} -start +server s12 {} -start +server s13 {} -start +server s14 {} -start +server s15 {} -start +server s16 {} -start +server s17 {} -start +server s18 {} -start +server s19 {} -start +server s20 {} -start +server s21 {} -start +server s22 {} -start +server s23 {} -start +server s24 {} -start +server s25 {} -start +server s26 {} -start +server s27 {} -start +server s28 {} -start +server s29 {} -start +server s30 {} -start +server s31 {} -start +server s32 {} -start +server s33 {} -start +server s34 {} -start +server s35 {} -start +server s36 {} -start +server s37 {} -start +server s38 {} -start +server s39 {} -start + +haproxy h1 -conf { +defaults +timeout client 1s +timeout server 1s +timeout connect 1s +default-server no-check downinter 1s rise 1 fall 1 + +backend be1 +option log-health-checks +log ${S_addr}:${S_port} daemon +server srv0 ${s0_addr}:${s0_port} +server srv1 ${s1_addr}:${s1_port} check +server srv2 ${s2_addr}:${s2_port} +server srv3 ${s3_addr}:${s3_port} check +server srv4 ${s4_addr}:${s4_port} +server srv5 ${s5_addr}:${s5_port} check +server srv6 ${s6_addr}:${s6_port} +server srv7 ${s7_addr}:${s7_port} check +server srv8 ${s8_addr}:${s8_port} +server srv9 ${s9_addr}:${s9_port} check +server srv10 ${s10_addr}:${s10_port} +server srv11 ${s11_addr}:${s11_port} check +server srv12 ${s12_addr}:${s12_port} +server srv13 ${s13_addr}:${s13_port} check +server srv14 ${s14_addr}:${s14_port} +server srv15 ${s15_addr}:${s15_port} check +server srv16 ${s16_addr}:${s16_port} +server srv17 ${s17_addr}:${s17_port} check +server srv18 ${s18_addr}:${s18_port} +server srv19 ${s19_addr}:${s19_port} check +server srv20 ${s20_addr}:${s20_port} +server srv21 ${s21_addr}:${s21_port} check +server srv22 ${s22_addr}:${s22_port} +server srv23 ${s23_addr}:${s23_port} check +server srv24 ${s24_addr}:${s24_port} +server srv25 ${s25_addr}:${s25_port} check +server srv26 ${s26_addr}:${s26_port} +server srv27 ${s27_addr}:${s27_port} check +server srv28 ${s28_addr}:${s28_port} +server srv29 ${s29_addr}:${s29_port} check +server srv30 ${s30_addr}:${s30_port} +server srv31 ${s31_addr}:${s31_port} check +server srv32 ${s32_addr}:${s32_port} +server srv33 ${s33_addr}:${s33_port} check +server srv34 ${s34_addr}:${s34_port} +server srv35 ${s35_addr}:${s35_port} check +server srv36 ${s36_addr}:${s36_port} +server srv37 ${s37_addr}:${s37_port} check +server srv38 ${s38_addr}:${s38_port} +server srv39 ${s39_addr}:${s39_port} check +} -start + +syslog S -wait + +haproxy h1 -cli { +send "show servers state" +expect ~ "# be_id be_name srv_id srv_name srv_addr srv_op_state srv_admin_state srv_uweight srv_iweight srv_time_since_last_change srv_check_status srv_check_result srv_check_health srv_check_state srv_agent_state bk_f_forced_id srv_f_forced_id srv_fqdn srv_port srvrecord\n2 be1 1 srv0 ${s0_addr} 2 0 1 1 [[:digit:]]+ 1 0 1 0 0 0 0 - ${s0_port} -\n2 be1 2 srv1 ${s1_addr} 2 0 1 1 [[:digit:]]+ 6 ([[:digit:]]+ ){3}0 0 0 - ${s1_port} -\n2 be1 3 srv2 ${s2_addr} 2 0 1 1 [[:digit:]]+ 1 0 1 0 0 0 0 - ${s2_port} -\n2 be1 4 srv3 ${s3_addr} 2 0 1 1 [[:digit:]]+ 6 ([[:digit:]]+ ){3}0 0 0 - ${s3_port} -\n2 be1 5 srv4 ${s4_addr} 2 0 1 1 [[:digit:]]+ 1 0 1 0 0 0 0 - ${s4_port} -\n2 be1 6 srv5 ${s5_addr} 2 0 1 1 [[:digit:]]+ 6 ([[:digit:]]+ ){3}0 0 0 - ${s5_port} -\n
[PATCH 5/5] REGTEST: Add miscellaneous reg tests for health-checks.
From: Frédéric Lécaille Signed-off-by: Frédéric Lécaille --- reg-tests/checks/s3.vtc | 95 + 1 file changed, 95 insertions(+) create mode 100644 reg-tests/checks/s3.vtc diff --git a/reg-tests/checks/s3.vtc b/reg-tests/checks/s3.vtc new file mode 100644 index ..b57b965f --- /dev/null +++ b/reg-tests/checks/s3.vtc @@ -0,0 +1,95 @@ +varnishtest "Check: smptchk option" +feature ignore_unknown_macro + +barrier b cond 3 + +syslog S1 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be1 started" +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be1/srv1 succeeded, reason: Layer7 check passed, code: 248, check duration: [[:digit:]]+ms, status: 1/1 UP." +barrier b sync +recv +expect ~ "Health check for server be1/srv1 failed, reason: Layer7 timeout, check duration: [[:digit:]]+ms, status: 0/1 DOWN" +} -start + +syslog S2 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be2 started" +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be2/srv2 succeeded, reason: Layer7 check passed, code: 200, info: \"OK\", check duration: [[:digit:]]+ms, status: 1/1 UP." +barrier b sync +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be2/srv2 failed, reason: Layer7 timeout, check duration: [[:digit:]]+ms, status: 0/1 DOWN" +} -start + +syslog S3 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be3 started" +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be3/srv3 failed, reason: Layer4 connection problem, info: \"General socket error \\(Network is unreachable\\)\", check duration: [[:digit:]]+ms, status: 0/1 DOWN." +} -start + +syslog S4 -level notice { +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Proxy be4 started" +recv +expect ~ "[^:\\[ ]\\[${h1_pid}\\]: Health check for server be4/srv4 failed, reason: Layer4 connection problem, info: \"Connection refused\", check duration: [[:digit:]]+ms, status: 0/1 DOWN." +} -start + +server s1 { +recv 16 +send "2" +send "4" +send "8" +send "\r\n\r\n" +} -start + +server s2 { +rxreq +txresp +} -start + +haproxy h1 -conf { +defaults +timeout client 1s +timeout server 1s +timeout connect 1s +option log-health-checks +default-server downinter 1s rise 1 fall 1 + +backend be1 +option smtpchk +log ${S1_addr}:${S1_port} daemon +server srv1 ${s1_addr}:${s1_port} check + +backend be2 +mode tcp +log ${S2_addr}:${S2_port} daemon +option httpchk OPTIONS * HTTP/1.1\r\nHost:\ www +server srv2 ${s2_addr}:${s2_port} check + +backend be3 +log ${S3_addr}:${S3_port} daemon +server srv3 255.255.255.255:1 check + +backend be4 +log ${S4_addr}:${S4_port} daemon +server srv4 localhost:1 check +} -start + +haproxy h1 -cli { +barrier b sync +send "show servers state" +expect ~ .* +} + +server s1 -wait +server s2 -wait + +syslog S1 -wait +syslog S2 -wait +syslog S3 -wait +syslog S4 -wait + + -- 2.11.0