[MEDIUM] add the "fail" condition to monitor requests
Under certain circumstances, it is very useful to be able to fail some monitor requests. One specific case is when the number of servers in the backend falls below a certain level. The new "monitor fail" construct followed by either "if"/"unless" <condition> makes it possible to specify ACL-based conditions which will make the monitor return 503 instead of 200. Any number of conditions can be passed. Another use may be to limit the requests to local networks only.
This commit is contained in:
@ -168,6 +168,7 @@ struct proxy {
|
||||
struct uri_auth *uri_auth; /* if non-NULL, the (list of) per-URI authentications */
|
||||
char *monitor_uri; /* a special URI to which we respond with HTTP/200 OK */
|
||||
int monitor_uri_len; /* length of the string above. 0 if unused */
|
||||
struct list mon_fail_cond; /* list of conditions to fail monitoring requests (chained) */
|
||||
struct timeval clitimeout; /* client I/O timeout (in milliseconds) */
|
||||
struct timeval srvtimeout; /* server I/O timeout (in milliseconds) */
|
||||
struct timeval contimeout; /* connect timeout (in milliseconds) */
|
||||
|
@ -564,6 +564,7 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
|
||||
LIST_INIT(&curproxy->pendconns);
|
||||
LIST_INIT(&curproxy->acl);
|
||||
LIST_INIT(&curproxy->block_cond);
|
||||
LIST_INIT(&curproxy->mon_fail_cond);
|
||||
LIST_INIT(&curproxy->switching_rules);
|
||||
|
||||
/* Timeouts are defined as -1, so we cannot use the zeroed area
|
||||
@ -1305,6 +1306,38 @@ int cfg_parse_listen(const char *file, int linenum, char **args)
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else if (!strcmp(args[0], "monitor")) {
|
||||
if (warnifnotcap(curproxy, PR_CAP_FE, file, linenum, args[0], NULL))
|
||||
return 0;
|
||||
|
||||
if (strcmp(args[1], "fail") == 0) {
|
||||
/* add a condition to fail monitor requests */
|
||||
int pol = ACL_COND_NONE;
|
||||
struct acl_cond *cond;
|
||||
|
||||
if (!strcmp(args[2], "if"))
|
||||
pol = ACL_COND_IF;
|
||||
else if (!strcmp(args[2], "unless"))
|
||||
pol = ACL_COND_UNLESS;
|
||||
|
||||
if (pol == ACL_COND_NONE) {
|
||||
Alert("parsing [%s:%d] : '%s %s' requires either 'if' or 'unless' followed by a condition.\n",
|
||||
file, linenum, args[0], args[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((cond = parse_acl_cond((const char **)args + 3, &curproxy->acl, pol)) == NULL) {
|
||||
Alert("parsing [%s:%d] : error detected while parsing a '%s %s' condition.\n",
|
||||
file, linenum, args[0], args[1]);
|
||||
return -1;
|
||||
}
|
||||
LIST_ADDQ(&curproxy->mon_fail_cond, &cond->list);
|
||||
}
|
||||
else {
|
||||
Alert("parsing [%s:%d] : '%s' only supports 'fail'.\n", file, linenum, args[0]);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
#ifdef TPROXY
|
||||
else if (!strcmp(args[0], "transparent")) {
|
||||
/* enable transparent proxy connections */
|
||||
|
@ -658,6 +658,12 @@ void deinit(void)
|
||||
free(cond);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(cond, condb, &p->mon_fail_cond, list) {
|
||||
LIST_DEL(&cond->list);
|
||||
prune_acl_cond(cond);
|
||||
free(cond);
|
||||
}
|
||||
|
||||
for (exp = p->req_exp; exp != NULL; ) {
|
||||
if (exp->preg)
|
||||
regfree((regex_t *)exp->preg);
|
||||
|
@ -1637,7 +1637,26 @@ int process_cli(struct session *t)
|
||||
/*
|
||||
* We have found the monitor URI
|
||||
*/
|
||||
struct acl_cond *cond;
|
||||
cur_proxy = t->fe;
|
||||
|
||||
t->flags |= SN_MONITOR;
|
||||
|
||||
/* Check if we want to fail this monitor request or not */
|
||||
list_for_each_entry(cond, &cur_proxy->mon_fail_cond, list) {
|
||||
int ret = acl_exec_cond(cond, cur_proxy, t, txn, ACL_DIR_REQ);
|
||||
if (cond->pol == ACL_COND_UNLESS)
|
||||
ret = !ret;
|
||||
|
||||
if (ret) {
|
||||
/* we fail this request, let's return 503 service unavail */
|
||||
txn->status = 503;
|
||||
client_retnclose(t, error_message(t, HTTP_ERR_503));
|
||||
goto return_prx_cond;
|
||||
}
|
||||
}
|
||||
|
||||
/* nothing to fail, let's reply normaly */
|
||||
txn->status = 200;
|
||||
client_retnclose(t, &http_200_chunk);
|
||||
goto return_prx_cond;
|
||||
|
Reference in New Issue
Block a user