]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: checks: Support custom functions to eval a tcp-check expect rules
authorChristopher Faulet <cfaulet@haproxy.com>
Fri, 3 Apr 2020 13:24:06 +0000 (15:24 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Mon, 27 Apr 2020 07:39:38 +0000 (09:39 +0200)
It is now possible to set a custom function to evaluate a tcp-check expect
rule. It is an internal and not documentd option because the right pointer of
function must be set and it is not possible to express it in the
configuration. It will be used to convert some protocol healthchecks to
tcp-checks.

Custom functions must have the following signature:

  enum tcpcheck_eval_ret (*custom)(struct check *, struct tcpcheck_rule *, int);

include/types/checks.h
src/checks.c

index 220563345cb639b1e8e983d39a43ff1dfa006d28..30f7d75fb044721c666daea6f30a2cf854cc5332 100644 (file)
@@ -253,11 +253,12 @@ enum tcpcheck_eval_ret {
 };
 
 enum tcpcheck_expect_type {
-       TCPCHK_EXPECT_UNDEF = 0, /* Match is not used. */
-       TCPCHK_EXPECT_STRING, /* Matches a string. */
-       TCPCHK_EXPECT_REGEX, /* Matches a regular pattern. */
+       TCPCHK_EXPECT_UNDEF = 0,    /* Match is not used. */
+       TCPCHK_EXPECT_STRING,       /* Matches a string. */
+       TCPCHK_EXPECT_REGEX,        /* Matches a regular pattern. */
        TCPCHK_EXPECT_REGEX_BINARY, /* Matches a regular pattern on a hex-encoded text. */
-       TCPCHK_EXPECT_BINARY, /* Matches a binary sequence. */
+       TCPCHK_EXPECT_BINARY,       /* Matches a binary sequence. */
+       TCPCHK_EXPECT_CUSTOM,       /* Execute a custom function. */
 };
 
 struct tcpcheck_expect {
@@ -265,6 +266,9 @@ struct tcpcheck_expect {
        union {
                char *string;           /* Matching a literal string / binary anywhere in the response. */
                struct my_regex *regex; /* Matching a regex pattern. */
+
+               /* custom function to eval epxect rule */
+               enum tcpcheck_eval_ret (*custom)(struct check *, struct tcpcheck_rule *, int);
        };
        struct tcpcheck_rule *head;     /* first expect of a chain. */
        int length;                     /* Size in bytes of the pattern referenced by string / binary. */
index 6a28b543c55cabc9f9b48100b22baae2913b6e4f..c6bced88a65500997bd80c115f470e77866a9870 100644 (file)
@@ -664,6 +664,9 @@ static void chk_report_conn_err(struct check *check, int errno_bck, int expired)
                                case TCPCHK_EXPECT_REGEX_BINARY:
                                        chunk_appendf(chk, " (expect binary regex)");
                                        break;
+                               case TCPCHK_EXPECT_CUSTOM:
+                                       chunk_appendf(chk, " (expect custom function)");
+                                       break;
                                case TCPCHK_EXPECT_UNDEF:
                                        chunk_appendf(chk, " (undefined expect!)");
                                        break;
@@ -2803,6 +2806,9 @@ static void tcpcheck_onerror_message(struct buffer *msg, struct check *check, st
                        }
                }
                break;
+       case TCPCHK_EXPECT_CUSTOM:
+               chunk_appendf(msg, " (custom function) at step %d", tcpcheck_get_step_id(check, rule));
+               break;
        case TCPCHK_EXPECT_UNDEF:
                /* Should never happen. */
                return;
@@ -3193,6 +3199,10 @@ static enum tcpcheck_eval_ret tcpcheck_eval_expect(struct check *check, struct t
                else
                        match = regex_exec2(expect->regex, b_head(&trash), MIN(b_data(&trash), b_size(&trash)-1));
                break;
+       case TCPCHK_EXPECT_CUSTOM:
+               if (expect->custom)
+                       ret = expect->custom(check, rule, last_read);
+               goto out;
        case TCPCHK_EXPECT_UNDEF:
                /* Should never happen. */
                ret = TCPCHK_EVAL_STOP;
@@ -3540,6 +3550,7 @@ static void free_tcpcheck(struct tcpcheck_rule *rule, int in_pool)
                case TCPCHK_EXPECT_REGEX_BINARY:
                        regex_free(rule->expect.regex);
                        break;
+               case TCPCHK_EXPECT_CUSTOM:
                case TCPCHK_EXPECT_UNDEF:
                        break;
                }
@@ -4676,8 +4687,8 @@ static struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, str
        int inverse = 0, with_capture = 0;
 
        str = on_success_msg = on_error_msg = comment = pattern = NULL;
-       if (!*(args[cur_arg+1]) || !*(args[cur_arg+2])) {
-               memprintf(errmsg, "expects a pattern (type+string) as arguments");
+       if (!*(args[cur_arg+1])) {
+               memprintf(errmsg, "expects at least a matching pattern as arguments");
                goto error;
        }
 
@@ -4730,6 +4741,17 @@ static struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, str
                        cur_arg++;
                        pattern = args[cur_arg];
                }
+               else if (strcmp(args[cur_arg], "custom") == 0) {
+                       if (in_pattern) {
+                               memprintf(errmsg, "[!] not supported with '%s'", args[cur_arg]);
+                               goto error;
+                       }
+                       if (type != TCPCHK_EXPECT_UNDEF) {
+                               memprintf(errmsg, "only on pattern expected");
+                               goto error;
+                       }
+                       type = TCPCHK_EXPECT_CUSTOM;
+               }
                else if (strcmp(args[cur_arg], "comment") == 0) {
                        if (in_pattern) {
                                memprintf(errmsg, "[!] not supported with '%s'", args[cur_arg]);
@@ -4941,6 +4963,9 @@ static struct tcpcheck_rule *parse_tcpcheck_expect(char **args, int cur_arg, str
                if (!chk->expect.regex)
                        goto error;
                break;
+       case TCPCHK_EXPECT_CUSTOM:
+               chk->expect.custom = NULL; /* Must be defined by the caller ! */
+               break;
        case TCPCHK_EXPECT_UNDEF:
                free(chk);
                memprintf(errmsg, "pattern not found");