Welcome! Log In Create A New Profile

Advanced

[PATCH 1/4] MINOR: stats admin: allow unordered parameters in POST requests

Posted by Cyril Bonté 
Previously, the stats admin page required POST parameters to be provided
exactly in the same order as the HTML form.
This patch allows to handle those parameters in any orders.

Also, note that haproxy won't alter server states anymore if backend or server
names are ambiguous (duplicated names in the configuration) to prevent
unexpected results (the same should probably be applied to the stats socket).
---
include/proto/dumpstats.h | 4 +-
include/types/proto_http.h | 7 +++
src/dumpstats.c | 20 ++++++++
src/proto_http.c | 105 ++++++++++++++++++++++++++++++++++---------
4 files changed, 113 insertions(+), 23 deletions(-)

diff --git a/include/proto/dumpstats.h b/include/proto/dumpstats.h
index eb44a36..4c3837b 100644
--- a/include/proto/dumpstats.h
+++ b/include/proto/dumpstats.h
@@ -58,8 +58,10 @@
/* status codes (strictly 4 chars) used in the URL to display a message */
#define STAT_STATUS_UNKN "UNKN" /* an unknown error occured, shouldn't happen */
#define STAT_STATUS_DONE "DONE" /* the action is successful */
+#define STAT_STATUS_PART "PART" /* the action is partially successful */
#define STAT_STATUS_NONE "NONE" /* nothing happened (no action chosen or servers state didn't change) */
-#define STAT_STATUS_EXCD "EXCD" /* an error occured becayse the buffer couldn't store all data */
+#define STAT_STATUS_ERRP "ERRP" /* an error occured due to invalid values in parameters */
+#define STAT_STATUS_EXCD "EXCD" /* an error occured because the buffer couldn't store all data */
#define STAT_STATUS_DENY "DENY" /* action denied */

extern struct si_applet http_stats_applet;
diff --git a/include/types/proto_http.h b/include/types/proto_http.h
index f1b3eef..a7b16aa 100644
--- a/include/types/proto_http.h
+++ b/include/types/proto_http.h
@@ -251,6 +251,13 @@ enum {
HTTP_ERR_SIZE
};

