[6.0] 1c8fed623 More work on vtc_haproxy.
Poul-Henning Kamp
phk at FreeBSD.org
Thu Aug 16 08:52:29 UTC 2018
commit 1c8fed623298ec14a3ef5f0cb33b89b6eedec9f7
Author: Poul-Henning Kamp <phk at FreeBSD.org>
Date: Thu Mar 29 13:52:35 2018 +0000
More work on vtc_haproxy.
I hadn't realized how unsuitable vtc_varnish was to copy from,
because of the dual process complications, this simplifiles
things back again.
Move -D and -W out of -arg, it makes no sense to have to pull
them out of there again.
Add -conf-OK and -conf-BAD arguments.
diff --git a/bin/varnishtest/tests/h00001.vtc b/bin/varnishtest/tests/h00001.vtc
index 3c599a520..1b86d81a0 100644
--- a/bin/varnishtest/tests/h00001.vtc
+++ b/bin/varnishtest/tests/h00001.vtc
@@ -9,7 +9,7 @@ server s1 {
txresp -body "s1 >>> Hello world!"
} -start
-haproxy h1 -arg "-d" -conf {
+haproxy h1 -conf {
defaults
mode http
timeout connect 5s
diff --git a/bin/varnishtest/tests/h00002.vtc b/bin/varnishtest/tests/h00002.vtc
index 6e2af6651..935f2331a 100644
--- a/bin/varnishtest/tests/h00002.vtc
+++ b/bin/varnishtest/tests/h00002.vtc
@@ -9,7 +9,7 @@ server s1 {
txresp -body "s1 >>> Hello world!"
} -start
-haproxy h1 -arg "-D" -conf {
+haproxy h1 -D -conf {
defaults
mode http
timeout connect 5s
diff --git a/bin/varnishtest/tests/h00003.vtc b/bin/varnishtest/tests/h00003.vtc
index c894495b5..404b1eecb 100644
--- a/bin/varnishtest/tests/h00003.vtc
+++ b/bin/varnishtest/tests/h00003.vtc
@@ -9,7 +9,7 @@ server s1 {
txresp -body "s1 >>> Hello world!"
} -start
-haproxy h1 -arg "-d" -conf+backend {
+haproxy h1 -conf+backend {
defaults
mode http
timeout connect 5s
diff --git a/bin/varnishtest/tests/h00004.vtc b/bin/varnishtest/tests/h00004.vtc
new file mode 100644
index 000000000..122e0411d
--- /dev/null
+++ b/bin/varnishtest/tests/h00004.vtc
@@ -0,0 +1,18 @@
+varnishtest "Test -conf+backend"
+
+feature ignore_unknown_macro
+
+feature cmd {haproxy --version 2>&1 | grep -q 'HA-Proxy version'}
+
+haproxy h1 -conf-OK {
+ defaults
+ mode http
+ timeout connect 5s
+ timeout server 30s
+ timeout client 30s
+
+}
+
+haproxy h2 -conf-BAD {unknown keyword 'FOOBAR' in 'global' section} {
+ FOOBAR
+}
diff --git a/bin/varnishtest/vtc_haproxy.c b/bin/varnishtest/vtc_haproxy.c
index d9c03508d..f8eec1215 100644
--- a/bin/varnishtest/vtc_haproxy.c
+++ b/bin/varnishtest/vtc_haproxy.c
@@ -37,7 +37,6 @@
#include "vtc.h"
-#include "vav.h"
#include "vfil.h"
#include "vpf.h"
#include "vtcp.h"
@@ -46,9 +45,9 @@
#define HAPROXY_PROGRAM_ENV_VAR "HAPROXY_PROGRAM"
#define HAPROXY_OPT_WORKER "-W"
#define HAPROXY_OPT_DAEMON "-D"
-#define HAPROXY_OPT_CHECK_MODE "-c"
#define HAPROXY_SIGNAL SIGINT
#define HAPROXY_EXPECT_EXIT (128 + HAPROXY_SIGNAL)
+#define HAPROXY_GOOD_CONF "Configuration file is valid"
struct haproxy {
unsigned magic;
@@ -77,10 +76,9 @@ struct haproxy {
const char *cli_fn;
char *workdir;
+ struct vsb *msgs;
};
-static void haproxy_cleanup(struct haproxy *h, int is_haproxy_listener);
-
static VTAILQ_HEAD(, haproxy) haproxies =
VTAILQ_HEAD_INITIALIZER(haproxies);
@@ -89,42 +87,14 @@ static VTAILQ_HEAD(, haproxy) haproxies =
*/
static void
-wait_stopped(struct haproxy *h)
-{
- vtc_log(h->vl, 3, "wait-stopped");
- while (1) {
- if (h->kill_status >= 0 || h->kill_errno == ESRCH)
- break;
-
- usleep(1000);
- h->kill_status = kill(h->pid, 0);
- h->kill_errno = errno;
- }
-}
-
-static void
-wait_running(struct haproxy *h)
+haproxy_wait_pidfile(struct haproxy *h)
{
char buf_err[1024] = {0};
int usleep_time = 1000;
double t0;
pid_t pid;
- if (h->opt_check_mode)
- return;
-
- if (h->pid_fn == NULL) {
- /*
- * If we use no pid-file, check that the process
- * we started is still running.
- */
- if (kill(h->pid, 0) < 0)
- vtc_fatal(h->vl, "Process %ld not there: %s",
- (long)h->pid, strerror(errno));
- return;
- }
-
- vtc_log(h->vl, 3, "wait-running");
+ vtc_log(h->vl, 3, "wait-pid-file");
for (t0 = VTIM_mono(); VTIM_mono() - t0 < 3;) {
if (vtc_error)
return;
@@ -243,7 +213,7 @@ haproxy_thread(void *priv)
struct haproxy *h;
CAST_OBJ_NOTNULL(h, priv, HAPROXY_MAGIC);
- return (vtc_record(h->vl, h->fds[0], NULL));
+ return (vtc_record(h->vl, h->fds[0], h->msgs));
}
/**********************************************************************
@@ -253,35 +223,30 @@ haproxy_thread(void *priv)
static void
haproxy_start(struct haproxy *h)
{
- char **argv;
- int i;
char buf[PATH_MAX];
struct vsb *vsb;
vtc_log(h->vl, 2, "%s", __func__);
AZ(VSB_finish(h->args));
- argv = VAV_Parse(VSB_data(h->args), NULL, 0);
- AN(argv);
- if (argv[0] != NULL)
- vtc_fatal(h->vl, "Could not parse argv-string: %s", argv[0]);
- for (i = 1; argv[i] != NULL; i++) {
- /* Check if HAPROXY_OPT_WORKER option was provided. */
- if (!strcmp(argv[i], HAPROXY_OPT_WORKER)) {
- h->opt_worker = 1;
- } else if (!strcmp(argv[i], HAPROXY_OPT_DAEMON)) {
- h->opt_daemon = 1;
- } else if (!strcmp(argv[i], HAPROXY_OPT_CHECK_MODE)) {
- h->opt_check_mode = 1;
- }
- }
- VAV_Free(argv);
vtc_log(h->vl, 4, "opt_worker %d opt_daemon %d opt_check_mode %d",
h->opt_worker, h->opt_daemon, h->opt_check_mode);
vsb = VSB_new_auto();
AN(vsb);
- VSB_printf(vsb, "exec %s %s", h->filename, VSB_data(h->args));
+
+ VSB_printf(vsb, "exec %s", h->filename);
+ if (h->opt_check_mode)
+ VSB_printf(vsb, " -c");
+ else if (h->opt_daemon)
+ VSB_printf(vsb, " -D");
+ else
+ VSB_printf(vsb, " -d");
+
+ if (h->opt_worker)
+ VSB_printf(vsb, " -W");
+
+ VSB_printf(vsb, " %s", VSB_data(h->args));
VSB_printf(vsb, " -f %s ", h->cfg_fn);
@@ -301,11 +266,10 @@ haproxy_start(struct haproxy *h)
* if signaled by <signum> signal.
*/
h->expect_exit = HAPROXY_EXPECT_EXIT;
- } else {
- h->expect_exit = 0;
}
AZ(pipe(&h->fds[0]));
+ vtc_log(h->vl, 4, "XXX %d @%d", h->fds[1], __LINE__);
AZ(pipe(&h->fds[2]));
h->pid = h->ppid = fork();
assert(h->pid >= 0);
@@ -334,73 +298,44 @@ haproxy_start(struct haproxy *h)
AZ(pthread_create(&h->tp, NULL, haproxy_thread, h));
- wait_running(h);
+ if (h->pid_fn != NULL)
+ haproxy_wait_pidfile(h);
}
-/**********************************************************************
- * Stop a HAProxy
- */
-
-static void
-haproxy_stop(struct haproxy *h)
-{
- if (h->opt_check_mode)
- return;
-
- if (h->pid < 0)
- haproxy_start(h);
-
- vtc_log(h->vl, 2, "Stop");
- h->kill_status = kill(h->pid, HAPROXY_SIGNAL);
- h->kill_errno = errno;
- h->expect_signal = -HAPROXY_SIGNAL;
-
- wait_stopped(h);
-}
/**********************************************************************
- * Cleanup
+ * Wait for a HAProxy instance.
*/
static void
-haproxy_cleanup(struct haproxy *h, int is_haproxy_listener)
+haproxy_wait(struct haproxy *h)
{
void *p;
- vtc_log(h->vl, 2, "%s (%d)", __func__, is_haproxy_listener);
- if (!is_haproxy_listener) {
- /* Close the STDIN connection. */
- closefd(&h->fds[1]);
-
- /* Wait until STDOUT+STDERR closes */
- AZ(pthread_join(h->tp, &p));
- closefd(&h->fds[0]);
- if (h->opt_daemon)
- return;
- }
-
- if (h->ppid == -1)
- return;
-
- vtc_wait4(h->vl, h->ppid, h->expect_exit, h->expect_signal, 0);
- h->ppid = -1;
-}
-
-/**********************************************************************
- * Wait for a HAProxy instance.
- */
+ vtc_log(h->vl, 2, "Wait");
-static void
-haproxy_wait(struct haproxy *h)
-{
if (h->pid < 0)
- return;
+ haproxy_start(h);
- vtc_log(h->vl, 2, "Wait");
+ closefd(&h->fds[1]);
- haproxy_stop(h);
+ if (!h->opt_check_mode) {
+ assert(h->pid > 0);
+ vtc_log(h->vl, 2, "Stop HAproxy pid=%ld", (long)h->pid);
+ h->kill_status = kill(h->pid, HAPROXY_SIGNAL);
+ h->kill_errno = errno;
+ h->expect_signal = -HAPROXY_SIGNAL;
+ // XXX: loop over kills to ESRCH ?
+ }
- haproxy_cleanup(h, 0);
+ AZ(pthread_join(h->tp, &p));
+ AZ(p);
+ closefd(&h->fds[0]);
+ if (!h->opt_daemon) {
+ vtc_wait4(h->vl, h->ppid, h->expect_exit, h->expect_signal, 0);
+ h->ppid = -1;
+ }
+ h->pid = -1;
}
#define HAPROXY_BE_FD_STR "fd@${"
@@ -454,6 +389,22 @@ haproxy_build_backends(const struct haproxy *h, const char *vsb_data)
return (0);
}
+static void
+haproxy_check_conf(struct haproxy *h, const char *expect)
+{
+
+ h->msgs = VSB_new_auto();
+ AN(h->msgs);
+ h->opt_check_mode = 1;
+ haproxy_start(h);
+ haproxy_wait(h);
+ AZ(VSB_finish(h->msgs));
+ if (strstr(VSB_data(h->msgs), expect) == NULL)
+ vtc_fatal(h->vl, "Did not find expected string '%s'", expect);
+ vtc_log(h->vl, 2, "Found expected '%s'", expect);
+ VSB_destroy(&h->msgs);
+}
+
/**********************************************************************
* Write a configuration for <h> HAProxy instance.
*/
@@ -498,7 +449,9 @@ haproxy_write_conf(const struct haproxy *h, const char *cfg, int auto_be)
*
* To define a haproxy server, you'll use this syntax::
*
- * haproxy hNAME [-arg STRING] [-conf[+vcl] STRING]
+ * haproxy hNAME -conf-OK CONFIG
+ * haproxy hNAME -conf-BAD ERROR CONFIG
+ * haproxy hNAME [-D] [-W] [-arg STRING] [-conf[+vcl] STRING]
*
* The first ``haproxy hNAME`` invocation will start the haproxy master
* process in the background, waiting for the ``-start`` switch to actually
@@ -509,6 +462,22 @@ haproxy_write_conf(const struct haproxy *h, const char *cfg, int auto_be)
* hNAME
* Identify the HAProxy server with a string, it must starts with 'h'.
*
+ * \-conf-OK CONFIG
+ * Run haproxy in '-c' mode to check config is OK
+ * stdout/stderr should contain 'Configuration file is valid'
+ * The exit code should be 0.
+ *
+ * \-conf-BAD ERROR CONFIG
+ * Run haproxy in '-c' mode to check config is BAD.
+ * "ERROR" should be part of the diagnostics on stdout/stderr.
+ * The exit code should be 1.
+ *
+ * \-D
+ * Run HAproxy in daemon mode. If not given '-d' mode used.
+ *
+ * \-W
+ * Enable HAproxy in Worker mode.
+ *
* \-arg STRING
* Pass an argument to haproxy, for example "-h simple_list".
*
@@ -519,26 +488,12 @@ haproxy_write_conf(const struct haproxy *h, const char *cfg, int auto_be)
* Specify the configuration to be loaded by this HAProxy instance,
* all server instances will be automatically appended
*
- * You can decide to start the HAProxy instance and/or wait for several events::
- *
- * haproxy hNAME [-start] [-wait-running] [-wait-stopped]
- *
* \-start
* Start this HAProxy instance.
*
- * \-stop
+ * \-wait
* Stop this HAProxy instance.
*
- * \-wait-running
- * Wait for that instance to terminate.
- *
- * \-wait-stopped
- * Wait for that instance to terminate.
- *
- * \-cleanup
- * Once HAProxy is stopped, clean everything after it. This is only used
- * in very few tests and you should never need it.
- *
* \-expectexit NUMBER
* Expect haproxy to exit(3) with this value
*
@@ -580,6 +535,33 @@ cmd_haproxy(CMD_ARGS)
for (; *av != NULL; av++) {
if (vtc_error)
break;
+
+ if (!strcmp(*av, "-conf-OK")) {
+ AN(av[1]);
+ haproxy_write_conf(h, av[1], 0);
+ av++;
+ haproxy_check_conf(h, HAPROXY_GOOD_CONF);
+ continue;
+ }
+ if (!strcmp(*av, "-conf-BAD")) {
+ AN(av[1]);
+ AN(av[2]);
+ haproxy_write_conf(h, av[2], 0);
+ h->expect_exit = 1;
+ haproxy_check_conf(h, av[1]);
+ av += 2;
+ continue;
+ }
+
+ if (!strcmp(*av, HAPROXY_OPT_DAEMON)) {
+ h->opt_daemon = 1;
+ continue;
+ }
+ if (!strcmp(*av, HAPROXY_OPT_WORKER)) {
+ h->opt_worker = 1;
+ continue;
+ }
+
if (!strcmp(*av, "-arg")) {
AN(av[1]);
AZ(h->pid);
@@ -588,6 +570,7 @@ cmd_haproxy(CMD_ARGS)
av++;
continue;
}
+
if (!strcmp(*av, "-conf")) {
AN(av[1]);
haproxy_write_conf(h, av[1], 0);
@@ -600,6 +583,7 @@ cmd_haproxy(CMD_ARGS)
av++;
continue;
}
+
if (!strcmp(*av, "-expectexit")) {
h->expect_exit = strtoul(av[1], NULL, 0);
av++;
@@ -610,7 +594,7 @@ cmd_haproxy(CMD_ARGS)
continue;
}
if (!strcmp(*av, "-wait")) {
- wait_stopped(h);
+ haproxy_wait(h);
continue;
}
vtc_fatal(h->vl, "Unknown haproxy argument: %s", *av);
More information about the varnish-commit
mailing list