MINOR: checks: Add support to set-var and unset-var rules in tcp-checks

Evaluate the registered action_ptr associated with each CHK_ACTION_KW rules from
a ruleset. Currently only the 'set-var' and 'unset-var' are parsed by the
tcp-check parser. Thus it is now possible to set or unset variables. It is
possible to use such rules before the first connect of the ruleset.
This commit is contained in:
Gaetan Rivet 2020-02-24 17:34:11 +01:00 committed by Christopher Faulet
parent 707b52f17e
commit 0c39eccdd4
3 changed files with 83 additions and 4 deletions

View File

@ -2759,6 +2759,8 @@ tcp-check connect - - X X
tcp-check expect - - X X
tcp-check send - - X X
tcp-check send-binary - - X X
tcp-check set-var - - X X
tcp-check unset-var - - X X
tcp-request connection - X X -
tcp-request content - X X X
tcp-request inspect-delay - X X X
@ -7986,6 +7988,10 @@ option tcp-check
in debug mode. It is useful to make user-friendly error reporting.
The "comment" is of course optional.
During the execution of a health check, a variable scope is made available
to store data samples, using the "tcp-check set-var" operation. Freeing
those variable is possible using "tcp-check unset-var".
Examples :
# perform a POP check (analyze only server's banner)
@ -9805,6 +9811,9 @@ tcp-check connect [params*]
the ruleset with a 'connect' rule. Purpose is to ensure admin know what they
do.
When a connect must start the ruleset, if may still be preceded by set-var,
unset-var or comment rules.
Parameters :
They are optional and can be used to describe how HAProxy should open and
use the TCP connection.
@ -9991,6 +10000,50 @@ tcp-check send-binary <hexstring>
"tcp-check send", tune.chksize
tcp-check set-var(<var-name>) <expr>
This operation sets the content of a variable. The variable is declared inline.
May be used in sections: defaults | frontend | listen | backend
no | no | yes | yes
Arguments:
<var-name> The name of the variable starts with an indication about its
scope. The scopes allowed for tcp-check are:
"proc" : the variable is shared with the whole process.
"sess" : the variable is shared with the tcp-check session.
"check": the variable is declared for the lifetime of the tcp-check.
This prefix is followed by a name. The separator is a '.'.
The name may only contain characters 'a-z', 'A-Z', '0-9', '.',
and '-'.
<expr> Is a sample-fetch expression potentially followed by converters.
Example:
tcp-check set-var(check.port) int(1234)
tcp-check unset-var(<var-name>)
Free a reference to a variable within its scope.
May be used in sections: defaults | frontend | listen | backend
no | no | yes | yes
Arguments:
<var-name> The name of the variable starts with an indication about its
scope. The scopes allowed for tcp-check are:
"proc" : the variable is shared with the whole process.
"sess" : the variable is shared with the tcp-check session.
"check": the variable is declared for the lifetime of the tcp-check.
This prefix is followed by a name. The separator is a '.'.
The name may only contain characters 'a-z', 'A-Z', '0-9', '.',
and '-'.
Example:
tcp-check unset-var(check.port)
tcp-request connection <action> [{if | unless} <condition>]
Perform an action on an incoming connection depending on a layer 4 condition
May be used in sections : defaults | frontend | listen | backend

View File

@ -3042,8 +3042,7 @@ static enum tcpcheck_eval_ret tcpcheck_eval_send(struct check *check, struct tcp
}
/* Evaluate a TCPCHK_ACT_EXPECT rule. It returns 1 to evaluate the next rule, 0
* to wait and -1 to stop the check. <rule> is updated to point on the last
* evaluated TCPCHK_ACT_EXPECT rule.
* to wait and -1 to stop the check.
*/
static enum tcpcheck_eval_ret tcpcheck_eval_expect(struct check *check, struct tcpcheck_rule *rule, int last_read)
{
@ -3167,6 +3166,27 @@ static enum tcpcheck_eval_ret tcpcheck_eval_expect(struct check *check, struct t
return ret;
}
/* Evaluate a TCPCHK_ACT_ACTION_KW rule. It returns 1 to evaluate the next rule, 0
* to wait and -1 to stop the check.
*/
static enum tcpcheck_eval_ret tcpcheck_eval_action_kw(struct check *check, struct tcpcheck_rule *rule)
{
enum tcpcheck_eval_ret ret = TCPCHK_EVAL_CONTINUE;
struct act_rule *act_rule;
enum act_return act_ret;
act_rule =rule->action_kw.rule;
act_ret = act_rule->action_ptr(act_rule, check->proxy, check->sess, NULL, 0);
if (act_ret != ACT_RET_CONT) {
chunk_printf(&trash, "TCPCHK ACTION unexpected result at step %d\n",
tcpcheck_get_step_id(check, rule));
set_server_check_status(check, HCHK_STATUS_L7RSP, trash.area);
ret = TCPCHK_EVAL_STOP;
}
return ret;
}
/* proceed with next steps for the TCP checks <check>. Note that this is called
* both from the connection's wake() callback and from the check scheduling task.
* It returns 0 on normal cases, or <0 if a close() has happened on an existing
@ -3308,12 +3328,17 @@ static int tcpcheck_main(struct check *check)
}
must_read = 0;
}
eval_ret = tcpcheck_eval_expect(check, rule, last_read);
if (eval_ret == TCPCHK_EVAL_WAIT) {
check->current_step = rule->expect.head;
conn->mux->subscribe(cs, SUB_RETRY_RECV, &check->wait_list);
}
break;
case TCPCHK_ACT_ACTION_KW:
/* Don't update the current step */
eval_ret = tcpcheck_eval_action_kw(check, rule);
break;
default:
/* Otherwise, just go to the next one and don't update
* the current step
@ -3588,7 +3613,7 @@ static int add_tcpcheck_expect_str(struct list *list, const char *str)
tcpcheck->expect.head = prev_check;
continue;
}
if (prev_check->action != TCPCHK_ACT_COMMENT)
if (prev_check->action != TCPCHK_ACT_COMMENT && prev_check->action != TCPCHK_ACT_ACTION_KW)
break;
}
LIST_ADDQ(list, &tcpcheck->list);
@ -4368,7 +4393,7 @@ static struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, str
chk->expect.head = prev_check;
continue;
}
if (prev_check->action != TCPCHK_ACT_COMMENT)
if (prev_check->action != TCPCHK_ACT_COMMENT && prev_check->action != TCPCHK_ACT_ACTION_KW)
break;
}
return chk;

View File

@ -671,6 +671,7 @@ static enum act_return action_store(struct act_rule *rule, struct proxy *px,
case ACT_F_TCP_RES_CNT: dir = SMP_OPT_DIR_RES; break;
case ACT_F_HTTP_REQ: dir = SMP_OPT_DIR_REQ; break;
case ACT_F_HTTP_RES: dir = SMP_OPT_DIR_RES; break;
case ACT_F_TCP_CHK: dir = SMP_OPT_DIR_REQ; break;
default:
send_log(px, LOG_ERR, "Vars: internal error while execute action store.");
if (!(global.mode & MODE_QUIET) || (global.mode & MODE_VERBOSE))