]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: checks: Add support to set-var and unset-var rules in tcp-checks
authorGaetan Rivet <grive@u256.net>
Mon, 24 Feb 2020 16:34:11 +0000 (17:34 +0100)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 27 Apr 2020 07:39:37 +0000 (09:39 +0200)
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.

doc/configuration.txt
src/checks.c
src/vars.c

index 09f4b669eb1817a668831b5c12d4995f046e90cc..40585b815fbe85fc4c198eca95e38ff2b87966cb 100644 (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
index 5e147b81f47596f98d6b63dd2993627aa191abe8..b9fb4d53a7bbb4378e2557d48e96e00088271e7e 100644 (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;
index 7f3d2d0cf3f172d66659afda3aa3e901b218fd7a..0fa3397c761eb8dad6423b7496850564434bf4db 100644 (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))