+/* Actions available for the stats admin forms */
+enum {
+ ST_ADM_ACTION_NONE = 0,
+ ST_ADM_ACTION_DISABLE,
+ ST_ADM_ACTION_ENABLE,
+};
+
/* This is an HTTP message, as described in RFC2616. It can be either a request
* message or a response message.
*
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 142429b..16d07dd 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -2037,6 +2037,26 @@ static int stats_dump_http(struct stream_interface *si, struct uri_auth *uri)
"Nothing has changed."
"</div>\n", uri->uri_prefix);
}
+ else if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_PART) == 0) {
+ chunk_printf(&msg,
+ "<p><div class=active2>"
+ "<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
+ "Action partially processed.<br>"
+ "Some server names are probably unknown or ambiguous (duplicated names in the backend)."
+ "</div>\n", uri->uri_prefix);
+ }
+ else if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_ERRP) == 0) {
+ chunk_printf(&msg,
+ "<p><div class=active0>"
+ "<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
+ "Action not processed because of invalid parameters."
+ "<ul>"
+ "<li>The action is maybe unknown.</li>"
+ "<li>The backend name is probably unknown or ambiguous (duplicated names).</li>"
+ "<li>Some server names are probably unknown or ambiguous (duplicated names in the backend).</li>"
+ "</ul>"
+ "</div>\n", uri->uri_prefix);
+ }
else if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_EXCD) == 0) {
chunk_printf(&msg,
"<p><div class=active0>"
diff --git a/src/proto_http.c b/src/proto_http.c
index ed8e018..bf91328 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -2545,13 +2545,18 @@ int http_wait_for_request(struct session *s, struct buffer *req, int an_bit)
*/
int http_process_req_stat_post(struct stream_interface *si, struct http_txn *txn, struct buffer *req)
{
- struct proxy *px;
- struct server *sv;
+ struct proxy *px = NULL;
+ struct server *sv = NULL;

- char *backend = NULL;
- int action = 0;
+ char key[LINESIZE];
+ int action = ST_ADM_ACTION_NONE;
+ int reprocess = 0;
+
+ int total_servers = 0;
+ int altered_servers = 0;

char *first_param, *cur_param, *next_param, *end_params;
+ char *st_cur_param, *st_next_param;

first_param = req->data + txn->req.eoh + 2;
end_params = first_param + txn->req.body_len;
@@ -2578,15 +2583,21 @@ int http_process_req_stat_post(struct stream_interface *si, struct http_txn *txn
* From the html form, the backend and the action are at the end.
*/
while (cur_param > first_param) {
- char *key, *value;
+ char *value;
+ int poffset, plen;

cur_param--;
if ((*cur_param == '&') || (cur_param == first_param)) {
+ reprocess_servers:
/* Parse the key */
- key = cur_param;
- if (cur_param != first_param) {
- /* delimit the string for the next loop */
- *key++ = '\0';
+ poffset = (cur_param != first_param ? 1 : 0);
+ plen = next_param - cur_param + (cur_param == first_param ? 1 : 0);
+ if ((plen > 0) && (plen <= sizeof(key))) {
+ strncpy(key, cur_param + poffset, plen);
+ key[plen - 1] = '\0';
+ } else {
+ si->applet.ctx.stats.st_code = STAT_STATUS_EXCD;
+ goto out;
}

/* Parse the value */
@@ -2603,45 +2614,91 @@ int http_process_req_stat_post(struct stream_interface *si, struct http_txn *txn
break;

/* Now we can check the key to see what to do */
- if (!backend && strcmp(key, "b") == 0) {
- backend = value;
+ if (!px && (strcmp(key, "b") == 0)) {
+ if ((px = findproxy(value, PR_CAP_BE)) == NULL) {
+ /* the backend name is unknown or ambiguous (duplicate names) */
+ si->applet.ctx.stats.st_code = STAT_STATUS_ERRP;
+ goto out;
+ }
}
- else if (!action && strcmp(key, "action") == 0) {
+ else if (!action && (strcmp(key, "action") == 0)) {
if (strcmp(value, "disable") == 0) {
- action = 1;
+ action = ST_ADM_ACTION_DISABLE;
}
else if (strcmp(value, "enable") == 0) {
- action = 2;
- } else {
- /* unknown action, no need to continue */
- break;
+ action = ST_ADM_ACTION_ENABLE;
+ }
+ else {
+ si->applet.ctx.stats.st_code = STAT_STATUS_ERRP;
+ goto out;
}
}
else if (strcmp(key, "s") == 0) {
- if (backend && action && get_backend_server(backend, value, &px, &sv)) {
+ if (!(px && action)) {
+ /*
+ * Indicates that we'll need to reprocess the parameters
+ * as soon as backend and action are known
+ */
+ if (!reprocess) {
+ st_cur_param = cur_param;
+ st_next_param = next_param;
+ }
+ reprocess = 1;
+ }
+ else if ((sv = findserver(px, value)) != NULL) {
switch (action) {
- case 1:
+ case ST_ADM_ACTION_DISABLE:
if ((px->state != PR_STSTOPPED) && !(sv->state & SRV_MAINTAIN)) {
/* Not already in maintenance, we can change the server state */
sv->state |= SRV_MAINTAIN;
set_server_down(sv);
- si->applet.ctx.stats.st_code = STAT_STATUS_DONE;
+ altered_servers++;
+ total_servers++;
}
break;
- case 2:
+ case ST_ADM_ACTION_ENABLE:
if ((px->state != PR_STSTOPPED) && (sv->state & SRV_MAINTAIN)) {
/* Already in maintenance, we can change the server state */
set_server_up(sv);
sv->health = sv->rise; /* up, but will fall down at first failure */
- si->applet.ctx.stats.st_code = STAT_STATUS_DONE;
+ altered_servers++;
+ total_servers++;
}
break;
}
+ } else {
+ /* the server name is unknown or ambiguous (duplicate names) */
+ total_servers++;
}
}
+ if (reprocess && px && action) {
+ /* Now, we know the backend and the action chosen by the user.
+ * We can safely restart from the first server parameter
+ * to reprocess them
+ */
+ cur_param = st_cur_param;
+ next_param = st_next_param;
+ reprocess = 0;
+ goto reprocess_servers;
+ }
+
next_param = cur_param;
}
}
+
+ if (total_servers == 0) {
+ si->applet.ctx.stats.st_code = STAT_STATUS_NONE;
+ }
+ else if (altered_servers == 0) {
+ si->applet.ctx.stats.st_code = STAT_STATUS_ERRP;
+ }
+ else if (altered_servers == total_servers) {
+ si->applet.ctx.stats.st_code = STAT_STATUS_DONE;
+ }
+ else {
+ si->applet.ctx.stats.st_code = STAT_STATUS_PART;
+ }
+ out:
return 1;
}

@@ -7124,6 +7181,10 @@ int stats_check_uri(struct stream_interface *si, struct http_txn *txn, struct pr
si->applet.ctx.stats.st_code = STAT_STATUS_DONE;
else if (memcmp(h, STAT_STATUS_NONE, 4) == 0)
si->applet.ctx.stats.st_code = STAT_STATUS_NONE;
+ else if (memcmp(h, STAT_STATUS_PART, 4) == 0)
+ si->applet.ctx.stats.st_code = STAT_STATUS_PART;
+ else if (memcmp(h, STAT_STATUS_ERRP, 4) == 0)
+ si->applet.ctx.stats.st_code = STAT_STATUS_ERRP;
else if (memcmp(h, STAT_STATUS_EXCD, 4) == 0)
si->applet.ctx.stats.st_code = STAT_STATUS_EXCD;
else if (memcmp(h, STAT_STATUS_DENY, 4) == 0)
--
1.7.9.1
Cyril Bonté
[PATCH 2/4] CLEANUP: fix typo in findserver() log message
April 04, 2012 01:00PM
There was a typo in the findserver() log message :
"found" was written "fould".
---
src/proxy.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/src/proxy.c b/src/proxy.c
index 123fd61..84d430a 100644
--- a/src/proxy.c
+++ b/src/proxy.c
@@ -366,7 +366,7 @@ struct server *findserver(const struct proxy *px, const char *name) {
continue;
}

- Alert("Refusing to use duplicated server '%s' fould in proxy: %s!\n",
+ Alert("Refusing to use duplicated server '%s' found in proxy: %s!\n",
name, px->id);

return NULL;
--
1.7.9.1
Proxy ids are unique whereas names can be used several times in the
configuration. In order to prevent the ambiguity, the HTML form now provides
the backend id instead of its name (the name can still be provided in the POST
data).
---
src/dumpstats.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/dumpstats.c b/src/dumpstats.c
index 16d07dd..3f88fc5 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -3160,10 +3160,10 @@ static int stats_dump_proxy(struct stream_interface *si, struct proxy *px, struc
"<option value=\"disable\">Disable</option>"
"<option value=\"enable\">Enable</option>"
"</select>"
- "<input type=\"hidden\" name=\"b\" value=\"%s\">"
+ "<input type=\"hidden\" name=\"b\" value=\"#%d\">"
"&nbsp;<input type=\"submit\" value=\"Apply\">"
"</form>",
- px->id);
+ px->uuid);
}

chunk_printf(&msg, "<p>\n");
--
1.7.9.1
memcmp()/strcmp() calls were needed in different parts of code to determine
the status code. Each new status code introduces new calls, which can become
inefficient and source of bugs.
This patch reorganizes the code to rely on a numeric status code internally
and to be hopefully more generic.
---
include/proto/dumpstats.h | 9 ---------
include/types/proto_http.h | 13 +++++++++++++
include/types/stream_interface.h | 2 +-
src/dumpstats.c | 36 ++++++++++++++++++++++--------------
src/proto_http.c | 36 +++++++++++++++++++++---------------
5 files changed, 57 insertions(+), 39 deletions(-)

diff --git a/include/proto/dumpstats.h b/include/proto/dumpstats.h
index 4c3837b..319ab48 100644
--- a/include/proto/dumpstats.h
+++ b/include/proto/dumpstats.h
@@ -55,15 +55,6 @@
#define STAT_CLI_O_TAB 8 /* dump tables */
#define STAT_CLI_O_CLR 9 /* clear tables */

-/* status codes (strictly 4 chars) used in the URL to display a message */
-#define STAT_STATUS_UNKN "UNKN" /* an unknown error occured, shouldn't happen */
-#define STAT_STATUS_DONE "DONE" /* the action is successful */
-#define STAT_STATUS_PART "PART" /* the action is partially successful */
-#define STAT_STATUS_NONE "NONE" /* nothing happened (no action chosen or servers state didn't change) */
-#define STAT_STATUS_ERRP "ERRP" /* an error occured due to invalid values in parameters */
-#define STAT_STATUS_EXCD "EXCD" /* an error occured because the buffer couldn't store all data */
-#define STAT_STATUS_DENY "DENY" /* action denied */
-
extern struct si_applet http_stats_applet;

void stats_io_handler(struct stream_interface *si);
diff --git a/include/types/proto_http.h b/include/types/proto_http.h
index a7b16aa..51f321e 100644
--- a/include/types/proto_http.h
+++ b/include/types/proto_http.h
@@ -258,6 +258,19 @@ enum {
ST_ADM_ACTION_ENABLE,
};

+/* status codes available for the stats admin page */
+enum {
+ STAT_STATUS_INIT = 0,
+ STAT_STATUS_DENY, /* action denied */
+ STAT_STATUS_DONE, /* the action is successful */
+ STAT_STATUS_ERRP, /* an error occured due to invalid values in parameters */
+ STAT_STATUS_EXCD, /* an error occured because the buffer couldn't store all data */
+ STAT_STATUS_NONE, /* nothing happened (no action chosen or servers state didn't change) */
+ STAT_STATUS_PART, /* the action is partially successful */
+ STAT_STATUS_UNKN, /* an unknown error occured, shouldn't happen */
+ STAT_STATUS_SIZE
+};
+
/* This is an HTTP message, as described in RFC2616. It can be either a request
* message or a response message.
*
diff --git a/include/types/stream_interface.h b/include/types/stream_interface.h
index 5acbd57..711394a 100644
--- a/include/types/stream_interface.h
+++ b/include/types/stream_interface.h
@@ -149,7 +149,7 @@ struct stream_interface {
int px_st; /* STAT_PX_ST* */
unsigned int flags; /* STAT_* */
int iid, type, sid; /* proxy id, type and service id if bounding of stats is enabled */
- const char *st_code; /* pointer to the status code returned by an action */
+ int st_code; /* the status code returned by an action */
} stats;
struct {
struct bref bref; /* back-reference from the session being dumped */
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 3f88fc5..dc3ac75 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -114,6 +114,8 @@ enum {
STAT_PX_ST_FIN,
};

+extern const char *stat_status_codes[];
+
/* This function is called from the session-level accept() in order to instanciate
* a new stats socket. It returns a positive value upon success, 0 if the connection
* needs to be closed and ignored, or a negative value upon critical failure.
@@ -1686,7 +1688,12 @@ static int stats_http_redir(struct stream_interface *si, struct uri_auth *uri)
"Content-Type: text/plain\r\n"
"Connection: close\r\n"
"Location: %s;st=%s",
- uri->uri_prefix, si->applet.ctx.stats.st_code);
+ uri->uri_prefix,
+ ((si->applet.ctx.stats.st_code > STAT_STATUS_INIT) &&
+ (si->applet.ctx.stats.st_code < STAT_STATUS_SIZE) &&
+ stat_status_codes[si->applet.ctx.stats.st_code]) ?
+ stat_status_codes[si->applet.ctx.stats.st_code] :
+ stat_status_codes[STAT_STATUS_UNKN]);
chunk_printf(&msg, "\r\n\r\n");

if (buffer_feed_chunk(si->ib, &msg) >= 0)
@@ -2023,29 +2030,30 @@ static int stats_dump_http(struct stream_interface *si, struct uri_auth *uri)
);

if (si->applet.ctx.stats.st_code) {
- if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_DONE) == 0) {
+ switch (si->applet.ctx.stats.st_code) {
+ case STAT_STATUS_DONE:
chunk_printf(&msg,
"<p><div class=active3>"
"<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
"Action processed successfully."
"</div>\n", uri->uri_prefix);
- }
- else if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_NONE) == 0) {
+ break;
+ case STAT_STATUS_NONE:
chunk_printf(&msg,
"<p><div class=active2>"
"<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
"Nothing has changed."
"</div>\n", uri->uri_prefix);
- }
- else if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_PART) == 0) {
+ break;
+ case STAT_STATUS_PART:
chunk_printf(&msg,
"<p><div class=active2>"
"<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
"Action partially processed.<br>"
"Some server names are probably unknown or ambiguous (duplicated names in the backend)."
"</div>\n", uri->uri_prefix);
- }
- else if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_ERRP) == 0) {
+ break;
+ case STAT_STATUS_ERRP:
chunk_printf(&msg,
"<p><div class=active0>"
"<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
@@ -2056,23 +2064,23 @@ static int stats_dump_http(struct stream_interface *si, struct uri_auth *uri)
"<li>Some server names are probably unknown or ambiguous (duplicated names in the backend).</li>"
"</ul>"
"</div>\n", uri->uri_prefix);
- }
- else if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_EXCD) == 0) {
+ break;
+ case STAT_STATUS_EXCD:
chunk_printf(&msg,
"<p><div class=active0>"
"<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
"<b>Action not processed : the buffer couldn't store all the data.<br>"
"You should retry with less servers at a time.</b>"
"</div>\n", uri->uri_prefix);
- }
- else if (strcmp(si->applet.ctx.stats.st_code, STAT_STATUS_DENY) == 0) {
+ break;
+ case STAT_STATUS_DENY:
chunk_printf(&msg,
"<p><div class=active0>"
"<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
"<b>Action denied.</b>"
"</div>\n", uri->uri_prefix);
- }
- else {
+ break;
+ default:
chunk_printf(&msg,
"<p><div class=active6>"
"<a class=lfsb href=\"%s\" title=\"Remove this message\">[X]</a> "
diff --git a/src/proto_http.c b/src/proto_http.c
index bf91328..3f6ec04 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -188,6 +188,18 @@ static const char *http_err_msgs[HTTP_ERR_SIZE] = {

};

+/* status codes available for the stats admin page (strictly 4 chars length) */
+const char *stat_status_codes[STAT_STATUS_SIZE] = {
+ [STAT_STATUS_DENY] = "DENY",
+ [STAT_STATUS_DONE] = "DONE",
+ [STAT_STATUS_ERRP] = "ERRP",
+ [STAT_STATUS_EXCD] = "EXCD",
+ [STAT_STATUS_NONE] = "NONE",
+ [STAT_STATUS_PART] = "PART",
+ [STAT_STATUS_UNKN] = "UNKN",
+};
+
+
/* We must put the messages here since GCC cannot initialize consts depending
* on strlen().
*/
@@ -7132,6 +7144,7 @@ int stats_check_uri(struct stream_interface *si, struct http_txn *txn, struct pr
return 0;

memset(&si->applet.ctx.stats, 0, sizeof(si->applet.ctx.stats));
+ si->applet.ctx.stats.st_code = STAT_STATUS_INIT;

/* check URI size */
if (uri_auth->uri_len > txn->req.sl.rq.u_l)
@@ -7175,22 +7188,15 @@ int stats_check_uri(struct stream_interface *si, struct http_txn *txn, struct pr
h = txn->req.sol + txn->req.sl.rq.u + uri_auth->uri_len;
while (h <= txn->req.sol + txn->req.sl.rq.u + txn->req.sl.rq.u_l - 8) {
if (memcmp(h, ";st=", 4) == 0) {
+ int i;
h += 4;
-
- if (memcmp(h, STAT_STATUS_DONE, 4) == 0)
- si->applet.ctx.stats.st_code = STAT_STATUS_DONE;
- else if (memcmp(h, STAT_STATUS_NONE, 4) == 0)
- si->applet.ctx.stats.st_code = STAT_STATUS_NONE;
- else if (memcmp(h, STAT_STATUS_PART, 4) == 0)
- si->applet.ctx.stats.st_code = STAT_STATUS_PART;
- else if (memcmp(h, STAT_STATUS_ERRP, 4) == 0)
- si->applet.ctx.stats.st_code = STAT_STATUS_ERRP;
- else if (memcmp(h, STAT_STATUS_EXCD, 4) == 0)
- si->applet.ctx.stats.st_code = STAT_STATUS_EXCD;
- else if (memcmp(h, STAT_STATUS_DENY, 4) == 0)
- si->applet.ctx.stats.st_code = STAT_STATUS_DENY;
- else
- si->applet.ctx.stats.st_code = STAT_STATUS_UNKN;
+ for (i = STAT_STATUS_INIT + 1; i < STAT_STATUS_SIZE; i++) {
+ if (strncmp(stat_status_codes, h, 4) == 0) {
+ si->applet.ctx.stats.st_code = i;
+ break;
+ }
+ }
+ si->applet.ctx.stats.st_code = STAT_STATUS_UNKN;
break;
}
h++;
--
1.7.9.1
Hi Cyril,

Patches look good, all applied, thank you !

Willy
On Wed, Apr 04, 2012 at 12:57:20PM +0200, Cyril Bonté wrote:
> Proxy ids are unique whereas names can be used several times in the
> configuration. In order to prevent the ambiguity, the HTML form now provides
> the backend id instead of its name (the name can still be provided in the POST
> data).

BTW about this, a minor comment : the statement above is not exact since a
same name can only appear once for a same type in the config. You can't have
to similarly named backends, nor a backend and a "listen" sharing the same
name. Only a frontend and a backend may use the same name (used to ease
conversion from listen to front+back).

Cheers,
Willy
Hi Willy,


Le 05/04/2012 10:01, Willy Tarreau a écrit :
> On Wed, Apr 04, 2012 at 12:57:20PM +0200, Cyril Bonté wrote:
>> Proxy ids are unique whereas names can be used several times in the
>> configuration. In order to prevent the ambiguity, the HTML form now provides
>> the backend id instead of its name (the name can still be provided in the POST
>> data).
>
> BTW about this, a minor comment : the statement above is not exact since a
> same name can only appear once for a same type in the config. You can't have
> to similarly named backends, nor a backend and a "listen" sharing the same
> name. Only a frontend and a backend may use the same name (used to ease
> conversion from listen to front+back).

OK I guess where I missed something during my tests.
My test file declared several backends with the same name and it
worked...but i didn't add a "use_backend" or "default_backend" keyword
in any frontend to use them, which is valid for haproxy but has no sense
for such administration tasks ;-)

--
Cyril Bonté
On Thu, Apr 05, 2012 at 11:43:55AM +0200, Cyril Bonté wrote:
> Hi Willy,
>
>
> Le 05/04/2012 10:01, Willy Tarreau a écrit :
> >On Wed, Apr 04, 2012 at 12:57:20PM +0200, Cyril Bonté wrote:
> >>Proxy ids are unique whereas names can be used several times in the
> >>configuration. In order to prevent the ambiguity, the HTML form now
> >>provides
> >>the backend id instead of its name (the name can still be provided in the
> >>POST
> >>data).
> >
> >BTW about this, a minor comment : the statement above is not exact since a
> >same name can only appear once for a same type in the config. You can't
> >have
> >to similarly named backends, nor a backend and a "listen" sharing the same
> >name. Only a frontend and a backend may use the same name (used to ease
> >conversion from listen to front+back).
>
> OK I guess where I missed something during my tests.
> My test file declared several backends with the same name and it
> worked...but i didn't add a "use_backend" or "default_backend" keyword
> in any frontend to use them, which is valid for haproxy but has no sense
> for such administration tasks ;-)

You're right, in fact it only emits a warning, not an error :-)

Cheers,
Willy
Sorry, only registered users may post in this forum.

Click here to login