From 7d085039c6c633450bd88b2f98bb84e117e8ca29 Mon Sep 17 00:00:00 2001 From: Robert Maticevic Date: Tue, 26 Nov 2024 13:42:37 +0100 Subject: [PATCH] MINOR: add support for set-retries option for tcp/http requests --- config-parser/parsers/actions/set-retries.go | 81 ++++++++ config-parser/parsers/http/http-request.go | 2 + config-parser/parsers/tcp/types/content.go | 2 + .../tests/configs/haproxy_generated.cfg.go | 20 ++ .../tests/http-request_generated_test.go | 2 + .../tests/integration/backend_data_test.go | 16 ++ .../tests/integration/backend_test.go | 4 + .../tests/integration/defaults_data_test.go | 16 ++ .../tests/integration/defaults_test.go | 4 + .../tests/integration/frontend_data_test.go | 16 ++ .../tests/integration/frontend_test.go | 4 + .../tests/tcp-request_generated_test.go | 186 +++++++++--------- config-parser/types/types-other.go | 4 + configuration/http_request_rule.go | 13 ++ configuration/tcp_request_rule.go | 13 ++ models/http_request_rule.go | 9 +- models/tcp_request_rule.go | 9 +- specification/build/haproxy_spec.yaml | 4 + .../models/configuration/http/request.yaml | 2 + .../models/configuration/tcp/request.yaml | 2 + test/configuration_test.go | 4 + test/expected/structured.json | 22 +++ 22 files changed, 337 insertions(+), 98 deletions(-) create mode 100644 config-parser/parsers/actions/set-retries.go diff --git a/config-parser/parsers/actions/set-retries.go b/config-parser/parsers/actions/set-retries.go new file mode 100644 index 00000000..a80c3be8 --- /dev/null +++ b/config-parser/parsers/actions/set-retries.go @@ -0,0 +1,81 @@ +/* +Copyright 2019 HAProxy Technologies + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +//nolint:dupl +package actions + +import ( + stderrors "errors" + "strings" + + "github.com/haproxytech/client-native/v6/config-parser/common" + "github.com/haproxytech/client-native/v6/config-parser/errors" + "github.com/haproxytech/client-native/v6/config-parser/types" +) + +type SetRetries struct { + Expr common.Expression + Cond string + CondTest string + Comment string +} + +func (f *SetRetries) Parse(parts []string, parserType types.ParserType, comment string) error { + if comment != "" { + f.Comment = comment + } + if len(parts) < 3 { + return stderrors.New("not enough params") + } + var command []string + switch parserType { + case types.HTTP: + command = parts[2:] + case types.TCP: + command = parts[3:] + } + command, condition := common.SplitRequest(command) + if len(command) == 0 { + return errors.ErrInvalidData + } + expr := common.Expression{} + if expr.Parse(command) != nil { + return stderrors.New("not enough params") + } + f.Expr = expr + if len(condition) > 1 { + f.Cond = condition[0] + f.CondTest = strings.Join(condition[1:], " ") + } + return nil +} + +func (f *SetRetries) String() string { + var result strings.Builder + result.WriteString("set-retries ") + result.WriteString(f.Expr.String()) + if f.Cond != "" { + result.WriteString(" ") + result.WriteString(f.Cond) + result.WriteString(" ") + result.WriteString(f.CondTest) + } + return result.String() +} + +func (f *SetRetries) GetComment() string { + return f.Comment +} diff --git a/config-parser/parsers/http/http-request.go b/config-parser/parsers/http/http-request.go index 7f3946ea..0686e60b 100644 --- a/config-parser/parsers/http/http-request.go +++ b/config-parser/parsers/http/http-request.go @@ -145,6 +145,8 @@ func (h *Requests) Parse(line string, parts []string, comment string) (string, e err = h.ParseHTTPRequest(&actions.SetFcMark{}, parts, comment) case "set-fc-tos": err = h.ParseHTTPRequest(&actions.SetFcTos{}, parts, comment) + case "set-retries": + err = h.ParseHTTPRequest(&actions.SetRetries{}, parts, comment) default: switch { case strings.HasPrefix(parts[1], "track-sc"): diff --git a/config-parser/parsers/tcp/types/content.go b/config-parser/parsers/tcp/types/content.go index 880735a0..5330dc9a 100644 --- a/config-parser/parsers/tcp/types/content.go +++ b/config-parser/parsers/tcp/types/content.go @@ -94,6 +94,8 @@ func (f *Content) Parse(parts []string, comment string) error { err = f.ParseAction(&actions.SetFcMark{}, parts) case "set-fc-tos": err = f.ParseAction(&actions.SetFcTos{}, parts) + case "set-retries": + err = f.ParseAction(&actions.SetRetries{}, parts) default: switch { case strings.HasPrefix(parts[2], "track-sc"): diff --git a/config-parser/tests/configs/haproxy_generated.cfg.go b/config-parser/tests/configs/haproxy_generated.cfg.go index 9cbb0e6e..94c8aad3 100644 --- a/config-parser/tests/configs/haproxy_generated.cfg.go +++ b/config-parser/tests/configs/haproxy_generated.cfg.go @@ -603,6 +603,8 @@ backend test http-request set-bc-tos 10 http-request set-fc-mark 0 http-request set-fc-tos 0xff if TRUE + http-request set-retries 3 + http-request set-retries var(txn.retries) if TRUE http-request add-header Authorization Basic\ eC1oYXByb3h5LXJlY3J1aXRzOlBlb3BsZSB3aG8gZGVjb2RlIG1lc3NhZ2VzIG9mdGVuIGxvdmUgd29ya2luZyBhdCBIQVByb3h5LiBEbyBub3QgYmUgc2h5LCBjb250YWN0IHVz http-request add-header Authorisation "Basic eC1oYXByb3h5LXJlY3J1aXRzOlBlb3BsZSB3aG8gZGVjb2RlIG1lc3NhZ2VzIG9mdGVuIGxvdmUgd29ya2luZyBhdCBIQVByb3h5LiBEbyBub3QgYmUgc2h5LCBjb250YWN0IHVz" http-request return status 200 content-type "text/plain" string "My content" if { var(txn.myip) -m found } @@ -895,6 +897,8 @@ backend test tcp-request content lua.foo tcp-request content lua.foo param if !HTTP tcp-request content lua.foo param param1 + tcp-request content set-retries 3 + tcp-request content set-retries var(txn.retries) if TRUE tcp-request connection accept tcp-request connection accept if !HTTP tcp-request connection reject @@ -1461,6 +1465,8 @@ defaults test http-request set-bc-tos 10 http-request set-fc-mark 0 http-request set-fc-tos 0xff if TRUE + http-request set-retries 3 + http-request set-retries var(txn.retries) if TRUE http-request add-header Authorization Basic\ eC1oYXByb3h5LXJlY3J1aXRzOlBlb3BsZSB3aG8gZGVjb2RlIG1lc3NhZ2VzIG9mdGVuIGxvdmUgd29ya2luZyBhdCBIQVByb3h5LiBEbyBub3QgYmUgc2h5LCBjb250YWN0IHVz http-request add-header Authorisation "Basic eC1oYXByb3h5LXJlY3J1aXRzOlBlb3BsZSB3aG8gZGVjb2RlIG1lc3NhZ2VzIG9mdGVuIGxvdmUgd29ya2luZyBhdCBIQVByb3h5LiBEbyBub3QgYmUgc2h5LCBjb250YWN0IHVz" http-request return status 200 content-type "text/plain" string "My content" if { var(txn.myip) -m found } @@ -1753,6 +1759,8 @@ defaults test tcp-request content lua.foo tcp-request content lua.foo param if !HTTP tcp-request content lua.foo param param1 + tcp-request content set-retries 3 + tcp-request content set-retries var(txn.retries) if TRUE tcp-request connection accept tcp-request connection accept if !HTTP tcp-request connection reject @@ -2266,6 +2274,8 @@ frontend test http-request set-bc-tos 10 http-request set-fc-mark 0 http-request set-fc-tos 0xff if TRUE + http-request set-retries 3 + http-request set-retries var(txn.retries) if TRUE http-request capture req.cook_cnt(FirstVisit),bool len 10 http-request capture str("DNS resolution failure") len 32 unless dns_successful http-request add-header Authorization Basic\ eC1oYXByb3h5LXJlY3J1aXRzOlBlb3BsZSB3aG8gZGVjb2RlIG1lc3NhZ2VzIG9mdGVuIGxvdmUgd29ya2luZyBhdCBIQVByb3h5LiBEbyBub3QgYmUgc2h5LCBjb250YWN0IHVz @@ -2499,6 +2509,8 @@ frontend test tcp-request content lua.foo tcp-request content lua.foo param if !HTTP tcp-request content lua.foo param param1 + tcp-request content set-retries 3 + tcp-request content set-retries var(txn.retries) if TRUE tcp-request connection accept tcp-request connection accept if !HTTP tcp-request connection reject @@ -4373,6 +4385,10 @@ var configTests = []configTest{{` command spoa-mirror --runtime 0 --mirror-url {` http-request set-fc-mark 0 `, 3}, {` http-request set-fc-tos 0xff if TRUE +`, 3}, + {` http-request set-retries 3 +`, 3}, + {` http-request set-retries var(txn.retries) if TRUE `, 3}, {` http-request capture req.cook_cnt(FirstVisit),bool len 10 `, 1}, @@ -4879,6 +4895,10 @@ var configTests = []configTest{{` command spoa-mirror --runtime 0 --mirror-url {` tcp-request content lua.foo param if !HTTP `, 3}, {` tcp-request content lua.foo param param1 +`, 3}, + {` tcp-request content set-retries 3 +`, 3}, + {` tcp-request content set-retries var(txn.retries) if TRUE `, 3}, {` tcp-request connection accept `, 3}, diff --git a/config-parser/tests/http-request_generated_test.go b/config-parser/tests/http-request_generated_test.go index 3764f57f..cf157837 100644 --- a/config-parser/tests/http-request_generated_test.go +++ b/config-parser/tests/http-request_generated_test.go @@ -204,6 +204,8 @@ func TestRequestshttp(t *testing.T) { "http-request set-bc-tos 10": true, "http-request set-fc-mark 0": true, "http-request set-fc-tos 0xff if TRUE": true, + "http-request set-retries 3": true, + "http-request set-retries var(txn.retries) if TRUE": true, `http-request add-header Authorization Basic\ eC1oYXByb3h5LXJlY3J1aXRzOlBlb3BsZSB3aG8gZGVjb2RlIG1lc3NhZ2VzIG9mdGVuIGxvdmUgd29ya2luZyBhdCBIQVByb3h5LiBEbyBub3QgYmUgc2h5LCBjb250YWN0IHVz`: true, `http-request add-header Authorisation "Basic eC1oYXByb3h5LXJlY3J1aXRzOlBlb3BsZSB3aG8gZGVjb2RlIG1lc3NhZ2VzIG9mdGVuIGxvdmUgd29ya2luZyBhdCBIQVByb3h5LiBEbyBub3QgYmUgc2h5LCBjb250YWN0IHVz"`: true, `http-request return status 200 content-type "text/plain" string "My content" if { var(txn.myip) -m found }`: true, diff --git a/config-parser/tests/integration/backend_data_test.go b/config-parser/tests/integration/backend_data_test.go index f7520fb9..bbac6b42 100644 --- a/config-parser/tests/integration/backend_data_test.go +++ b/config-parser/tests/integration/backend_data_test.go @@ -2601,6 +2601,14 @@ const backend_httprequestsetfctos0xffifTRUE = ` backend test http-request set-fc-tos 0xff if TRUE ` +const backend_httprequestsetretries3 = ` +backend test + http-request set-retries 3 +` +const backend_httprequestsetretriesvartxnretri = ` +backend test + http-request set-retries var(txn.retries) if TRUE +` const backend_httprequestaddheaderAuthorizatio = ` backend test http-request add-header Authorization Basic\ eC1oYXByb3h5LXJlY3J1aXRzOlBlb3BsZSB3aG8gZGVjb2RlIG1lc3NhZ2VzIG9mdGVuIGxvdmUgd29ya2luZyBhdCBIQVByb3h5LiBEbyBub3QgYmUgc2h5LCBjb250YWN0IHVz @@ -3769,6 +3777,14 @@ const backend_tcprequestcontentluafooparampara = ` backend test tcp-request content lua.foo param param1 ` +const backend_tcprequestcontentsetretries3 = ` +backend test + tcp-request content set-retries 3 +` +const backend_tcprequestcontentsetretriesvartx = ` +backend test + tcp-request content set-retries var(txn.retries) if TRUE +` const backend_tcprequestconnectionaccept = ` backend test tcp-request connection accept diff --git a/config-parser/tests/integration/backend_test.go b/config-parser/tests/integration/backend_test.go index 0e16b009..ad9c4c93 100644 --- a/config-parser/tests/integration/backend_test.go +++ b/config-parser/tests/integration/backend_test.go @@ -493,6 +493,8 @@ func TestWholeConfigsSectionsBackend(t *testing.T) { {"backend_httprequestsetpriorityoffsetreqh", backend_httprequestsetpriorityoffsetreqh}, {"backend_httprequestsetpriorityoffsetreqh_", backend_httprequestsetpriorityoffsetreqh_}, {"backend_httprequestsetqueryqueryregsub3D", backend_httprequestsetqueryqueryregsub3D}, + {"backend_httprequestsetretries3", backend_httprequestsetretries3}, + {"backend_httprequestsetretriesvartxnretri", backend_httprequestsetretriesvartxnretri}, {"backend_httprequestsetsrchdrsrc", backend_httprequestsetsrchdrsrc}, {"backend_httprequestsetsrchdrsrcifFALSE", backend_httprequestsetsrchdrsrcifFALSE}, {"backend_httprequestsetsrcporthdrport", backend_httprequestsetsrcporthdrport}, @@ -1030,6 +1032,8 @@ func TestWholeConfigsSectionsBackend(t *testing.T) { {"backend_tcprequestcontentsetpriorityclas_", backend_tcprequestcontentsetpriorityclas_}, {"backend_tcprequestcontentsetpriorityoffs", backend_tcprequestcontentsetpriorityoffs}, {"backend_tcprequestcontentsetpriorityoffs_", backend_tcprequestcontentsetpriorityoffs_}, + {"backend_tcprequestcontentsetretries3", backend_tcprequestcontentsetretries3}, + {"backend_tcprequestcontentsetretriesvartx", backend_tcprequestcontentsetretriesvartx}, {"backend_tcprequestcontentsetsrcporthdrpo", backend_tcprequestcontentsetsrcporthdrpo}, {"backend_tcprequestcontentsetsrcporthdrpo_", backend_tcprequestcontentsetsrcporthdrpo_}, {"backend_tcprequestcontentsettos0", backend_tcprequestcontentsettos0}, diff --git a/config-parser/tests/integration/defaults_data_test.go b/config-parser/tests/integration/defaults_data_test.go index 929664a4..67e87131 100644 --- a/config-parser/tests/integration/defaults_data_test.go +++ b/config-parser/tests/integration/defaults_data_test.go @@ -1853,6 +1853,14 @@ const defaults_httprequestsetfctos0xffifTRUE = ` defaults test http-request set-fc-tos 0xff if TRUE ` +const defaults_httprequestsetretries3 = ` +defaults test + http-request set-retries 3 +` +const defaults_httprequestsetretriesvartxnretri = ` +defaults test + http-request set-retries var(txn.retries) if TRUE +` const defaults_httprequestaddheaderAuthorizatio = ` defaults test http-request add-header Authorization Basic\ eC1oYXByb3h5LXJlY3J1aXRzOlBlb3BsZSB3aG8gZGVjb2RlIG1lc3NhZ2VzIG9mdGVuIGxvdmUgd29ya2luZyBhdCBIQVByb3h5LiBEbyBub3QgYmUgc2h5LCBjb250YWN0IHVz @@ -3021,6 +3029,14 @@ const defaults_tcprequestcontentluafooparampara = ` defaults test tcp-request content lua.foo param param1 ` +const defaults_tcprequestcontentsetretries3 = ` +defaults test + tcp-request content set-retries 3 +` +const defaults_tcprequestcontentsetretriesvartx = ` +defaults test + tcp-request content set-retries var(txn.retries) if TRUE +` const defaults_tcprequestconnectionaccept = ` defaults test tcp-request connection accept diff --git a/config-parser/tests/integration/defaults_test.go b/config-parser/tests/integration/defaults_test.go index e25facaa..989cc0b0 100644 --- a/config-parser/tests/integration/defaults_test.go +++ b/config-parser/tests/integration/defaults_test.go @@ -489,6 +489,8 @@ func TestWholeConfigsSectionsDefaults(t *testing.T) { {"defaults_httprequestsetpriorityoffsetreqh", defaults_httprequestsetpriorityoffsetreqh}, {"defaults_httprequestsetpriorityoffsetreqh_", defaults_httprequestsetpriorityoffsetreqh_}, {"defaults_httprequestsetqueryqueryregsub3D", defaults_httprequestsetqueryqueryregsub3D}, + {"defaults_httprequestsetretries3", defaults_httprequestsetretries3}, + {"defaults_httprequestsetretriesvartxnretri", defaults_httprequestsetretriesvartxnretri}, {"defaults_httprequestsetsrchdrsrc", defaults_httprequestsetsrchdrsrc}, {"defaults_httprequestsetsrchdrsrcifFALSE", defaults_httprequestsetsrchdrsrcifFALSE}, {"defaults_httprequestsetsrcporthdrport", defaults_httprequestsetsrcporthdrport}, @@ -836,6 +838,8 @@ func TestWholeConfigsSectionsDefaults(t *testing.T) { {"defaults_tcprequestcontentsetpriorityclas_", defaults_tcprequestcontentsetpriorityclas_}, {"defaults_tcprequestcontentsetpriorityoffs", defaults_tcprequestcontentsetpriorityoffs}, {"defaults_tcprequestcontentsetpriorityoffs_", defaults_tcprequestcontentsetpriorityoffs_}, + {"defaults_tcprequestcontentsetretries3", defaults_tcprequestcontentsetretries3}, + {"defaults_tcprequestcontentsetretriesvartx", defaults_tcprequestcontentsetretriesvartx}, {"defaults_tcprequestcontentsetsrcporthdrpo", defaults_tcprequestcontentsetsrcporthdrpo}, {"defaults_tcprequestcontentsetsrcporthdrpo_", defaults_tcprequestcontentsetsrcporthdrpo_}, {"defaults_tcprequestcontentsettos0", defaults_tcprequestcontentsettos0}, diff --git a/config-parser/tests/integration/frontend_data_test.go b/config-parser/tests/integration/frontend_data_test.go index a035ea10..b66a1584 100644 --- a/config-parser/tests/integration/frontend_data_test.go +++ b/config-parser/tests/integration/frontend_data_test.go @@ -1581,6 +1581,14 @@ const frontend_httprequestsetfctos0xffifTRUE = ` frontend test http-request set-fc-tos 0xff if TRUE ` +const frontend_httprequestsetretries3 = ` +frontend test + http-request set-retries 3 +` +const frontend_httprequestsetretriesvartxnretri = ` +frontend test + http-request set-retries var(txn.retries) if TRUE +` const frontend_httprequestcapturereqcookcntFirs = ` frontend test http-request capture req.cook_cnt(FirstVisit),bool len 10 @@ -2513,6 +2521,14 @@ const frontend_tcprequestcontentluafooparampara = ` frontend test tcp-request content lua.foo param param1 ` +const frontend_tcprequestcontentsetretries3 = ` +frontend test + tcp-request content set-retries 3 +` +const frontend_tcprequestcontentsetretriesvartx = ` +frontend test + tcp-request content set-retries var(txn.retries) if TRUE +` const frontend_tcprequestconnectionaccept = ` frontend test tcp-request connection accept diff --git a/config-parser/tests/integration/frontend_test.go b/config-parser/tests/integration/frontend_test.go index f2146568..bdc747a9 100644 --- a/config-parser/tests/integration/frontend_test.go +++ b/config-parser/tests/integration/frontend_test.go @@ -389,6 +389,8 @@ func TestWholeConfigsSectionsFrontend(t *testing.T) { {"frontend_httprequestsetpriorityoffsetreqh", frontend_httprequestsetpriorityoffsetreqh}, {"frontend_httprequestsetpriorityoffsetreqh_", frontend_httprequestsetpriorityoffsetreqh_}, {"frontend_httprequestsetqueryqueryregsub3D", frontend_httprequestsetqueryqueryregsub3D}, + {"frontend_httprequestsetretries3", frontend_httprequestsetretries3}, + {"frontend_httprequestsetretriesvartxnretri", frontend_httprequestsetretriesvartxnretri}, {"frontend_httprequestsetsrchdrsrc", frontend_httprequestsetsrchdrsrc}, {"frontend_httprequestsetsrchdrsrcifFALSE", frontend_httprequestsetsrchdrsrcifFALSE}, {"frontend_httprequestsetsrcporthdrport", frontend_httprequestsetsrcporthdrport}, @@ -709,6 +711,8 @@ func TestWholeConfigsSectionsFrontend(t *testing.T) { {"frontend_tcprequestcontentsetpriorityclas_", frontend_tcprequestcontentsetpriorityclas_}, {"frontend_tcprequestcontentsetpriorityoffs", frontend_tcprequestcontentsetpriorityoffs}, {"frontend_tcprequestcontentsetpriorityoffs_", frontend_tcprequestcontentsetpriorityoffs_}, + {"frontend_tcprequestcontentsetretries3", frontend_tcprequestcontentsetretries3}, + {"frontend_tcprequestcontentsetretriesvartx", frontend_tcprequestcontentsetretriesvartx}, {"frontend_tcprequestcontentsetsrcporthdrpo", frontend_tcprequestcontentsetsrcporthdrpo}, {"frontend_tcprequestcontentsetsrcporthdrpo_", frontend_tcprequestcontentsetsrcporthdrpo_}, {"frontend_tcprequestcontentsettos0", frontend_tcprequestcontentsettos0}, diff --git a/config-parser/tests/tcp-request_generated_test.go b/config-parser/tests/tcp-request_generated_test.go index 18101ba3..522786bc 100644 --- a/config-parser/tests/tcp-request_generated_test.go +++ b/config-parser/tests/tcp-request_generated_test.go @@ -77,99 +77,101 @@ func TestRequeststcp(t *testing.T) { "tcp-request content silent-drop": true, "tcp-request content silent-drop if !HTTP": true, "tcp-request content silent-drop rst-ttl 1": true, - "tcp-request content silent-drop rst-ttl 1 if { src,table_http_req_rate(ratelimits.agg),sub(txn.rate_limit) ge 1000 }": true, - "tcp-request content send-spoe-group engine group": true, - "tcp-request content use-service lua.deny": true, - "tcp-request content use-service lua.deny if !HTTP": true, - "tcp-request content lua.foo": true, - "tcp-request content lua.foo param if !HTTP": true, - "tcp-request content lua.foo param param1": true, - "tcp-request connection accept": true, - "tcp-request connection accept if !HTTP": true, - "tcp-request connection reject": true, - "tcp-request connection reject if !HTTP": true, - "tcp-request connection expect-proxy layer4 if { src -f proxies.lst }": true, - "tcp-request connection expect-netscaler-cip layer4": true, - "tcp-request connection expect-netscaler-cip layer4 if TRUE": true, - "tcp-request connection capture req.payload(0,6) len 6": true, - "tcp-request connection track-sc0 src": true, - "tcp-request connection track-sc0 src if some_check": true, - "tcp-request connection track-sc1 src": true, - "tcp-request connection track-sc1 src if some_check": true, - "tcp-request connection track-sc2 src": true, - "tcp-request connection track-sc2 src if some_check": true, - "tcp-request connection track-sc0 src table foo": true, - "tcp-request connection track-sc0 src table foo if some_check": true, - "tcp-request connection track-sc1 src table foo": true, - "tcp-request connection track-sc1 src table foo if some_check": true, - "tcp-request connection track-sc2 src table foo": true, - "tcp-request connection track-sc2 src table foo if some_check": true, - "tcp-request connection track-sc5 src": true, - "tcp-request connection track-sc5 src if some_check": true, - "tcp-request connection track-sc5 src table foo": true, - "tcp-request connection track-sc5 src table foo if some_check": true, - "tcp-request connection sc-add-gpc(1,2) 1": true, - "tcp-request connection sc-add-gpc(1,2) 1 if is-error": true, - "tcp-request connection sc-inc-gpc(1,2)": true, - "tcp-request connection sc-inc-gpc(1,2) if is-error": true, - "tcp-request connection sc-inc-gpc0(2)": true, - "tcp-request connection sc-inc-gpc0(2) if is-error": true, - "tcp-request connection sc-inc-gpc1(2)": true, - "tcp-request connection sc-inc-gpc1(2) if is-error": true, - "tcp-request connection sc-set-gpt(scx,44) 1337 if exceeds_limit": true, - "tcp-request connection sc-set-gpt0(0) 1337": true, - "tcp-request connection sc-set-gpt0(0) 1337 if exceeds_limit": true, - "tcp-request connection set-src src,ipmask(24)": true, - "tcp-request connection set-src src,ipmask(24) if some_check": true, - "tcp-request connection set-src hdr(x-forwarded-for)": true, - "tcp-request connection set-src hdr(x-forwarded-for) if some_check": true, - "tcp-request connection silent-drop": true, - "tcp-request connection silent-drop if !HTTP": true, - "tcp-request connection silent-drop rst-ttl 1": true, + "tcp-request content silent-drop rst-ttl 1 if { src,table_http_req_rate(ratelimits.agg),sub(txn.rate_limit) ge 1000 }": true, + "tcp-request content send-spoe-group engine group": true, + "tcp-request content use-service lua.deny": true, + "tcp-request content use-service lua.deny if !HTTP": true, + "tcp-request content lua.foo": true, + "tcp-request content lua.foo param if !HTTP": true, + "tcp-request content lua.foo param param1": true, + "tcp-request content set-retries 3": true, + "tcp-request content set-retries var(txn.retries) if TRUE": true, + "tcp-request connection accept": true, + "tcp-request connection accept if !HTTP": true, + "tcp-request connection reject": true, + "tcp-request connection reject if !HTTP": true, + "tcp-request connection expect-proxy layer4 if { src -f proxies.lst }": true, + "tcp-request connection expect-netscaler-cip layer4": true, + "tcp-request connection expect-netscaler-cip layer4 if TRUE": true, + "tcp-request connection capture req.payload(0,6) len 6": true, + "tcp-request connection track-sc0 src": true, + "tcp-request connection track-sc0 src if some_check": true, + "tcp-request connection track-sc1 src": true, + "tcp-request connection track-sc1 src if some_check": true, + "tcp-request connection track-sc2 src": true, + "tcp-request connection track-sc2 src if some_check": true, + "tcp-request connection track-sc0 src table foo": true, + "tcp-request connection track-sc0 src table foo if some_check": true, + "tcp-request connection track-sc1 src table foo": true, + "tcp-request connection track-sc1 src table foo if some_check": true, + "tcp-request connection track-sc2 src table foo": true, + "tcp-request connection track-sc2 src table foo if some_check": true, + "tcp-request connection track-sc5 src": true, + "tcp-request connection track-sc5 src if some_check": true, + "tcp-request connection track-sc5 src table foo": true, + "tcp-request connection track-sc5 src table foo if some_check": true, + "tcp-request connection sc-add-gpc(1,2) 1": true, + "tcp-request connection sc-add-gpc(1,2) 1 if is-error": true, + "tcp-request connection sc-inc-gpc(1,2)": true, + "tcp-request connection sc-inc-gpc(1,2) if is-error": true, + "tcp-request connection sc-inc-gpc0(2)": true, + "tcp-request connection sc-inc-gpc0(2) if is-error": true, + "tcp-request connection sc-inc-gpc1(2)": true, + "tcp-request connection sc-inc-gpc1(2) if is-error": true, + "tcp-request connection sc-set-gpt(scx,44) 1337 if exceeds_limit": true, + "tcp-request connection sc-set-gpt0(0) 1337": true, + "tcp-request connection sc-set-gpt0(0) 1337 if exceeds_limit": true, + "tcp-request connection set-src src,ipmask(24)": true, + "tcp-request connection set-src src,ipmask(24) if some_check": true, + "tcp-request connection set-src hdr(x-forwarded-for)": true, + "tcp-request connection set-src hdr(x-forwarded-for) if some_check": true, + "tcp-request connection silent-drop": true, + "tcp-request connection silent-drop if !HTTP": true, + "tcp-request connection silent-drop rst-ttl 1": true, "tcp-request connection silent-drop rst-ttl 1 if { src,table_http_req_rate(ratelimits.agg),sub(txn.rate_limit) ge 1000 }": true, - "tcp-request connection lua.foo": true, - "tcp-request connection lua.foo param if !HTTP": true, - "tcp-request connection lua.foo param param1": true, - "tcp-request session accept": true, - "tcp-request session accept if !HTTP": true, - "tcp-request session reject": true, - "tcp-request session reject if !HTTP": true, - "tcp-request session track-sc0 src": true, - "tcp-request session track-sc0 src if some_check": true, - "tcp-request session track-sc1 src": true, - "tcp-request session track-sc1 src if some_check": true, - "tcp-request session track-sc2 src": true, - "tcp-request session track-sc2 src if some_check": true, - "tcp-request session track-sc0 src table foo": true, - "tcp-request session track-sc0 src table foo if some_check": true, - "tcp-request session track-sc1 src table foo": true, - "tcp-request session track-sc1 src table foo if some_check": true, - "tcp-request session track-sc2 src table foo": true, - "tcp-request session track-sc2 src table foo if some_check": true, - "tcp-request session track-sc5 src": true, - "tcp-request session track-sc5 src if some_check": true, - "tcp-request session track-sc5 src table foo": true, - "tcp-request session track-sc5 src table foo if some_check": true, - "tcp-request session sc-add-gpc(1,2) 1": true, - "tcp-request session sc-add-gpc(1,2) 1 if is-error": true, - "tcp-request session sc-inc-gpc(1,2)": true, - "tcp-request session sc-inc-gpc(1,2) if is-error": true, - "tcp-request session sc-inc-gpc0(2)": true, - "tcp-request session sc-inc-gpc0(2) if is-error": true, - "tcp-request session sc-inc-gpc1(2)": true, - "tcp-request session sc-inc-gpc1(2) if is-error": true, - "tcp-request session sc-set-gpt(sc5,1) 1337 if exceeds_limit": true, - "tcp-request session sc-set-gpt0(0) 1337": true, - "tcp-request session sc-set-gpt0(0) 1337 if exceeds_limit": true, - "tcp-request session set-var(sess.src) src": true, - "tcp-request session set-var(sess.dn) ssl_c_s_dn": true, - "tcp-request session set-var-fmt(sess.src) src": true, - "tcp-request session set-var-fmt(sess.dn) ssl_c_s_dn": true, - "tcp-request session unset-var(sess.src)": true, - "tcp-request session unset-var(sess.dn)": true, - "tcp-request session silent-drop": true, - "tcp-request session silent-drop if !HTTP": true, - "tcp-request session silent-drop rst-ttl 1": true, + "tcp-request connection lua.foo": true, + "tcp-request connection lua.foo param if !HTTP": true, + "tcp-request connection lua.foo param param1": true, + "tcp-request session accept": true, + "tcp-request session accept if !HTTP": true, + "tcp-request session reject": true, + "tcp-request session reject if !HTTP": true, + "tcp-request session track-sc0 src": true, + "tcp-request session track-sc0 src if some_check": true, + "tcp-request session track-sc1 src": true, + "tcp-request session track-sc1 src if some_check": true, + "tcp-request session track-sc2 src": true, + "tcp-request session track-sc2 src if some_check": true, + "tcp-request session track-sc0 src table foo": true, + "tcp-request session track-sc0 src table foo if some_check": true, + "tcp-request session track-sc1 src table foo": true, + "tcp-request session track-sc1 src table foo if some_check": true, + "tcp-request session track-sc2 src table foo": true, + "tcp-request session track-sc2 src table foo if some_check": true, + "tcp-request session track-sc5 src": true, + "tcp-request session track-sc5 src if some_check": true, + "tcp-request session track-sc5 src table foo": true, + "tcp-request session track-sc5 src table foo if some_check": true, + "tcp-request session sc-add-gpc(1,2) 1": true, + "tcp-request session sc-add-gpc(1,2) 1 if is-error": true, + "tcp-request session sc-inc-gpc(1,2)": true, + "tcp-request session sc-inc-gpc(1,2) if is-error": true, + "tcp-request session sc-inc-gpc0(2)": true, + "tcp-request session sc-inc-gpc0(2) if is-error": true, + "tcp-request session sc-inc-gpc1(2)": true, + "tcp-request session sc-inc-gpc1(2) if is-error": true, + "tcp-request session sc-set-gpt(sc5,1) 1337 if exceeds_limit": true, + "tcp-request session sc-set-gpt0(0) 1337": true, + "tcp-request session sc-set-gpt0(0) 1337 if exceeds_limit": true, + "tcp-request session set-var(sess.src) src": true, + "tcp-request session set-var(sess.dn) ssl_c_s_dn": true, + "tcp-request session set-var-fmt(sess.src) src": true, + "tcp-request session set-var-fmt(sess.dn) ssl_c_s_dn": true, + "tcp-request session unset-var(sess.src)": true, + "tcp-request session unset-var(sess.dn)": true, + "tcp-request session silent-drop": true, + "tcp-request session silent-drop if !HTTP": true, + "tcp-request session silent-drop rst-ttl 1": true, "tcp-request session silent-drop rst-ttl 1 if { src,table_http_req_rate(ratelimits.agg),sub(txn.rate_limit) ge 1000 }": true, "tcp-request session attach-srv srv1": true, "tcp-request session attach-srv srv1 name example.com": true, diff --git a/config-parser/types/types-other.go b/config-parser/types/types-other.go index ad58b9f6..74cdb72d 100644 --- a/config-parser/types/types-other.go +++ b/config-parser/types/types-other.go @@ -553,6 +553,8 @@ type Action interface { //test:ok:http-request set-bc-tos 10 //test:ok:http-request set-fc-mark 0 //test:ok:http-request set-fc-tos 0xff if TRUE +//test:ok:http-request set-retries 3 +//test:ok:http-request set-retries var(txn.retries) if TRUE type HTTPRequests struct{} //name:http-response @@ -1015,6 +1017,8 @@ type TCPType interface { //test:ok:tcp-request content lua.foo //test:ok:tcp-request content lua.foo param if !HTTP //test:ok:tcp-request content lua.foo param param1 +//test:ok:tcp-request content set-retries 3 +//test:ok:tcp-request content set-retries var(txn.retries) if TRUE //test:ok:tcp-request connection accept //test:ok:tcp-request connection accept if !HTTP //test:ok:tcp-request connection reject diff --git a/configuration/http_request_rule.go b/configuration/http_request_rule.go index a3ded9b1..05f9a8c5 100644 --- a/configuration/http_request_rule.go +++ b/configuration/http_request_rule.go @@ -805,6 +805,13 @@ func ParseHTTPRequestRule(f types.Action) (*models.HTTPRequestRule, error) { //n Cond: v.Cond, CondTest: v.CondTest, } + case *actions.SetRetries: + rule = &models.HTTPRequestRule{ + Type: models.HTTPRequestRuleTypeSetDashRetries, + Expr: v.Expr.String(), + Cond: v.Cond, + CondTest: v.CondTest, + } } return rule, nil @@ -1302,6 +1309,12 @@ func SerializeHTTPRequestRule(f models.HTTPRequestRule, opt *options.Configurati Cond: f.Cond, CondTest: f.CondTest, } + case "set-retries": + rule = &actions.SetRetries{ + Expr: common.Expression{Expr: strings.Split(f.Expr, " ")}, + Cond: f.Cond, + CondTest: f.CondTest, + } } return rule, nil diff --git a/configuration/tcp_request_rule.go b/configuration/tcp_request_rule.go index 83a41bb2..f5687056 100644 --- a/configuration/tcp_request_rule.go +++ b/configuration/tcp_request_rule.go @@ -621,6 +621,11 @@ func ParseTCPRequestRule(f types.TCPType) (*models.TCPRequestRule, error) { //no rule.SwitchModeProto = a.Proto rule.Cond = a.Cond rule.CondTest = a.CondTest + case *actions.SetRetries: + rule.Action = models.TCPRequestRuleActionSetDashRetries + rule.Expr = a.Expr.String() + rule.Cond = a.Cond + rule.CondTest = a.CondTest default: return nil, NewConfError(ErrValidationError, fmt.Sprintf("unsupported action '%s' in tcp_request_rule", a)) } @@ -1288,6 +1293,14 @@ func SerializeTCPRequestRule(f models.TCPRequestRule, opt *options.Configuration CondTest: f.CondTest, }, }, nil + case models.TCPRequestRuleActionSetDashRetries: + return &tcp_types.Content{ + Action: &actions.SetRetries{ + Expr: common.Expression{Expr: strings.Split(f.Expr, " ")}, + Cond: f.Cond, + CondTest: f.CondTest, + }, + }, nil } return nil, NewConfError(ErrValidationError, fmt.Sprintf("unsupported action '%s' in tcp_request_rule", f.Action)) case models.TCPRequestRuleTypeSession: diff --git a/models/http_request_rule.go b/models/http_request_rule.go index f7ce1f68..644ac35a 100644 --- a/models/http_request_rule.go +++ b/models/http_request_rule.go @@ -296,8 +296,8 @@ type HTTPRequestRule struct { // type // Required: true - // Enum: ["add-acl","add-header","allow","auth","cache-use","capture","del-acl","del-header","del-map","deny","disable-l7-retry","do-resolve","early-hint","lua","normalize-uri","redirect","reject","replace-header","replace-path","replace-pathq","replace-uri","replace-value","return","sc-add-gpc","sc-inc-gpc","sc-inc-gpc0","sc-inc-gpc1","sc-set-gpt","sc-set-gpt0","send-spoe-group","set-bc-mark","set-bc-tos","set-dst","set-dst-port","set-fc-mark","set-fc-tos","set-header","set-log-level","set-map","set-mark","set-method","set-nice","set-path","set-pathq","set-priority-class","set-priority-offset","set-query","set-src","set-src-port","set-timeout","set-tos","set-uri","set-var","silent-drop","strict-mode","tarpit","track-sc","unset-var","use-service","wait-for-body","wait-for-handshake","set-bandwidth-limit"] - // +kubebuilder:validation:Enum="add-acl","add-header","allow","auth","cache-use","capture","del-acl","del-header","del-map","deny","disable-l7-retry","do-resolve","early-hint","lua","normalize-uri","redirect","reject","replace-header","replace-path","replace-pathq","replace-uri","replace-value","return","sc-add-gpc","sc-inc-gpc","sc-inc-gpc0","sc-inc-gpc1","sc-set-gpt","sc-set-gpt0","send-spoe-group","set-bc-mark","set-bc-tos","set-dst","set-dst-port","set-fc-mark","set-fc-tos","set-header","set-log-level","set-map","set-mark","set-method","set-nice","set-path","set-pathq","set-priority-class","set-priority-offset","set-query","set-src","set-src-port","set-timeout","set-tos","set-uri","set-var","silent-drop","strict-mode","tarpit","track-sc","unset-var","use-service","wait-for-body","wait-for-handshake","set-bandwidth-limit"; + // Enum: ["add-acl","add-header","allow","auth","cache-use","capture","del-acl","del-header","del-map","deny","disable-l7-retry","do-resolve","early-hint","lua","normalize-uri","redirect","reject","replace-header","replace-path","replace-pathq","replace-uri","replace-value","return","sc-add-gpc","sc-inc-gpc","sc-inc-gpc0","sc-inc-gpc1","sc-set-gpt","sc-set-gpt0","send-spoe-group","set-bc-mark","set-bc-tos","set-dst","set-dst-port","set-fc-mark","set-fc-tos","set-header","set-log-level","set-map","set-mark","set-method","set-nice","set-path","set-pathq","set-priority-class","set-priority-offset","set-query","set-src","set-src-port","set-timeout","set-tos","set-uri","set-var","silent-drop","strict-mode","tarpit","track-sc","unset-var","use-service","wait-for-body","wait-for-handshake","set-bandwidth-limit","set-retries"] + // +kubebuilder:validation:Enum="add-acl","add-header","allow","auth","cache-use","capture","del-acl","del-header","del-map","deny","disable-l7-retry","do-resolve","early-hint","lua","normalize-uri","redirect","reject","replace-header","replace-path","replace-pathq","replace-uri","replace-value","return","sc-add-gpc","sc-inc-gpc","sc-inc-gpc0","sc-inc-gpc1","sc-set-gpt","sc-set-gpt0","send-spoe-group","set-bc-mark","set-bc-tos","set-dst","set-dst-port","set-fc-mark","set-fc-tos","set-header","set-log-level","set-map","set-mark","set-method","set-nice","set-path","set-pathq","set-priority-class","set-priority-offset","set-query","set-src","set-src-port","set-timeout","set-tos","set-uri","set-var","silent-drop","strict-mode","tarpit","track-sc","unset-var","use-service","wait-for-body","wait-for-handshake","set-bandwidth-limit","set-retries"; Type string `json:"type"` // uri fmt @@ -1252,7 +1252,7 @@ var httpRequestRuleTypeTypePropEnum []interface{} func init() { var res []string - if err := json.Unmarshal([]byte(`["add-acl","add-header","allow","auth","cache-use","capture","del-acl","del-header","del-map","deny","disable-l7-retry","do-resolve","early-hint","lua","normalize-uri","redirect","reject","replace-header","replace-path","replace-pathq","replace-uri","replace-value","return","sc-add-gpc","sc-inc-gpc","sc-inc-gpc0","sc-inc-gpc1","sc-set-gpt","sc-set-gpt0","send-spoe-group","set-bc-mark","set-bc-tos","set-dst","set-dst-port","set-fc-mark","set-fc-tos","set-header","set-log-level","set-map","set-mark","set-method","set-nice","set-path","set-pathq","set-priority-class","set-priority-offset","set-query","set-src","set-src-port","set-timeout","set-tos","set-uri","set-var","silent-drop","strict-mode","tarpit","track-sc","unset-var","use-service","wait-for-body","wait-for-handshake","set-bandwidth-limit"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["add-acl","add-header","allow","auth","cache-use","capture","del-acl","del-header","del-map","deny","disable-l7-retry","do-resolve","early-hint","lua","normalize-uri","redirect","reject","replace-header","replace-path","replace-pathq","replace-uri","replace-value","return","sc-add-gpc","sc-inc-gpc","sc-inc-gpc0","sc-inc-gpc1","sc-set-gpt","sc-set-gpt0","send-spoe-group","set-bc-mark","set-bc-tos","set-dst","set-dst-port","set-fc-mark","set-fc-tos","set-header","set-log-level","set-map","set-mark","set-method","set-nice","set-path","set-pathq","set-priority-class","set-priority-offset","set-query","set-src","set-src-port","set-timeout","set-tos","set-uri","set-var","silent-drop","strict-mode","tarpit","track-sc","unset-var","use-service","wait-for-body","wait-for-handshake","set-bandwidth-limit","set-retries"]`), &res); err != nil { panic(err) } for _, v := range res { @@ -1447,6 +1447,9 @@ const ( // HTTPRequestRuleTypeSetDashBandwidthDashLimit captures enum value "set-bandwidth-limit" HTTPRequestRuleTypeSetDashBandwidthDashLimit string = "set-bandwidth-limit" + + // HTTPRequestRuleTypeSetDashRetries captures enum value "set-retries" + HTTPRequestRuleTypeSetDashRetries string = "set-retries" ) // prop value enum diff --git a/models/tcp_request_rule.go b/models/tcp_request_rule.go index 68a56a50..ee3e07b7 100644 --- a/models/tcp_request_rule.go +++ b/models/tcp_request_rule.go @@ -38,8 +38,8 @@ import ( // swagger:model tcp_request_rule type TCPRequestRule struct { // action - // Enum: ["accept","attach-srv","capture","do-resolve","expect-netscaler-cip","expect-proxy","lua","reject","sc-add-gpc","sc-inc-gpc","sc-inc-gpc0","sc-inc-gpc1","sc-set-gpt","sc-set-gpt0","send-spoe-group","set-bandwidth-limit","set-bc-mark","set-bc-tos","set-dst-port","set-dst","set-fc-mark","set-fc-tos","set-log-level","set-mark","set-nice","set-priority-class","set-priority-offset","set-src","set-src-port","set-tos","set-var","set-var-fmt","silent-drop","switch-mode","track-sc","unset-var","use-service"] - // +kubebuilder:validation:Enum="accept","attach-srv","capture","do-resolve","expect-netscaler-cip","expect-proxy","lua","reject","sc-add-gpc","sc-inc-gpc","sc-inc-gpc0","sc-inc-gpc1","sc-set-gpt","sc-set-gpt0","send-spoe-group","set-bandwidth-limit","set-bc-mark","set-bc-tos","set-dst-port","set-dst","set-fc-mark","set-fc-tos","set-log-level","set-mark","set-nice","set-priority-class","set-priority-offset","set-src","set-src-port","set-tos","set-var","set-var-fmt","silent-drop","switch-mode","track-sc","unset-var","use-service"; + // Enum: ["accept","attach-srv","capture","do-resolve","expect-netscaler-cip","expect-proxy","lua","reject","sc-add-gpc","sc-inc-gpc","sc-inc-gpc0","sc-inc-gpc1","sc-set-gpt","sc-set-gpt0","send-spoe-group","set-bandwidth-limit","set-bc-mark","set-bc-tos","set-dst-port","set-dst","set-fc-mark","set-fc-tos","set-log-level","set-mark","set-nice","set-priority-class","set-priority-offset","set-src","set-src-port","set-tos","set-var","set-var-fmt","silent-drop","switch-mode","track-sc","unset-var","use-service","set-retries"] + // +kubebuilder:validation:Enum="accept","attach-srv","capture","do-resolve","expect-netscaler-cip","expect-proxy","lua","reject","sc-add-gpc","sc-inc-gpc","sc-inc-gpc0","sc-inc-gpc1","sc-set-gpt","sc-set-gpt0","send-spoe-group","set-bandwidth-limit","set-bc-mark","set-bc-tos","set-dst-port","set-dst","set-fc-mark","set-fc-tos","set-log-level","set-mark","set-nice","set-priority-class","set-priority-offset","set-src","set-src-port","set-tos","set-var","set-var-fmt","silent-drop","switch-mode","track-sc","unset-var","use-service","set-retries"; Action string `json:"action,omitempty"` // bandwidth limit limit @@ -235,7 +235,7 @@ var tcpRequestRuleTypeActionPropEnum []interface{} func init() { var res []string - if err := json.Unmarshal([]byte(`["accept","attach-srv","capture","do-resolve","expect-netscaler-cip","expect-proxy","lua","reject","sc-add-gpc","sc-inc-gpc","sc-inc-gpc0","sc-inc-gpc1","sc-set-gpt","sc-set-gpt0","send-spoe-group","set-bandwidth-limit","set-bc-mark","set-bc-tos","set-dst-port","set-dst","set-fc-mark","set-fc-tos","set-log-level","set-mark","set-nice","set-priority-class","set-priority-offset","set-src","set-src-port","set-tos","set-var","set-var-fmt","silent-drop","switch-mode","track-sc","unset-var","use-service"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["accept","attach-srv","capture","do-resolve","expect-netscaler-cip","expect-proxy","lua","reject","sc-add-gpc","sc-inc-gpc","sc-inc-gpc0","sc-inc-gpc1","sc-set-gpt","sc-set-gpt0","send-spoe-group","set-bandwidth-limit","set-bc-mark","set-bc-tos","set-dst-port","set-dst","set-fc-mark","set-fc-tos","set-log-level","set-mark","set-nice","set-priority-class","set-priority-offset","set-src","set-src-port","set-tos","set-var","set-var-fmt","silent-drop","switch-mode","track-sc","unset-var","use-service","set-retries"]`), &res); err != nil { panic(err) } for _, v := range res { @@ -355,6 +355,9 @@ const ( // TCPRequestRuleActionUseDashService captures enum value "use-service" TCPRequestRuleActionUseDashService string = "use-service" + + // TCPRequestRuleActionSetDashRetries captures enum value "set-retries" + TCPRequestRuleActionSetDashRetries string = "set-retries" ) // prop value enum diff --git a/specification/build/haproxy_spec.yaml b/specification/build/haproxy_spec.yaml index 527b5141..e6e33d83 100644 --- a/specification/build/haproxy_spec.yaml +++ b/specification/build/haproxy_spec.yaml @@ -4438,6 +4438,7 @@ definitions: - set-priority-offset - set-src - set-src-port + - set-retries x-display-name: Standard HAProxy expression hdr_format: type: string @@ -4937,6 +4938,7 @@ definitions: - wait-for-body - wait-for-handshake - set-bandwidth-limit + - set-retries type: string x-nullable: false uri-fmt: @@ -6245,6 +6247,7 @@ definitions: - track-sc - unset-var - use-service + - set-retries type: string x-dependency: type: @@ -6349,6 +6352,7 @@ definitions: - set-src - set-src-port - set-var + - set-retries type: value: - session diff --git a/specification/models/configuration/http/request.yaml b/specification/models/configuration/http/request.yaml index 0c6f46f2..344b355f 100644 --- a/specification/models/configuration/http/request.yaml +++ b/specification/models/configuration/http/request.yaml @@ -71,6 +71,7 @@ http_request_rule: - wait-for-body - wait-for-handshake - set-bandwidth-limit + - set-retries x-nullable: false capture_sample: pattern: '^(?:[A-Za-z]+\("([A-Za-z\s]+)"\)|[A-Za-z]+)' @@ -435,6 +436,7 @@ http_request_rule: - set-priority-offset - set-src - set-src-port + - set-retries required: true sc_expr: type: string diff --git a/specification/models/configuration/tcp/request.yaml b/specification/models/configuration/tcp/request.yaml index b2424106..c4b734b9 100644 --- a/specification/models/configuration/tcp/request.yaml +++ b/specification/models/configuration/tcp/request.yaml @@ -50,6 +50,7 @@ tcp_request_rule: - track-sc - unset-var - use-service + - set-retries x-nullable: false x-dependency: type: @@ -275,6 +276,7 @@ tcp_request_rule: - set-src - set-src-port - set-var + - set-retries required: true type: value: [session, connection, content] diff --git a/test/configuration_test.go b/test/configuration_test.go index 7c728e30..50534f23 100644 --- a/test/configuration_test.go +++ b/test/configuration_test.go @@ -470,6 +470,8 @@ frontend test http-request set-fc-mark hdr(port) http-request set-fc-tos 255 if FALSE http-request sc-set-gpt(1,2) hdr(Host),lower if FALSE + http-request set-retries 3 + http-request set-retries var(txn.retries) if TRUE http-response allow if src 192.168.0.0/16 http-response set-header X-SSL %[ssl_fc] http-response set-var(req.my_var) req.fhdr(user-agent),lower @@ -569,6 +571,8 @@ frontend test tcp-request connection sc-set-gpt(1,2) 1234 if FALSE tcp-request content sc-set-gpt(1,2) hdr(port) if FALSE tcp-request session sc-set-gpt(1,2) 1234 + tcp-request content set-retries 3 + tcp-request content set-retries var(txn.retries) if TRUE log global no log log 127.0.0.1:514 local0 notice notice diff --git a/test/expected/structured.json b/test/expected/structured.json index b745fea3..b768584c 100644 --- a/test/expected/structured.json +++ b/test/expected/structured.json @@ -1996,6 +1996,16 @@ "sc_expr": "hdr(Host),lower", "cond": "if", "cond_test": "FALSE" + }, + { + "type": "set-retries", + "expr": "3" + }, + { + "type": "set-retries", + "expr": "var(txn.retries)", + "cond": "if", + "cond_test": "TRUE" } ], "http_response_rule_list": [ @@ -2567,6 +2577,18 @@ "sc_inc_id": "1", "sc_idx": "2", "sc_int": 1234 + }, + { + "type": "content", + "action": "set-retries", + "expr": "3" + }, + { + "type": "content", + "action": "set-retries", + "expr": "var(txn.retries)", + "cond": "if", + "cond_test": "TRUE" } ], "binds": {