diff --git a/parsers/tcp/actions/attach-srv.go b/parsers/tcp/actions/attach-srv.go new file mode 100644 index 0000000..2ba4850 --- /dev/null +++ b/parsers/tcp/actions/attach-srv.go @@ -0,0 +1,102 @@ +/* +Copyright 2023 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. +*/ + +package actions + +import ( + "fmt" + "strings" + + "github.com/haproxytech/config-parser/v5/common" + "github.com/haproxytech/config-parser/v5/types" +) + +type AttachSrv struct { + Server string + Name common.Expression + Cond string + CondTest string + Comment string +} + +// tcp-request session attach-srv [name ] [{ if | unless } ] + +func (f *AttachSrv) Parse(parts []string, parserType types.ParserType, comment string) error { + if f.Comment != "" { + f.Comment = comment + } + + n := len(parts) + if n < 4 { + return fmt.Errorf("not enough params") + } + + f.Server = parts[3] + + if n == 4 { + // Nothing more to parse. + return nil + } + + i := 4 + + if parts[i] == "name" { + if n < 6 { + return fmt.Errorf("not enough params") + } + expr := common.Expression{} + err := expr.Parse([]string{parts[i+1]}) + if err != nil { + return fmt.Errorf("invalid expression after '%s': %w", parts[i], err) + } + f.Name = expr + i += 2 + if i == n { + return nil + } + } + + _, condition := common.SplitRequest(parts[i:]) + if len(condition) > 1 { + f.Cond = condition[0] + f.CondTest = strings.Join(condition[1:], " ") + } else { + return fmt.Errorf("invalid condition after '%s'", parts[i]) + } + + return nil +} + +func (f *AttachSrv) String() string { + var result strings.Builder + result.WriteString("attach-srv ") + result.WriteString(f.Server) + if name := f.Name.String(); name != "" { + result.WriteString(" name ") + result.WriteString(name) + } + if f.Cond != "" { + result.WriteString(" ") + result.WriteString(f.Cond) + result.WriteString(" ") + result.WriteString(f.CondTest) + } + return result.String() +} + +func (f *AttachSrv) GetComment() string { + return f.Comment +} diff --git a/parsers/tcp/types/session.go b/parsers/tcp/types/session.go index 7f04d0e..04bbf2e 100644 --- a/parsers/tcp/types/session.go +++ b/parsers/tcp/types/session.go @@ -51,6 +51,8 @@ func (f *Session) Parse(parts []string, comment string) error { switch parts[2] { case "accept": err = f.ParseAction(&tcpActions.Accept{}, parts) + case "attach-srv": + err = f.ParseAction(&tcpActions.AttachSrv{}, parts) case "reject": err = f.ParseAction(&actions.Reject{}, parts) case "silent-drop": diff --git a/tests/configs/haproxy_generated.cfg.go b/tests/configs/haproxy_generated.cfg.go index 02864e1..74b552a 100644 --- a/tests/configs/haproxy_generated.cfg.go +++ b/tests/configs/haproxy_generated.cfg.go @@ -948,6 +948,9 @@ backend test tcp-request session unset-var(sess.dn) tcp-request session silent-drop tcp-request session silent-drop if !HTTP + tcp-request session attach-srv srv1 + tcp-request session attach-srv srv1 name example.com + tcp-request session attach-srv srv1 name example.com if exceeds_limit tcp-request content set-bandwidth-limit my-limit tcp-request content set-bandwidth-limit my-limit limit 1m period 10s tcp-request content set-bandwidth-limit my-limit period 10s @@ -1968,6 +1971,9 @@ frontend test tcp-request session unset-var(sess.dn) tcp-request session silent-drop tcp-request session silent-drop if !HTTP + tcp-request session attach-srv srv1 + tcp-request session attach-srv srv1 name example.com + tcp-request session attach-srv srv1 name example.com if exceeds_limit tcp-request content set-bandwidth-limit my-limit tcp-request content set-bandwidth-limit my-limit limit 1m period 10s tcp-request content set-bandwidth-limit my-limit period 10s @@ -4328,6 +4334,12 @@ var configTests = []configTest{{` command spoa-mirror --runtime 0 --mirror-url {` tcp-request session silent-drop `, 2}, {` tcp-request session silent-drop if !HTTP +`, 2}, + {` tcp-request session attach-srv srv1 +`, 2}, + {` tcp-request session attach-srv srv1 name example.com +`, 2}, + {` tcp-request session attach-srv srv1 name example.com if exceeds_limit `, 2}, {` tcp-request content set-bandwidth-limit my-limit `, 2}, diff --git a/tests/integration/backend_data_test.go b/tests/integration/backend_data_test.go index 74595e7..e288157 100644 --- a/tests/integration/backend_data_test.go +++ b/tests/integration/backend_data_test.go @@ -4013,6 +4013,18 @@ const backend_tcprequestsessionsilentdropifHTT = ` backend test tcp-request session silent-drop if !HTTP ` +const backend_tcprequestsessionattachsrvsrv1 = ` +backend test + tcp-request session attach-srv srv1 +` +const backend_tcprequestsessionattachsrvsrv1na = ` +backend test + tcp-request session attach-srv srv1 name example.com +` +const backend_tcprequestsessionattachsrvsrv1na_ = ` +backend test + tcp-request session attach-srv srv1 name example.com if exceeds_limit +` const backend_tcprequestcontentsetbandwidthlim = ` backend test tcp-request content set-bandwidth-limit my-limit diff --git a/tests/integration/backend_test.go b/tests/integration/backend_test.go index 3d8d5f4..a612090 100644 --- a/tests/integration/backend_test.go +++ b/tests/integration/backend_test.go @@ -1037,6 +1037,9 @@ func TestWholeConfigsSectionsBackend(t *testing.T) { {"backend_tcprequestcontentuseserviceluade_", backend_tcprequestcontentuseserviceluade_}, {"backend_tcprequestsessionaccept", backend_tcprequestsessionaccept}, {"backend_tcprequestsessionacceptifHTTP", backend_tcprequestsessionacceptifHTTP}, + {"backend_tcprequestsessionattachsrvsrv1", backend_tcprequestsessionattachsrvsrv1}, + {"backend_tcprequestsessionattachsrvsrv1na", backend_tcprequestsessionattachsrvsrv1na}, + {"backend_tcprequestsessionattachsrvsrv1na_", backend_tcprequestsessionattachsrvsrv1na_}, {"backend_tcprequestsessionreject", backend_tcprequestsessionreject}, {"backend_tcprequestsessionrejectifHTTP", backend_tcprequestsessionrejectifHTTP}, {"backend_tcprequestsessionscaddgpc121", backend_tcprequestsessionscaddgpc121}, diff --git a/tests/integration/frontend_data_test.go b/tests/integration/frontend_data_test.go index df90b7b..86ac8c3 100644 --- a/tests/integration/frontend_data_test.go +++ b/tests/integration/frontend_data_test.go @@ -2749,6 +2749,18 @@ const frontend_tcprequestsessionsilentdropifHTT = ` frontend test tcp-request session silent-drop if !HTTP ` +const frontend_tcprequestsessionattachsrvsrv1 = ` +frontend test + tcp-request session attach-srv srv1 +` +const frontend_tcprequestsessionattachsrvsrv1na = ` +frontend test + tcp-request session attach-srv srv1 name example.com +` +const frontend_tcprequestsessionattachsrvsrv1na_ = ` +frontend test + tcp-request session attach-srv srv1 name example.com if exceeds_limit +` const frontend_tcprequestcontentsetbandwidthlim = ` frontend test tcp-request content set-bandwidth-limit my-limit diff --git a/tests/integration/frontend_test.go b/tests/integration/frontend_test.go index 3495701..43a1290 100644 --- a/tests/integration/frontend_test.go +++ b/tests/integration/frontend_test.go @@ -713,6 +713,9 @@ func TestWholeConfigsSectionsFrontend(t *testing.T) { {"frontend_tcprequestcontentuseserviceluade_", frontend_tcprequestcontentuseserviceluade_}, {"frontend_tcprequestsessionaccept", frontend_tcprequestsessionaccept}, {"frontend_tcprequestsessionacceptifHTTP", frontend_tcprequestsessionacceptifHTTP}, + {"frontend_tcprequestsessionattachsrvsrv1", frontend_tcprequestsessionattachsrvsrv1}, + {"frontend_tcprequestsessionattachsrvsrv1na", frontend_tcprequestsessionattachsrvsrv1na}, + {"frontend_tcprequestsessionattachsrvsrv1na_", frontend_tcprequestsessionattachsrvsrv1na_}, {"frontend_tcprequestsessionreject", frontend_tcprequestsessionreject}, {"frontend_tcprequestsessionrejectifHTTP", frontend_tcprequestsessionrejectifHTTP}, {"frontend_tcprequestsessionscaddgpc121", frontend_tcprequestsessionscaddgpc121}, diff --git a/tests/tcp-request_generated_test.go b/tests/tcp-request_generated_test.go index 8af1694..9cec01b 100644 --- a/tests/tcp-request_generated_test.go +++ b/tests/tcp-request_generated_test.go @@ -161,6 +161,9 @@ func TestRequeststcp(t *testing.T) { "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 attach-srv srv1": true, + "tcp-request session attach-srv srv1 name example.com": true, + "tcp-request session attach-srv srv1 name example.com if exceeds_limit": true, "tcp-request content set-bandwidth-limit my-limit": true, "tcp-request content set-bandwidth-limit my-limit limit 1m period 10s": true, "tcp-request content set-bandwidth-limit my-limit period 10s": true, @@ -197,55 +200,59 @@ func TestRequeststcp(t *testing.T) { "tcp-request session sc-inc-gpc": false, "tcp-request session sc-inc-gpc0": false, "tcp-request session sc-inc-gpc1": false, - "tcp-request": false, - "tcp-request content": false, - "tcp-request connection": false, - "tcp-request content do-resolve(txn.myip) capture.req.hdr(0),lower": false, - "tcp-request session": false, - "tcp-request content lua.": false, - "tcp-request content lua. param": false, - "tcp-request connection lua.": false, - "tcp-request connection lua. param": false, - "tcp-request content track-sc0 src table": false, - "tcp-request content track-sc0 src table if some_check": false, - "tcp-request content track-sc1 src table": false, - "tcp-request content track-sc1 src table if some_check": false, - "tcp-request content track-sc2 src table": false, - "tcp-request content track-sc2 src table if some_check": false, - "tcp-request connection track-sc0 src table": false, - "tcp-request connection track-sc0 src table if some_check": false, - "tcp-request connection track-sc1 src table": false, - "tcp-request connection track-sc1 src table if some_check": false, - "tcp-request connection track-sc2 src table": false, - "tcp-request connection track-sc2 src table if some_check": false, - "tcp-request session track-sc0 src table": false, - "tcp-request session track-sc0 src table if some_check": false, - "tcp-request session track-sc1 src table": false, - "tcp-request session track-sc1 src table if some_check": false, - "tcp-request session track-sc2 src table": false, - "tcp-request session track-sc2 src table if some_check": false, - "tcp-request content track-sc5 src table": false, - "tcp-request content track-sc5 src table if some_check": false, - "tcp-request connection track-sc5 src table": false, - "tcp-request connection track-sc5 src table if some_check": false, - "tcp-request session track-sc5 src table": false, - "tcp-request session track-sc5 src table if some_check": false, - "tcp-request content set-bandwidth-limit my-limit limit": false, - "tcp-request content set-bandwidth-limit my-limit period": false, - "tcp-request content set-bandwidth-limit my-limit 10s": false, - "tcp-request content set-bandwidth-limit my-limit period 10s limit": false, - "tcp-request content set-bandwidth-limit my-limit limit period 10s": false, - "tcp-request content set-log-level": false, - "tcp-request connection set-mark": false, - "tcp-request content set-mark": false, - "tcp-request connection set-src-port": false, - "tcp-request content set-src-port": false, - "tcp-request connection set-tos": false, - "tcp-request content set-tos": false, - "tcp-request content set-nice": false, - "tcp-request content switch-mode": false, - "tcp-request content switch-mode tcp": false, - "tcp-request content switch-mode http proto": false, + "tcp-request session attach-srv": false, + "tcp-request session attach-srv srv1 name": false, + "tcp-request session attach-srv srv1 if": false, + "tcp-request session attach-srv srv1 name example.com unless": false, + "tcp-request": false, + "tcp-request content": false, + "tcp-request connection": false, + "tcp-request content do-resolve(txn.myip) capture.req.hdr(0),lower": false, + "tcp-request session": false, + "tcp-request content lua.": false, + "tcp-request content lua. param": false, + "tcp-request connection lua.": false, + "tcp-request connection lua. param": false, + "tcp-request content track-sc0 src table": false, + "tcp-request content track-sc0 src table if some_check": false, + "tcp-request content track-sc1 src table": false, + "tcp-request content track-sc1 src table if some_check": false, + "tcp-request content track-sc2 src table": false, + "tcp-request content track-sc2 src table if some_check": false, + "tcp-request connection track-sc0 src table": false, + "tcp-request connection track-sc0 src table if some_check": false, + "tcp-request connection track-sc1 src table": false, + "tcp-request connection track-sc1 src table if some_check": false, + "tcp-request connection track-sc2 src table": false, + "tcp-request connection track-sc2 src table if some_check": false, + "tcp-request session track-sc0 src table": false, + "tcp-request session track-sc0 src table if some_check": false, + "tcp-request session track-sc1 src table": false, + "tcp-request session track-sc1 src table if some_check": false, + "tcp-request session track-sc2 src table": false, + "tcp-request session track-sc2 src table if some_check": false, + "tcp-request content track-sc5 src table": false, + "tcp-request content track-sc5 src table if some_check": false, + "tcp-request connection track-sc5 src table": false, + "tcp-request connection track-sc5 src table if some_check": false, + "tcp-request session track-sc5 src table": false, + "tcp-request session track-sc5 src table if some_check": false, + "tcp-request content set-bandwidth-limit my-limit limit": false, + "tcp-request content set-bandwidth-limit my-limit period": false, + "tcp-request content set-bandwidth-limit my-limit 10s": false, + "tcp-request content set-bandwidth-limit my-limit period 10s limit": false, + "tcp-request content set-bandwidth-limit my-limit limit period 10s": false, + "tcp-request content set-log-level": false, + "tcp-request connection set-mark": false, + "tcp-request content set-mark": false, + "tcp-request connection set-src-port": false, + "tcp-request content set-src-port": false, + "tcp-request connection set-tos": false, + "tcp-request content set-tos": false, + "tcp-request content set-nice": false, + "tcp-request content switch-mode": false, + "tcp-request content switch-mode tcp": false, + "tcp-request content switch-mode http proto": false, "---": false, "--- ---": false, } diff --git a/types/types-other.go b/types/types-other.go index fd25210..575c0d1 100644 --- a/types/types-other.go +++ b/types/types-other.go @@ -1082,6 +1082,13 @@ type TCPType interface { //test:ok:tcp-request session unset-var(sess.dn) //test:ok:tcp-request session silent-drop //test:ok:tcp-request session silent-drop if !HTTP +//test:ok:tcp-request session attach-srv srv1 +//test:ok:tcp-request session attach-srv srv1 name example.com +//test:ok:tcp-request session attach-srv srv1 name example.com if exceeds_limit +//test:fail:tcp-request session attach-srv +//test:fail:tcp-request session attach-srv srv1 name +//test:fail:tcp-request session attach-srv srv1 if +//test:fail:tcp-request session attach-srv srv1 name example.com unless //test:ok:tcp-request content set-bandwidth-limit my-limit //test:ok:tcp-request content set-bandwidth-limit my-limit limit 1m period 10s //test:ok:tcp-request content set-bandwidth-limit my-limit period 10s