From fba3af8a07e7ae1447659769deff63709c0847e4 Mon Sep 17 00:00:00 2001 From: Helene Durand Date: Wed, 17 Jan 2024 10:27:38 +0100 Subject: [PATCH] TEST: refactor and use json expectation --- configuration/acl.go | 6 +- configuration/backend_switching_rule.go | 12 +- configuration/backend_test.go | 1427 ------- configuration/bind.go | 6 +- configuration/capture.go | 20 +- configuration/configuration.go | 12 + configuration/defaults_test.go | 670 ---- configuration/filter.go | 22 +- configuration/filter_test.go | 249 -- configuration/frontend_test.go | 675 ---- configuration/global_test.go | 840 ---- configuration/http_after_response_rule.go | 20 +- .../http_after_response_rule_test.go | 336 -- configuration/http_check.go | 20 +- configuration/http_check_test.go | 381 -- configuration/http_error_rule.go | 30 +- configuration/http_error_rule_test.go | 345 -- configuration/http_request_rule.go | 20 +- configuration/http_request_rule_test.go | 985 ----- configuration/http_response_rule.go | 20 +- configuration/http_response_rule_test.go | 766 ---- configuration/log_target.go | 12 +- configuration/nameserver.go | 14 +- configuration/peer_entry.go | 14 +- configuration/server.go | 10 +- configuration/server_switching_rule.go | 12 +- configuration/server_template.go | 14 +- configuration/server_test.go | 468 --- configuration/service.go | 28 +- configuration/site.go | 22 +- configuration/stick_rule.go | 12 +- configuration/table.go | 10 +- configuration/tcp_check.go | 20 +- configuration/tcp_request_rule.go | 20 +- configuration/tcp_request_rule_test.go | 961 ----- configuration/tcp_response_rule.go | 12 +- configuration/tcp_response_rule_test.go | 472 --- {configuration => test}/acl_test.go | 156 +- .../backend_switching_rule_test.go | 80 +- test/backend_test.go | 860 +++++ {configuration => test}/bind_test.go | 123 +- {configuration => test}/cache_test.go | 90 +- {configuration => test}/capture_test.go | 41 +- {configuration => test}/configuration_test.go | 39 +- test/convert.go | 422 +++ test/defaults_test.go | 363 ++ {configuration => test}/dgram_bind_test.go | 70 +- test/expected/structured.json | 3364 +++++++++++++++++ {configuration => test}/fcgi_app_test.go | 122 +- test/filter_test.go | 192 + test/frontend_test.go | 297 ++ test/global_test.go | 190 + {configuration => test}/group_test.go | 89 +- {configuration => test}/helpers.go | 2 +- test/http_after_response_rule_test.go | 130 + test/http_check_test.go | 238 ++ test/http_error_rule_test.go | 251 ++ .../http_errors_section_test.go | 74 +- test/http_request_rule_test.go | 276 ++ test/http_response_rule_test.go | 258 ++ {configuration => test}/log_forward_test.go | 62 +- {configuration => test}/log_target_test.go | 137 +- {configuration => test}/mailer_entry_test.go | 57 +- .../mailers_section_test.go | 67 +- {configuration => test}/nameserver_test.go | 72 +- {configuration => test}/peer_entry_test.go | 72 +- {configuration => test}/peer_section_test.go | 105 +- {configuration => test}/program_test.go | 43 +- {configuration => test}/resolver_test.go | 67 +- {configuration => test}/ring_test.go | 73 +- .../server_switching_rule_test.go | 83 +- .../server_template_test.go | 134 +- test/server_test.go | 322 ++ {configuration => test}/service_test.go | 69 +- {configuration => test}/site_test.go | 2 +- {configuration => test}/stick_rule_test.go | 128 +- {configuration => test}/table_test.go | 2 +- {configuration => test}/tcp_check_test.go | 85 +- test/tcp_request_rule_test.go | 412 ++ test/tcp_response_rule_test.go | 190 + {configuration => test}/user_test.go | 114 +- {configuration => test}/userlist_test.go | 2 +- {configuration => test}/version_test.go | 2 +- 83 files changed, 9172 insertions(+), 9818 deletions(-) delete mode 100644 configuration/backend_test.go delete mode 100644 configuration/defaults_test.go delete mode 100644 configuration/filter_test.go delete mode 100644 configuration/frontend_test.go delete mode 100644 configuration/global_test.go delete mode 100644 configuration/http_after_response_rule_test.go delete mode 100644 configuration/http_check_test.go delete mode 100644 configuration/http_error_rule_test.go delete mode 100644 configuration/http_request_rule_test.go delete mode 100644 configuration/http_response_rule_test.go delete mode 100644 configuration/server_test.go delete mode 100644 configuration/tcp_request_rule_test.go delete mode 100644 configuration/tcp_response_rule_test.go rename {configuration => test}/acl_test.go (51%) rename {configuration => test}/backend_switching_rule_test.go (75%) create mode 100644 test/backend_test.go rename {configuration => test}/bind_test.go (56%) rename {configuration => test}/cache_test.go (71%) rename {configuration => test}/capture_test.go (85%) rename {configuration => test}/configuration_test.go (96%) create mode 100644 test/convert.go create mode 100644 test/defaults_test.go rename {configuration => test}/dgram_bind_test.go (77%) create mode 100644 test/expected/structured.json rename {configuration => test}/fcgi_app_test.go (54%) create mode 100644 test/filter_test.go create mode 100644 test/frontend_test.go create mode 100644 test/global_test.go rename {configuration => test}/group_test.go (81%) rename {configuration => test}/helpers.go (96%) create mode 100644 test/http_after_response_rule_test.go create mode 100644 test/http_check_test.go create mode 100644 test/http_error_rule_test.go rename {configuration => test}/http_errors_section_test.go (84%) create mode 100644 test/http_request_rule_test.go create mode 100644 test/http_response_rule_test.go rename {configuration => test}/log_forward_test.go (71%) rename {configuration => test}/log_target_test.go (51%) rename {configuration => test}/mailer_entry_test.go (72%) rename {configuration => test}/mailers_section_test.go (72%) rename {configuration => test}/nameserver_test.go (77%) rename {configuration => test}/peer_entry_test.go (78%) rename {configuration => test}/peer_section_test.go (60%) rename {configuration => test}/program_test.go (73%) rename {configuration => test}/resolver_test.go (71%) rename {configuration => test}/ring_test.go (73%) rename {configuration => test}/server_switching_rule_test.go (74%) rename {configuration => test}/server_template_test.go (63%) create mode 100644 test/server_test.go rename {configuration => test}/service_test.go (84%) rename {configuration => test}/site_test.go (99%) rename {configuration => test}/stick_rule_test.go (57%) rename {configuration => test}/table_test.go (99%) rename {configuration => test}/tcp_check_test.go (78%) create mode 100644 test/tcp_request_rule_test.go create mode 100644 test/tcp_response_rule_test.go rename {configuration => test}/user_test.go (73%) rename {configuration => test}/userlist_test.go (99%) rename {configuration => test}/version_test.go (99%) diff --git a/configuration/acl.go b/configuration/acl.go index 1f0649e4..4a76e29b 100644 --- a/configuration/acl.go +++ b/configuration/acl.go @@ -140,11 +140,11 @@ func (c *client) CreateACL(parentType string, parentName string, data *models.AC func (c *client) getACLParserFromParent(parent string) (parser.Section, error) { switch parent { - case "backend": + case BackendParentName: return parser.Backends, nil - case "frontend": + case FrontendParentName: return parser.Frontends, nil - case "fcgi-app": + case FCGIAppParentName: return parser.FCGIApp, nil default: return "", fmt.Errorf("unsupported parent: %s", parent) diff --git a/configuration/backend_switching_rule.go b/configuration/backend_switching_rule.go index e1db99cd..547672de 100644 --- a/configuration/backend_switching_rule.go +++ b/configuration/backend_switching_rule.go @@ -43,7 +43,7 @@ func (c *client) GetBackendSwitchingRules(frontend string, transactionID string) bckRules, err := ParseBackendSwitchingRules(frontend, p) if err != nil { - return v, nil, c.HandleError("", "frontend", frontend, "", false, err) + return v, nil, c.HandleError("", FrontendParentName, frontend, "", false, err) } return v, bckRules, nil @@ -64,7 +64,7 @@ func (c *client) GetBackendSwitchingRule(id int64, frontend string, transactionI data, err := p.GetOne(parser.Frontends, frontend, "use_backend", int(id)) if err != nil { - return v, nil, c.HandleError(strconv.FormatInt(id, 10), "frontend", frontend, "", false, err) + return v, nil, c.HandleError(strconv.FormatInt(id, 10), FrontendParentName, frontend, "", false, err) } bckRule := ParseBackendSwitchingRule(data.(types.UseBackend)) @@ -82,7 +82,7 @@ func (c *client) DeleteBackendSwitchingRule(id int64, frontend string, transacti } if err := p.Delete(parser.Frontends, frontend, "use_backend", int(id)); err != nil { - return c.HandleError(strconv.FormatInt(id, 10), "frontend", frontend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(id, 10), FrontendParentName, frontend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -104,7 +104,7 @@ func (c *client) CreateBackendSwitchingRule(frontend string, data *models.Backen } if err := p.Insert(parser.Frontends, frontend, "use_backend", SerializeBackendSwitchingRule(*data), int(*data.Index)); err != nil { - return c.HandleError(strconv.FormatInt(*data.Index, 10), "frontend", frontend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(*data.Index, 10), FrontendParentName, frontend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -125,11 +125,11 @@ func (c *client) EditBackendSwitchingRule(id int64, frontend string, data *model } if _, err := p.GetOne(parser.Frontends, frontend, "use_backend", int(id)); err != nil { - return c.HandleError(strconv.FormatInt(id, 10), "frontend", frontend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(id, 10), FrontendParentName, frontend, t, transactionID == "", err) } if err := p.Set(parser.Frontends, frontend, "use_backend", SerializeBackendSwitchingRule(*data), int(id)); err != nil { - return c.HandleError(strconv.FormatInt(id, 10), "frontend", frontend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(id, 10), FrontendParentName, frontend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") diff --git a/configuration/backend_test.go b/configuration/backend_test.go deleted file mode 100644 index fd864eee..00000000 --- a/configuration/backend_test.go +++ /dev/null @@ -1,1427 +0,0 @@ -// 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. -// - -package configuration - -import ( - "fmt" - "reflect" - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/haproxytech/client-native/v5/misc" - "github.com/haproxytech/client-native/v5/models" -) - -func TestGetBackends(t *testing.T) { //nolint:gocognit,gocyclo - v, backends, err := clientTest.GetBackends("") - if err != nil { - t.Error(err.Error()) - } - - if len(backends) != 2 { - t.Errorf("%v backends returned, expected 2", len(backends)) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - for _, b := range backends { - if b.Name != "test" && b.Name != "test_2" { - t.Errorf("Expected only test or test_2 backend, %v found", b.Name) - } - optionValue := "disabled" - if b.Name == "test" { - optionValue = "enabled" - } - if b.Name == "test_2" { - if b.From != "test_defaults_2" { - t.Errorf("%v: From not test_defaults_2: %v", b.Name, b.From) - } - } - if b.BindProcess != "all" { - t.Errorf("%v: BindProcess not all: %v", b.Name, b.BindProcess) - } - if b.AdvCheck != "httpchk" { - t.Errorf("%v: AdvCheck.Method not HEAD: %v", b.Name, b.AdvCheck) - } - if b.HttpchkParams.Method != "HEAD" { - t.Errorf("%v: HttpchkParams.Method not HEAD: %v", b.Name, b.HttpchkParams.Method) - } - if b.HttpchkParams.URI != "/" { - t.Errorf("%v: HttpchkParams.URI not HEAD: %v", b.Name, b.HttpchkParams.URI) - } - if b.Mode != "http" { - t.Errorf("%v: Mode not http: %v", b.Name, b.Mode) - } - if *b.Balance.Algorithm != "roundrobin" { - t.Errorf("%v: Balance.Algorithm not roundrobin: %v", b.Name, b.Balance.Algorithm) - } - if b.HashType.Method != "consistent" { - t.Errorf("%v: HashType.Method not consistent: %v", b.Name, b.HashType.Method) - } - if b.HashType.Function != "sdbm" { - t.Errorf("%v: HashType.Function not sdbm: %v", b.Name, b.HashType.Function) - } - if b.HashType.Modifier != "avalanche" { - t.Errorf("%v: HashType.Modifier not avalanche: %v", b.Name, b.HashType.Modifier) - } - if b.HTTPConnectionMode != "http-keep-alive" { - t.Errorf("%v: HTTPConnectionMode not http-keep-alive: %v", b.Name, b.HTTPConnectionMode) - } - if *b.Forwardfor.Enabled != "enabled" { - t.Errorf("%v: Forwardfor not enabled: %v", b.Name, b.Forwardfor) - } - if *b.DefaultServer.Fall != 2000 { - t.Errorf("%v: DefaultServer.Fall not 2000: %v", b.Name, *b.DefaultServer.Fall) - } - if *b.DefaultServer.Rise != 4000 { - t.Errorf("%v: DefaultServer.Rise not 4000: %v", b.Name, *b.DefaultServer.Rise) - } - if *b.DefaultServer.Inter != 5000 { - t.Errorf("%v: DefaultServer.Inter not 5000: %v", b.Name, *b.DefaultServer.Inter) - } - if *b.DefaultServer.HealthCheckPort != 8888 { - t.Errorf("%v: DefaultServer.HealthCheckPort not 8888: %v", b.Name, *b.DefaultServer.HealthCheckPort) - } - if *b.Cookie.Name != "BLA" { - t.Errorf("%v: HTTPCookie Name not BLA: %v", b.Name, b.Cookie) - } - if b.Cookie.Type != "rewrite" { - t.Errorf("%v: HTTPCookie Type not rewrite %v", b.Name, b.Cookie.Type) - } - if !b.Cookie.Httponly { - t.Errorf("%v: HTTPCookie Httponly not true %v", b.Name, b.Cookie.Httponly) - } - if !b.Cookie.Nocache { - t.Errorf("%v: HTTPCookie Nocache not false %v", b.Name, b.Cookie.Nocache) - } - if *b.CheckTimeout != 2000 { - t.Errorf("%v: CheckTimeout not 2000: %v", b.Name, *b.CheckTimeout) - } - if *b.ServerTimeout != 3000 { - t.Errorf("%v: ServerTimeout not 3000: %v", b.Name, *b.ServerTimeout) - } - if b.Tcpka != "enabled" { - t.Errorf("%v: Tcpka not enabled: %v", b.Name, b.Tcpka) - } - if b.Srvtcpka != "enabled" { - t.Errorf("%v: Srvtcpka not enabled: %v", b.Name, b.Srvtcpka) - } - if b.Checkcache != optionValue { - t.Errorf("%v: Checkcache not %s: %v", b.Name, optionValue, b.Checkcache) - } - if b.IndependentStreams != optionValue { - t.Errorf("%v: IndependentStreams not %s: %v", b.Name, optionValue, b.IndependentStreams) - } - if b.Nolinger != optionValue { - t.Errorf("%v: Nolinger not %s: %v", b.Name, optionValue, b.Nolinger) - } - if b.Originalto == nil { - t.Errorf("%v: Originalto is nil, expected not nil", b.Name) - } else { - if *b.Originalto.Enabled != "enabled" { - t.Errorf("%v: Originalto.Enabled is not enabled: %v", b.Name, *b.Originalto.Enabled) - } - if b.Name == "test" && b.Originalto.Except != "" { - t.Errorf("%v: Originalto.Except is not empty: %v", b.Name, b.Originalto.Except) - } - if b.Name == "test_2" && b.Originalto.Except != "127.0.0.1" { - t.Errorf("%v: Originalto.Except is not 127.0.0.1: %v", b.Name, b.Originalto.Except) - } - if b.Originalto.Header != "X-Client-Dst" { - t.Errorf("%v: Originalto.Header is not X-Client-Dst: %v", b.Name, b.Originalto.Header) - } - } - if b.Persist != optionValue { - t.Errorf("%v: Persist not %s: %v", b.Name, optionValue, b.Persist) - } - if b.PreferLastServer != optionValue { - t.Errorf("%v: PreferLastServer not %s: %v", b.Name, optionValue, b.PreferLastServer) - } - if b.SpopCheck != optionValue { - t.Errorf("%v: SpopCheck not %s: %v", b.Name, optionValue, b.SpopCheck) - } - if b.TCPSmartConnect != optionValue { - t.Errorf("%v: TCPSmartConnect not %s: %v", b.Name, optionValue, b.TCPSmartConnect) - } - if b.Transparent != optionValue { - t.Errorf("%v: Transparent not %s: %v", b.Name, optionValue, b.Transparent) - } - if b.SpliceAuto != optionValue { - t.Errorf("%v: SpliceAuto not %s: %v", b.Name, optionValue, b.SpliceAuto) - } - if b.SpliceRequest != optionValue { - t.Errorf("%v: SpliceRequest not %s: %v", b.Name, optionValue, b.SpliceRequest) - } - if b.SpliceResponse != optionValue { - t.Errorf("%v: SpliceResponse not %s: %v", b.Name, optionValue, b.SpliceResponse) - } - if b.SrvtcpkaCnt == nil { - t.Errorf("%v: SrvtcpkaCnt is nil", b.Name) - } else if *b.SrvtcpkaCnt != 10 { - t.Errorf("%v: SrvtcpkaCnt not 10: %v", b.Name, *b.SrvtcpkaCnt) - } - if b.SrvtcpkaIdle == nil { - t.Errorf("%v: SrvtcpkaIdle is nil", b.Name) - } else if *b.SrvtcpkaIdle != 10000 { - t.Errorf("%v: SrvtcpkaIdle not 10000: %v", b.Name, *b.SrvtcpkaIdle) - } - if b.SrvtcpkaIntvl == nil { - t.Errorf("%v: SrvtcpkaIntvl is nil", b.Name) - } else if *b.SrvtcpkaIntvl != 10000 { - t.Errorf("%v: SrvtcpkaIntvl not 10000: %v", b.Name, *b.SrvtcpkaIntvl) - } - if b.StatsOptions == nil { - t.Errorf("%v: StatsOptions is nil", b.Name) - } - if b.StatsOptions.StatsShowModules != true { - t.Error("StatsShowModules not set") - } - if b.StatsOptions.StatsRealm != true { - t.Error("StatsRealm not set") - } - if b.StatsOptions.StatsRealmRealm == nil { - t.Errorf("%v: StatsRealmRealm is nil", b.Name) - } else if *b.StatsOptions.StatsRealmRealm != `HAProxy\\ Statistics` { - t.Errorf("%v: StatsRealmRealm not 'HAProxy Statistics': %v", b.Name, *b.StatsOptions.StatsRealmRealm) - } - if len(b.StatsOptions.StatsAuths) != 2 { - t.Errorf("%v: StatsAuths expected 2 instances got: %v", b.Name, len(b.StatsOptions.StatsAuths)) - } - if b.StatsOptions.StatsAuths[0].User == nil { - t.Errorf("%v: StatsAuths 0 User is nil", b.Name) - } else if *b.StatsOptions.StatsAuths[0].User != "admin" { - t.Errorf("%v: StatsAuths 0 User not admin: %v", b.Name, *b.StatsOptions.StatsAuths[0]) - } - if b.StatsOptions.StatsAuths[0].Passwd == nil { - t.Errorf("%v: StatsAuths 0 Passwd is nil", b.Name) - } else if *b.StatsOptions.StatsAuths[0].Passwd != "AdMiN123" { - t.Errorf("%v: StatsAuths 0 Passwd not AdMiN123: %v", b.Name, *b.StatsOptions.StatsAuths[0].Passwd) - } - if b.StatsOptions.StatsAuths[1].User == nil { - t.Errorf("%v: StatsAuths 1 User is nil", b.Name) - } else if *b.StatsOptions.StatsAuths[1].User != "admin2" { - t.Errorf("%v: StatsAuths 1 User not admin2: %v", b.Name, *b.StatsOptions.StatsAuths[1].User) - } - if b.StatsOptions.StatsAuths[1].Passwd == nil { - t.Errorf("%v: StatsAuths 1 Passwd is nil", b.Name) - } else if *b.StatsOptions.StatsAuths[1].Passwd != "AdMiN1234" { - t.Errorf("%v: StatsAuths 1 Passwd not AdMiN1234: %v", b.Name, *b.StatsOptions.StatsAuths[1].Passwd) - } - if len(b.StatsOptions.StatsHTTPRequests) != 2 { - t.Errorf("%v: StatsHTTPRequests expected 2 instances got: %v", b.Name, len(b.StatsOptions.StatsHTTPRequests)) - } - if b.StatsOptions.StatsHTTPRequests[0].Type == nil { - t.Errorf("%v: StatsHTTPRequests 0 Type is nil", b.Name) - } else if *b.StatsOptions.StatsHTTPRequests[0].Type != "auth" { - t.Errorf("%v: StatsHTTPRequests 0 Type not auth: %v", b.Name, *b.StatsOptions.StatsHTTPRequests[0].Type) - } - if b.StatsOptions.StatsHTTPRequests[0].Realm != `HAProxy\\ Statistics` { - t.Errorf("%v: StatsHTTPRequests 0 Realm not 'HAProxy Statistics': %v", b.Name, b.StatsOptions.StatsHTTPRequests[0].Realm) - } - if b.StatsOptions.StatsHTTPRequests[1].Type == nil { - t.Errorf("%v: StatsHTTPRequests 1 Type is nil", b.Name) - } else if *b.StatsOptions.StatsHTTPRequests[1].Type != "allow" { - t.Errorf("%v: StatsHTTPRequests 1 Type not allow: %v", b.Name, *b.StatsOptions.StatsHTTPRequests[1].Type) - } - if b.StatsOptions.StatsHTTPRequests[1].Cond != "if" { - t.Errorf("%v: StatsHTTPRequests 1 Cond not if: %v", b.Name, b.StatsOptions.StatsHTTPRequests[1].Cond) - } - if b.StatsOptions.StatsHTTPRequests[1].CondTest != "something" { - t.Errorf("%v: StatsHTTPRequests 1 CondTest not something: %v", b.Name, b.StatsOptions.StatsHTTPRequests[1].CondTest) - } - - if b.EmailAlert == nil { - t.Error("EmailAlert is nil") - } else if *b.EmailAlert.From != "prod01@example.com" { - t.Errorf("EmailAlert.From is not prod01@example.com: %v", *b.EmailAlert.From) - } else if *b.EmailAlert.To != "sre@example.com" { - t.Errorf("EmailAlert.To is not sre@example.com: %v", *b.EmailAlert.To) - } else if b.EmailAlert.Level != "warning" { - t.Errorf("EmailAlert.Level is not warning: %v", b.EmailAlert.Level) - } else if b.EmailAlert.Myhostname != "prod01" { - t.Errorf("EmailAlert.Myhostname is not prod01: %v", b.EmailAlert.Myhostname) - } else if *b.EmailAlert.Mailers != "localmailer1" { - t.Errorf("EmailAlert.Mailers is not localmailer1: %v", *b.EmailAlert.Mailers) - } - - if b.Name == "test" && (b.DefaultServer.LogBufsize == nil || *b.DefaultServer.LogBufsize != 6) { - t.Errorf("%v: DefaultServer.LogBufsize not 6: %v", b.Name, b.DefaultServer.LogBufsize) - } - if b.Name == "test2" && b.DefaultServer.LogBufsize != nil { - t.Errorf("%v: DefaultServer.LogBufsize should be nil: %v", b.Name, b.DefaultServer.LogBufsize) - } - } -} - -func TestGetBackend(t *testing.T) { - v, b, err := clientTest.GetBackend("test", "") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - if b.Name != "test" { - t.Errorf("Expected only test, %v found", b.Name) - } - if b.BindProcess != "all" { - t.Errorf("%v: BindProcess not all: %v", b.Name, b.BindProcess) - } - if b.AdvCheck != "httpchk" { - t.Errorf("%v: AdvCheck.Method not HEAD: %v", b.Name, b.AdvCheck) - } - if b.HttpchkParams.Method != "HEAD" { - t.Errorf("%v: HttpchkParams.Method not HEAD: %v", b.Name, b.HttpchkParams.Method) - } - if b.HttpchkParams.URI != "/" { - t.Errorf("%v: HttpchkParams.URI not HEAD: %v", b.Name, b.HttpchkParams.URI) - } - if b.Mode != "http" { - t.Errorf("%v: Mode not http: %v", b.Name, b.Mode) - } - if *b.Balance.Algorithm != "roundrobin" { - t.Errorf("%v: Balance.Algorithm not roundrobin: %v", b.Name, b.Balance.Algorithm) - } - if b.HashType.Method != "consistent" { - t.Errorf("%v: HashType.Method not consistent: %v", b.Name, b.HashType.Method) - } - if b.HashType.Function != "sdbm" { - t.Errorf("%v: HashType.Function not sdbm: %v", b.Name, b.HashType.Function) - } - if b.HashType.Modifier != "avalanche" { - t.Errorf("%v: HashType.Modifier not avalanche: %v", b.Name, b.HashType.Modifier) - } - if b.HTTPConnectionMode != "http-keep-alive" { - t.Errorf("%v: HTTPConnectionMode not http-keep-alive: %v", b.Name, b.HTTPConnectionMode) - } - if b.HTTPRestrictReqHdrNames != "preserve" { - t.Errorf("%v: HTTPRestrictReqHdrNames not delete: %v", b.Name, b.HTTPRestrictReqHdrNames) - } - if *b.Forwardfor.Enabled != "enabled" { - t.Errorf("%v: Forwardfor not enabled: %v", b.Name, b.Forwardfor) - } - if *b.DefaultServer.Fall != 2000 { - t.Errorf("%v: DefaultServer.Fall not 2000: %v", b.Name, *b.DefaultServer) - } - if *b.DefaultServer.Rise != 4000 { - t.Errorf("%v: DefaultServer.Rise not 4000: %v", b.Name, *b.DefaultServer.Rise) - } - if *b.DefaultServer.Inter != 5000 { - t.Errorf("%v: DefaultServer.Inter not 5000: %v", b.Name, *b.DefaultServer.Inter) - } - if *b.DefaultServer.HealthCheckPort != 8888 { - t.Errorf("%v: DefaultServer.HealthCheckPort not 8888: %v", b.Name, *b.DefaultServer.HealthCheckPort) - } - if b.Name == "test" && (b.DefaultServer.LogBufsize == nil || *b.DefaultServer.LogBufsize != 6) { - t.Errorf("%v: DefaultServer.LogBufsize not 6: %v", b.Name, b.DefaultServer.LogBufsize) - } - if *b.Cookie.Name != "BLA" { - t.Errorf("%v: HTTPCookie Name not BLA: %v", b.Name, b.Cookie) - } - if b.Cookie.Type != "rewrite" { - t.Errorf("%v: HTTPCookie Type not rewrite %v", b.Name, b.Cookie.Type) - } - if !b.Cookie.Httponly { - t.Errorf("%v: HTTPCookie Httponly not true %v", b.Name, b.Cookie.Httponly) - } - if !b.Cookie.Nocache { - t.Errorf("%v: HTTPCookie Nocache not false %v", b.Name, b.Cookie.Nocache) - } - if *b.CheckTimeout != 2000 { - t.Errorf("%v: CheckTimeout not 2000: %v", b.Name, *b.CheckTimeout) - } - if *b.ServerTimeout != 3000 { - t.Errorf("%v: ServerTimeout not 3000: %v", b.Name, *b.ServerTimeout) - } - if *b.ServerFinTimeout != 1000 { - t.Errorf("%v: ServerFinTimeout not 1000: %v", b.Name, *b.ServerFinTimeout) - } - if *b.TarpitTimeout != 2000 { - t.Errorf("%v: TarpitTimeout not 2000: %v", b.Name, *b.TarpitTimeout) - } - if b.AcceptInvalidHTTPResponse != "disabled" { - t.Errorf("%v: AcceptInvalidHTTPResponse not disabled: %v", b.Name, b.AcceptInvalidHTTPResponse) - } - if b.H1CaseAdjustBogusServer != "disabled" { - t.Errorf("%v: H1CaseAdjustBogusServer not disabled: %v", b.Name, b.H1CaseAdjustBogusServer) - } - if b.Tcpka != "enabled" { - t.Errorf("%v: Tcpka not enabled: %v", b.Name, b.Tcpka) - } - if b.Srvtcpka != "enabled" { - t.Errorf("%v: Srvtcpka not enabled: %v", b.Name, b.Srvtcpka) - } - if b.Compression == nil { - t.Errorf("%v: Compression is nil", b.Name) - } else { - if len(b.Compression.Types) != 2 { - t.Errorf("%v: len Compression.Types not 2: %v", b.Name, len(b.Compression.Types)) - } else { - if !(b.Compression.Types[0] == "application/json" || b.Compression.Types[0] != "text/plain") { - t.Errorf("%v: Compression.Types[0] wrong: %v", b.Name, b.Compression.Types[0]) - } - if !(b.Compression.Types[1] != "application/json" || b.Compression.Types[0] != "text/plain") { - t.Errorf("%v: Compression.Types[1] wrong: %v", b.Name, b.Compression.Types[1]) - } - } - } - if b.Checkcache != "enabled" { - t.Errorf("%v: Checkcache not enabled: %v", b.Name, b.Checkcache) - } - if b.IndependentStreams != "enabled" { - t.Errorf("%v: IndependentStreams not enabled: %v", b.Name, b.IndependentStreams) - } - if b.Nolinger != "enabled" { - t.Errorf("%v: Nolinger not enabled: %v", b.Name, b.Nolinger) - } - if b.Originalto == nil { - t.Errorf("%v: Originalto is nil, expected not nil", b.Name) - } else { - if *b.Originalto.Enabled != "enabled" { - t.Errorf("%v: Originalto.Enabled is not enabled: %v", b.Name, *b.Originalto.Enabled) - } - if b.Originalto.Except != "" { - t.Errorf("%v: Originalto.Except is not empty: %v", b.Name, b.Originalto.Except) - } - if b.Originalto.Header != "X-Client-Dst" { - t.Errorf("%v: Originalto.Header is not X-Client-Dst: %v", b.Name, b.Originalto.Header) - } - } - if b.Persist != "enabled" { - t.Errorf("%v: Persist not enabled: %v", b.Name, b.Persist) - } - if b.PreferLastServer != "enabled" { - t.Errorf("%v: PreferLastServer not enabled: %v", b.Name, b.PreferLastServer) - } - if b.SpopCheck != "enabled" { - t.Errorf("%v: SpopCheck not enabled: %v", b.Name, b.SpopCheck) - } - if b.TCPSmartConnect != "enabled" { - t.Errorf("%v: TCPSmartConnect not enabled: %v", b.Name, b.TCPSmartConnect) - } - if b.Transparent != "enabled" { - t.Errorf("%v: Transparent not enabled: %v", b.Name, b.Transparent) - } - if b.SpliceAuto != "enabled" { - t.Errorf("%v: SpliceAuto not enabled: %v", b.Name, b.SpliceAuto) - } - if b.SpliceRequest != "enabled" { - t.Errorf("%v: SpliceRequest not enabled: %v", b.Name, b.SpliceRequest) - } - if b.SpliceResponse != "enabled" { - t.Errorf("%v: SpliceResponse not enabled: %v", b.Name, b.SpliceResponse) - } - if b.SrvtcpkaCnt == nil { - t.Errorf("%v: SrvtcpkaCnt is nil", b.Name) - } else if *b.SrvtcpkaCnt != 10 { - t.Errorf("%v: SrvtcpkaCnt not 10: %v", b.Name, *b.SrvtcpkaCnt) - } - if b.SrvtcpkaIdle == nil { - t.Errorf("%v: SrvtcpkaIdle is nil", b.Name) - } else if *b.SrvtcpkaIdle != 10000 { - t.Errorf("%v: SrvtcpkaIdle not 10000: %v", b.Name, *b.SrvtcpkaIdle) - } - if b.SrvtcpkaIntvl == nil { - t.Errorf("%v: SrvtcpkaIntvl is nil", b.Name) - } else if *b.SrvtcpkaIntvl != 10000 { - t.Errorf("%v: SrvtcpkaIntvl not 10000: %v", b.Name, *b.SrvtcpkaIntvl) - } - if b.StatsOptions == nil { - t.Errorf("%v: StatsOptions is nil", b.Name) - } - if b.StatsOptions.StatsShowModules != true { - t.Error("StatsShowModules not set") - } - if b.StatsOptions.StatsRealm != true { - t.Error("StatsRealm not set") - } - if b.StatsOptions.StatsRealmRealm == nil { - t.Errorf("%v: StatsRealmRealm is nil", b.Name) - } else if *b.StatsOptions.StatsRealmRealm != `HAProxy\\ Statistics` { - t.Errorf("%v: StatsRealmRealm not 'HAProxy Statistics': %v", b.Name, *b.StatsOptions.StatsRealmRealm) - } - if len(b.StatsOptions.StatsAuths) != 2 { - t.Errorf("%v: StatsAuths expected 2 instances got: %v", b.Name, len(b.StatsOptions.StatsAuths)) - } - if b.StatsOptions.StatsAuths[0].User == nil { - t.Errorf("%v: StatsAuths 0 User is nil", b.Name) - } else if *b.StatsOptions.StatsAuths[0].User != "admin" { - t.Errorf("%v: StatsAuths 0 User not admin: %v", b.Name, *b.StatsOptions.StatsAuths[0]) - } - if b.StatsOptions.StatsAuths[0].Passwd == nil { - t.Errorf("%v: StatsAuths 0 Passwd is nil", b.Name) - } else if *b.StatsOptions.StatsAuths[0].Passwd != "AdMiN123" { - t.Errorf("%v: StatsAuths 0 Passwd not AdMiN123: %v", b.Name, *b.StatsOptions.StatsAuths[0].Passwd) - } - if b.StatsOptions.StatsAuths[1].User == nil { - t.Errorf("%v: StatsAuths 1 User is nil", b.Name) - } else if *b.StatsOptions.StatsAuths[1].User != "admin2" { - t.Errorf("%v: StatsAuths 1 User not admin2: %v", b.Name, *b.StatsOptions.StatsAuths[1].User) - } - if b.StatsOptions.StatsAuths[1].Passwd == nil { - t.Errorf("%v: StatsAuths 1 Passwd is nil", b.Name) - } else if *b.StatsOptions.StatsAuths[1].Passwd != "AdMiN1234" { - t.Errorf("%v: StatsAuths 1 Passwd not AdMiN1234: %v", b.Name, *b.StatsOptions.StatsAuths[1].Passwd) - } - if len(b.StatsOptions.StatsHTTPRequests) != 2 { - t.Errorf("%v: StatsHTTPRequests expected 2 instances got: %v", b.Name, len(b.StatsOptions.StatsHTTPRequests)) - } - if b.StatsOptions.StatsHTTPRequests[0].Type == nil { - t.Errorf("%v: StatsHTTPRequests 0 Type is nil", b.Name) - } else if *b.StatsOptions.StatsHTTPRequests[0].Type != "auth" { - t.Errorf("%v: StatsHTTPRequests 0 Type not auth: %v", b.Name, *b.StatsOptions.StatsHTTPRequests[0].Type) - } - if b.StatsOptions.StatsHTTPRequests[0].Realm != `HAProxy\\ Statistics` { - t.Errorf("%v: StatsHTTPRequests 0 Realm not 'HAProxy Statistics': %v", b.Name, b.StatsOptions.StatsHTTPRequests[0].Realm) - } - if b.StatsOptions.StatsHTTPRequests[1].Type == nil { - t.Errorf("%v: StatsHTTPRequests 1 Type is nil", b.Name) - } else if *b.StatsOptions.StatsHTTPRequests[1].Type != "allow" { - t.Errorf("%v: StatsHTTPRequests 1 Type not allow: %v", b.Name, *b.StatsOptions.StatsHTTPRequests[1].Type) - } - if b.StatsOptions.StatsHTTPRequests[1].Cond != "if" { - t.Errorf("%v: StatsHTTPRequests 1 Cond not if: %v", b.Name, b.StatsOptions.StatsHTTPRequests[1].Cond) - } - if b.StatsOptions.StatsHTTPRequests[1].CondTest != "something" { - t.Errorf("%v: StatsHTTPRequests 1 CondTest not something: %v", b.Name, b.StatsOptions.StatsHTTPRequests[1].CondTest) - } - if b.LoadServerStateFromFile != "local" { - t.Errorf("%v: LoadServerStateFromFile not global: %v", b.Name, b.LoadServerStateFromFile) - } - if b.ServerStateFileName != "use-backend-name" { - t.Errorf("%v: ServerStateFileName not: %v", b.Name, b.ServerStateFileName) - } - if b.Description != "this is a backend description" { - t.Errorf("%v: Description not `this is a backend description`: %v", b.Name, b.Description) - } - if b.UseFCGIApp != "app-name" { - t.Errorf("%v: UseFcgiApp not app-name: %v", b.Name, b.UseFCGIApp) - } - if !b.Enabled { - t.Errorf("%v: Enabled not enabled", b.Name) - } - if *b.ID != 456 { - t.Errorf("ID not 456: %v", *b.ID) - } - if *b.Errorloc302.Code != 404 { - t.Errorf("%v: Errorloc302 Code not 404: %v", b.Name, *b.Errorloc302.Code) - } - if *b.Errorloc302.URL != "http://www.myawesomesite.com/not_found" { - t.Errorf("%v: Errorloc302 Code not http://www.myawesomesite.com/not_found: %v", b.Name, *b.Errorloc302.URL) - } - if *b.Errorloc303.Code != 404 { - t.Errorf("%v: Errorloc302 Code not 404: %v", b.Name, *b.Errorloc303.Code) - } - if *b.Errorloc303.URL != "http://www.myawesomesite.com/not_found" { - t.Errorf("%v: Errorloc302 Code not http://www.myawesomesite.com/not_found: %v", b.Name, *b.Errorloc303.URL) - } - if len(b.ErrorFiles) != 3 { - t.Errorf("ErrorFiles not 3: %v", len(b.ErrorFiles)) - } else { - for _, ef := range b.ErrorFiles { - if ef.Code == 403 { - if ef.File != "/test/403.html" { - t.Errorf("File for %v not 403: %v", ef.Code, ef.File) - } - } - if ef.Code == 500 { - if ef.File != "/test/500.html" { - t.Errorf("File for %v not 500: %v", ef.Code, ef.File) - } - } - if ef.Code == 429 { - if ef.File != "/test/429.html" { - t.Errorf("File for %v not 429: %v", ef.Code, ef.File) - } - } - } - } - if len(b.ErrorFilesFromHTTPErrors) != 3 { - t.Errorf("ErrorFilesFromHTTPErrors not 3: %v", len(b.ErrorFilesFromHTTPErrors)) - } else { - for _, ef := range b.ErrorFilesFromHTTPErrors { - if ef.Name == "my_errors" { - if len(ef.Codes) != 3 { - t.Errorf("ErrorFilesFromHTTPErrors Codes not 3 for errofiles name %s: %v", ef.Name, len(ef.Codes)) - } - if ef.Codes[0] != 404 { - t.Errorf("Codes[0] not 404 for errofiles name %s: %v", ef.Name, ef.Codes[0]) - } - if ef.Codes[1] != 401 { - t.Errorf("Codes[1] not 401 for errofiles name %s: %v", ef.Name, ef.Codes[1]) - } - if ef.Codes[2] != 500 { - t.Errorf("Codes[2] not 500 for errofiles name %s: %v", ef.Name, ef.Codes[2]) - } - } - if ef.Name == "other_errors" { - if len(ef.Codes) != 0 { - t.Errorf("ErrorFilesFromHTTPErrors Codes not 0 for errofiles name %s: %v", ef.Name, len(ef.Codes)) - } - } - if ef.Name == "another_errors" { - if len(ef.Codes) != 1 { - t.Errorf("ErrorFilesFromHTTPErrors Codes not 1 for errofiles name %s: %v", ef.Name, len(ef.Codes)) - } - if ef.Codes[0] != 501 { - t.Errorf("Codes[0] not 501 for errofiles name %s: %v", ef.Name, ef.Codes[0]) - } - } - } - } - if b.EmailAlert == nil { - t.Error("EmailAlert is nil") - } else if *b.EmailAlert.From != "prod01@example.com" { - t.Errorf("EmailAlert.From is not prod01@example.com: %v", *b.EmailAlert.From) - } else if *b.EmailAlert.To != "sre@example.com" { - t.Errorf("EmailAlert.To is not sre@example.com: %v", *b.EmailAlert.To) - } else if b.EmailAlert.Level != "warning" { - t.Errorf("EmailAlert.Level is not warning: %v", b.EmailAlert.Level) - } else if b.EmailAlert.Myhostname != "prod01" { - t.Errorf("EmailAlert.Myhostname is not prod01: %v", b.EmailAlert.Myhostname) - } else if *b.EmailAlert.Mailers != "localmailer1" { - t.Errorf("EmailAlert.Mailers is not localmailer1: %v", *b.EmailAlert.Mailers) - } - - if *b.Fullconn != 11 { - t.Errorf("Fullconn not 11: %v", *b.Fullconn) - } - if *b.MaxKeepAliveQueue != 101 { - t.Errorf("MaxKeepAliveQueue not 101: %v", *b.MaxKeepAliveQueue) - } - - if *b.IgnorePersist.Cond != "if" { - t.Errorf("IgnorePersist Cond not if: %v", *b.IgnorePersist.Cond) - } - if *b.IgnorePersist.CondTest != "acl-name" { - t.Errorf("IgnorePersist CondTest not acl-name: %v", *b.IgnorePersist.CondTest) - } - - if *b.ForcePersist.Cond != "unless" { - t.Errorf("ForcePersist Cond not if: %v", *b.ForcePersist.Cond) - } - if *b.ForcePersist.CondTest != "acl-name-2" { - t.Errorf("ForcePersist CondTest not acl-name-2: %v", *b.ForcePersist.CondTest) - } - if b.RetryOn != "504 505" { - t.Errorf("RetryOn CondTest not 504 505: %v", b.RetryOn) - } - if *b.HTTPSendNameHeader != "X-My-Awesome-Header" { - t.Errorf("%v: HTTPSendNameHeader not X-My-Awesome-Header: %v", b.Name, *b.HTTPSendNameHeader) - } - if b.PersistRule.RdpCookieName != "name" { - t.Errorf("%v: PersistRule.RdpCookieName is not name: %v", b.Name, b.PersistRule.RdpCookieName) - } - if *b.Source.Address != "192.168.1.222" { - t.Errorf("Source Address not 192.168.1.222 %v", *b.Source.Address) - } - if b.Source.Port != 0 { - t.Errorf("Source Port not 0: %v", b.Source.Port) - } - if b.Source.Usesrc != "hdr_ip" { - t.Errorf("Source Usesrc not hdr_ip: %v", b.Source.Usesrc) - } - if b.Source.AddressSecond != "" { - t.Errorf("Source Address not empty: %v", b.Source.AddressSecond) - } - if b.Source.PortSecond != 0 { - t.Errorf("Source PortSecond not 0: %v", b.Source.PortSecond) - } - if b.Source.Hdr != "hdr" { - t.Errorf("Source Hdr not hdr: %v", b.Source.Hdr) - } - if b.Source.Occ != "occ" { - t.Errorf("Source Occ not occ: %v", b.Source.Occ) - } - if b.Source.Interface != "" { - t.Errorf("Source Interface not empty: %v", b.Source.Interface) - } - - _, err = b.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - _, _, err = clientTest.GetBackend("doesnotexist", "") - if err == nil { - t.Error("Should throw error, non existent bck") - } -} - -func TestCreateEditDeleteBackend(t *testing.T) { - // TestCreateBackend - tOut := int64(5) - cookieName := "BLA" - balanceAlgorithm := "uri" - srvtcpkaCnt := int64(10) - srvtcpkaTimeout := int64(10000) - statsRealm := "Haproxy Stats" - b := &models.Backend{ - Name: "created", - Mode: "http", - Balance: &models.Balance{ - Algorithm: &balanceAlgorithm, - URILen: 100, - URIDepth: 250, - }, - BindProcess: "4", - Cookie: &models.Cookie{ - Domains: []*models.Domain{ - {Value: "dom1"}, - {Value: "dom2"}, - }, - Attrs: []*models.Attr{}, - Dynamic: true, - Httponly: true, - Indirect: true, - Maxidle: 5, - Maxlife: 20, - Name: &cookieName, - Nocache: true, - Postonly: true, - Preserve: false, - Secure: false, - Type: "prefix", - }, - HashType: &models.HashType{ - Method: "map-based", - Function: "crc32", - }, - DefaultServer: &models.DefaultServer{ - ServerParams: models.ServerParams{ - Fall: &tOut, - Inter: &tOut, - LogBufsize: misc.Int64P(123), - }, - }, - HTTPConnectionMode: "http-keep-alive", - HTTPKeepAlive: "enabled", - ConnectTimeout: &tOut, - ExternalCheck: "enabled", - ExternalCheckCommand: "/bin/false", - ExternalCheckPath: "/bin", - Allbackups: "enabled", - AdvCheck: "smtpchk", - SmtpchkParams: &models.SmtpchkParams{ - Hello: "HELO", - Domain: "example.com", - }, - AcceptInvalidHTTPResponse: "enabled", - Compression: &models.Compression{ - Offload: true, - }, - LogHealthChecks: "enabled", - Checkcache: "enabled", - IndependentStreams: "enabled", - Nolinger: "enabled", - Originalto: &models.Originalto{ - Enabled: misc.StringP("enabled"), - Except: "127.0.0.1", - Header: "X-Client-Dst", - }, - Persist: "enabled", - PreferLastServer: "enabled", - SpopCheck: "enabled", - TCPSmartConnect: "enabled", - Transparent: "enabled", - SpliceAuto: "enabled", - SpliceRequest: "enabled", - SpliceResponse: "enabled", - SrvtcpkaCnt: &srvtcpkaCnt, - SrvtcpkaIdle: &srvtcpkaTimeout, - SrvtcpkaIntvl: &srvtcpkaTimeout, - StatsOptions: &models.StatsOptions{ - StatsShowModules: true, - StatsRealm: true, - StatsRealmRealm: &statsRealm, - StatsAuths: []*models.StatsAuth{ - {User: misc.StringP("user1"), Passwd: misc.StringP("pwd1")}, - {User: misc.StringP("user2"), Passwd: misc.StringP("pwd2")}, - }, - StatsHTTPRequests: []*models.StatsHTTPRequest{ - {Type: misc.StringP("allow"), Cond: "if", CondTest: "something"}, - {Type: misc.StringP("auth"), Realm: "haproxy\\ stats"}, - }, - }, - EmailAlert: &models.EmailAlert{ - From: misc.StringP("prod01@example.com"), - To: misc.StringP("sre@example.com"), - Level: "warning", - Mailers: misc.StringP("localmailer1"), - }, - ErrorFilesFromHTTPErrors: []*models.Errorfiles{ - {Name: "test_errors", Codes: []int64{400}}, - {Name: "test_errors_all"}, - }, - Disabled: true, - } - - err := clientTest.CreateBackend(b, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, backend, err := clientTest.GetBackend("created", "") - if err != nil { - t.Error(err.Error()) - } - - var givenJSONB []byte - givenJSONB, err = b.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - var ondiskJSONB []byte - ondiskJSONB, err = backend.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - if string(givenJSONB) != string(ondiskJSONB) { - fmt.Printf("Created backend: %v\n", string(ondiskJSONB)) - fmt.Printf("Given backend: %v\n", string(givenJSONB)) - t.Error("Created backend not equal to given backend") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - err = clientTest.CreateBackend(b, "", version) - if err == nil { - t.Error("Should throw error bck already exists") - version++ - } - // TestEditBackend - tOut = int64(3) - e := int64(1200000) - kl := int64(128) - s := int64(25600) - backends := []*models.Backend{ - { - From: "test_defaults", - Name: "created", - Mode: "http", - Balance: &models.Balance{ - Algorithm: &balanceAlgorithm, - URILen: 10, - URIDepth: 25, - }, - BindProcess: "3", - Cookie: &models.Cookie{ - Domains: []*models.Domain{ - {Value: "dom1"}, - {Value: "dom3"}, - }, - Dynamic: true, - Httponly: true, - Indirect: false, - Maxidle: 150, - Maxlife: 100, - Name: &cookieName, - Nocache: false, - Postonly: false, - Preserve: true, - Secure: true, - Type: "rewrite", - }, - // Use non deprecated option only - HTTPConnectionMode: "httpclose", - ConnectTimeout: &tOut, - StickTable: &models.ConfigStickTable{ - Expire: &e, - Keylen: &kl, - Size: &s, - Store: "gpc0,http_req_rate(40s)", - Type: "string", - }, - AdvCheck: "mysql-check", - MysqlCheckParams: &models.MysqlCheckParams{ - Username: "user", - ClientVersion: "pre-41", - }, - EmailAlert: &models.EmailAlert{ - From: misc.StringP("prod01@example.com"), - To: misc.StringP("sre@example.com"), - Level: "warning", - Mailers: misc.StringP("localmailer1"), - }, - Originalto: &models.Originalto{ - Enabled: misc.StringP("enabled"), - Except: "127.0.0.1", - }, - }, - { - Name: "created", - Mode: "http", - Balance: &models.Balance{ - Algorithm: &balanceAlgorithm, - }, - Cookie: &models.Cookie{ - Domains: []*models.Domain{ - {Value: "dom1"}, - {Value: "dom2"}, - }, - Name: &cookieName, - }, - ConnectTimeout: &tOut, - StickTable: &models.ConfigStickTable{}, - AdvCheck: "pgsql-check", - PgsqlCheckParams: &models.PgsqlCheckParams{ - Username: "user", - }, - EmailAlert: &models.EmailAlert{ - From: misc.StringP("prod01@example.com"), - To: misc.StringP("sre@example.com"), - Level: "warning", - Mailers: misc.StringP("localmailer1"), - }, - // Use deprecated option only - Httpclose: "enabled", - Originalto: &models.Originalto{ - Enabled: misc.StringP("enabled"), - Header: "X-Client-Dst", - }, - }, - { - Name: "created", - Mode: "http", - Balance: &models.Balance{ - Algorithm: &balanceAlgorithm, - }, - Cookie: &models.Cookie{ - Domains: []*models.Domain{ - {Value: "dom4"}, - {Value: "dom5"}, - }, - Name: &cookieName, - }, - ConnectTimeout: &tOut, - StickTable: &models.ConfigStickTable{}, - AdvCheck: "httpchk", - HttpchkParams: &models.HttpchkParams{ - Method: "HEAD", - URI: "/", - }, - HTTPCheck: &models.HTTPCheck{ - Type: "send", - Method: "OPTIONS", - URI: "/", - Version: "HTTP/1.1", - Index: misc.Int64P(0), - }, - Checkcache: "disabled", - IndependentStreams: "disabled", - Nolinger: "disabled", - Persist: "disabled", - PreferLastServer: "disabled", - SpopCheck: "disabled", - TCPSmartConnect: "disabled", - Transparent: "disabled", - SpliceAuto: "disabled", - SpliceRequest: "disabled", - SpliceResponse: "disabled", - SrvtcpkaCnt: &srvtcpkaCnt, - SrvtcpkaIdle: &srvtcpkaTimeout, - SrvtcpkaIntvl: &srvtcpkaTimeout, - StatsOptions: &models.StatsOptions{ - StatsShowModules: true, - StatsRealm: true, - StatsRealmRealm: &statsRealm, - StatsAuths: []*models.StatsAuth{ - {User: misc.StringP("new_user1"), Passwd: misc.StringP("new_pwd1")}, - {User: misc.StringP("new_user2"), Passwd: misc.StringP("new_pwd2")}, - }, - StatsHTTPRequests: []*models.StatsHTTPRequest{ - {Type: misc.StringP("allow"), Cond: "if", CondTest: "something_else"}, - {Type: misc.StringP("auth"), Realm: "haproxy\\ stats2"}, - }, - }, - EmailAlert: &models.EmailAlert{ - From: misc.StringP("prod01@example.com"), - To: misc.StringP("sre@example.com"), - Level: "warning", - Mailers: misc.StringP("localmailer1"), - }, - Originalto: &models.Originalto{ - Enabled: misc.StringP("enabled"), - Except: "127.0.0.1", - Header: "X-Client-Dst", - }, - }, - } - - for i, backend := range backends { - if errB := testBackendUpdate(backend, t); errB != nil { - t.Errorf("failed update for backend %d: %v", i, errB) - } - } - - // TestDeleteBackend - err = clientTest.DeleteBackend("created", "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - if v, _ := clientTest.GetVersion(""); v != version { - t.Error("Version not incremented") - } - - err = clientTest.DeleteBackend("created", "", 999999999) - if err != nil { - if confErr, ok := err.(*ConfError); ok { - if !confErr.Is(ErrVersionMismatch) { - t.Error("Should throw ErrVersionMismatch error") - } - } else { - t.Error("Should throw ErrVersionMismatch error") - } - } - - _, _, err = clientTest.GetBackend("created", "") - if err == nil { - t.Error("DeleteBackend failed, bck test still exists") - } - - err = clientTest.DeleteBackend("doesnotexist", "", version) - if err == nil { - t.Error("Should throw error, non existent bck") - version++ - } -} - -func testBackendUpdate(b *models.Backend, t *testing.T) error { - err := clientTest.EditBackend("created", b, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, backend, err := clientTest.GetBackend("created", "") - if err != nil { - return err - } - - if !compareBackends(backend, b, t) { - fmt.Printf("Edited bck: %+v\n", backend) - fmt.Printf("Given bck: %+v\n", b) - return fmt.Errorf("edited backend not equal to given backend") - } - - if v != version { - return fmt.Errorf("version %v returned, expected %v", v, version) - } - return nil -} - -func compareBackends(x, y *models.Backend, t *testing.T) bool { //nolint:gocognit,gocyclo - if *x.Balance.Algorithm != *y.Balance.Algorithm { - return false - } - if x.Balance.HdrName != y.Balance.HdrName { - return false - } - if x.Balance.HdrUseDomainOnly != y.Balance.HdrUseDomainOnly { - return false - } - if x.Balance.RandomDraws != y.Balance.RandomDraws { - return false - } - if x.Balance.RdpCookieName != y.Balance.RdpCookieName { - return false - } - if x.Balance.URIDepth != y.Balance.URIDepth { - return false - } - if x.Balance.URILen != y.Balance.URILen { - return false - } - if x.Balance.URIWhole != y.Balance.URIWhole { - return false - } - if x.Balance.URLParam != y.Balance.URLParam { - return false - } - if x.Balance.URLParamCheckPost != y.Balance.URLParamCheckPost { - return false - } - if x.Balance.URLParamMaxWait != y.Balance.URLParamMaxWait { - return false - } - - x.Balance = nil - y.Balance = nil - - if *x.Cookie.Name != *y.Cookie.Name { - return false - } - if len(x.Cookie.Domains) != len(y.Cookie.Domains) { - return false - } - if x.Cookie.Domains[0].Value != y.Cookie.Domains[0].Value { - return false - } - if x.Cookie.Dynamic != y.Cookie.Dynamic { - return false - } - if x.Cookie.Httponly != y.Cookie.Httponly { - return false - } - if x.Cookie.Indirect != y.Cookie.Indirect { - return false - } - if x.Cookie.Maxidle != y.Cookie.Maxidle { - return false - } - if x.Cookie.Maxlife != y.Cookie.Maxlife { - return false - } - if x.Cookie.Nocache != y.Cookie.Nocache { - return false - } - if x.Cookie.Postonly != y.Cookie.Postonly { - return false - } - if x.Cookie.Preserve != y.Cookie.Preserve { - return false - } - if x.Cookie.Secure != y.Cookie.Secure { - return false - } - if x.Cookie.Type != y.Cookie.Type { - return false - } - - x.Cookie = nil - y.Cookie = nil - - if x.BindProcess != y.BindProcess { - return false - } - - if !reflect.DeepEqual(x.DefaultServer, y.DefaultServer) { - return false - } - - x.DefaultServer = nil - y.DefaultServer = nil - - if !reflect.DeepEqual(x.HttpchkParams, y.HttpchkParams) { - return false - } - - x.HttpchkParams = nil - y.HttpchkParams = nil - - if !cmp.Equal(x.HTTPCheck, y.HTTPCheck, cmpopts.EquateEmpty()) { - t.Errorf("Diff in HTTPChecK %s", cmp.Diff(x.HTTPCheck, y.HTTPCheck, cmpopts.EquateEmpty())) - return false - } - - x.HTTPCheck = nil - y.HTTPCheck = nil - - if !reflect.DeepEqual(x.StickTable, y.StickTable) { - return false - } - - x.StickTable = nil - y.StickTable = nil - - if !reflect.DeepEqual(x.Redispatch, y.Redispatch) { - return false - } - - x.Redispatch = nil - y.Redispatch = nil - - if !reflect.DeepEqual(x.Forwardfor, y.Forwardfor) { - return false - } - - x.Forwardfor = nil - y.Forwardfor = nil - - if !reflect.DeepEqual(x.SmtpchkParams, y.SmtpchkParams) { - return false - } - - x.SmtpchkParams = nil - y.SmtpchkParams = nil - - if !reflect.DeepEqual(x.MysqlCheckParams, y.MysqlCheckParams) { - return false - } - - x.MysqlCheckParams = nil - y.MysqlCheckParams = nil - - if !reflect.DeepEqual(x.PgsqlCheckParams, y.PgsqlCheckParams) { - return false - } - - x.PgsqlCheckParams = nil - y.PgsqlCheckParams = nil - - if !reflect.DeepEqual(x.Originalto, y.Originalto) { - return false - } - - x.Originalto = nil - y.Originalto = nil - - // Due to deprecated fields Httpclose, HTTPKeepAlive, HTTPServerClose - // in favor of HTTPConnectionMode - // If HTTPConnectionMode is set in original backend - // - Httpclose, HTTPKeepAlive, HTTPServerClose will be set in updated backend, even if not present in original backend - // If HTTPConnectionMode is unset in original backend: - // - it will be set in updated backend - switch y.HTTPConnectionMode { - case "http-keep-alive": - if x.HTTPKeepAlive != "enabled" { - return false - } - x.HTTPKeepAlive = "" - case "http-server-close": - if x.HTTPServerClose != "enabled" { - return false - } - x.HTTPServerClose = "" - case "httpclose": - if x.Httpclose != "enabled" { - return false - } - x.Httpclose = "" - case "": - x.HTTPConnectionMode = "" - } - - return reflect.DeepEqual(x, y) -} - -func TestCreateEditDeleteBackendHTTPConnectionMode(t *testing.T) { - // TestCreateBackend - tOut := int64(5) - - // Backend with HTTPConnectionMode only - b := &models.Backend{ - Name: "special-httpconnectionmode", - Mode: "http", - DefaultServer: &models.DefaultServer{ - ServerParams: models.ServerParams{ - Fall: &tOut, - Inter: &tOut, - }, - }, - HTTPConnectionMode: "http-keep-alive", - } - - err := clientTest.CreateBackend(b, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, backend, err := clientTest.GetBackend("special-httpconnectionmode", "") - if err != nil { - t.Error(err.Error()) - } - - if backend.HTTPConnectionMode != "http-keep-alive" { - t.Errorf("Created backend is not correct for HTTPConnectionMode: %s", backend.HTTPConnectionMode) - } - if backend.HTTPKeepAlive != "enabled" { - t.Errorf("Created backend is not correct for HTTPKeepAlive: %s", backend.HTTPConnectionMode) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - err = clientTest.CreateBackend(b, "", version) - if err == nil { - t.Error("Should throw error bck already exists") - version++ - } - - type testinput struct { - backend *models.Backend - expectedHTTPConnectionMode string - expectedHTTPKeepAlive string - expectedHttpclose string - exptectedHTTPServerClose string - } - // TestEditBackend - inputs := []testinput{ - { - // Update HTTPConnectionMode - backend: &models.Backend{ - Name: "special-httpconnectionmode", - Mode: "http", - DefaultServer: &models.DefaultServer{ - ServerParams: models.ServerParams{ - Fall: &tOut, - Inter: &tOut, - }, - }, - HTTPConnectionMode: "httpclose", - }, - expectedHTTPConnectionMode: "httpclose", - expectedHTTPKeepAlive: "", - exptectedHTTPServerClose: "", - expectedHttpclose: "enabled", - }, - { - // Use only deprecated option - backend: &models.Backend{ - Name: "special-httpconnectionmode", - Mode: "http", - DefaultServer: &models.DefaultServer{ - ServerParams: models.ServerParams{ - Fall: &tOut, - Inter: &tOut, - }, - }, - HTTPServerClose: "enabled", - }, - expectedHTTPConnectionMode: "http-server-close", - expectedHTTPKeepAlive: "", - exptectedHTTPServerClose: "enabled", - expectedHttpclose: "", - }, - { - // Use both - Priority on HTTPConnection - backend: &models.Backend{ - Name: "special-httpconnectionmode", - Mode: "http", - DefaultServer: &models.DefaultServer{ - ServerParams: models.ServerParams{ - Fall: &tOut, - Inter: &tOut, - }, - }, - HTTPConnectionMode: "http-keep-alive", - HTTPServerClose: "enabled", - }, - expectedHTTPConnectionMode: "http-keep-alive", - expectedHTTPKeepAlive: "enabled", - exptectedHTTPServerClose: "", - expectedHttpclose: "", - }, - { - // no option with deprecated option - backend: &models.Backend{ - Name: "special-httpconnectionmode", - Mode: "http", - DefaultServer: &models.DefaultServer{ - ServerParams: models.ServerParams{ - Fall: &tOut, - Inter: &tOut, - }, - }, - HTTPServerClose: "disabled", - }, - expectedHTTPConnectionMode: "", // not possible to set no option with this field - expectedHTTPKeepAlive: "", - exptectedHTTPServerClose: "disabled", - expectedHttpclose: "", - }, - { - // set back with HTTPConnectionMode - backend: &models.Backend{ - Name: "special-httpconnectionmode", - Mode: "http", - DefaultServer: &models.DefaultServer{ - ServerParams: models.ServerParams{ - Fall: &tOut, - Inter: &tOut, - }, - }, - HTTPConnectionMode: "httpclose", - }, - expectedHTTPConnectionMode: "httpclose", - expectedHTTPKeepAlive: "", - exptectedHTTPServerClose: "", - expectedHttpclose: "enabled", - }, - { - // remove option - backend: &models.Backend{ - Name: "special-httpconnectionmode", - Mode: "http", - DefaultServer: &models.DefaultServer{ - ServerParams: models.ServerParams{ - Fall: &tOut, - Inter: &tOut, - }, - }, - HTTPConnectionMode: "", - }, - expectedHTTPConnectionMode: "", - expectedHTTPKeepAlive: "", - exptectedHTTPServerClose: "", - expectedHttpclose: "", - }, - } - - for i, input := range inputs { - err := clientTest.EditBackend("special-httpconnectionmode", input.backend, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - _, backend, err := clientTest.GetBackend("special-httpconnectionmode", "") - if err != nil { - t.Error(err.Error()) - } - - if backend.HTTPConnectionMode != input.expectedHTTPConnectionMode { - t.Errorf("Updated backend %d is not correct for HTTPConnectionMode: %s", i, backend.HTTPConnectionMode) - } - if backend.HTTPKeepAlive != input.expectedHTTPKeepAlive { - t.Errorf("Updated backend %d is not correct for HTTPKeepAlive: %s", i, backend.HTTPConnectionMode) - } - if backend.HTTPServerClose != input.exptectedHTTPServerClose { - t.Errorf("Updated backend %d is not correct for HTTPServerClose: %s", i, backend.HTTPServerClose) - } - if backend.Httpclose != input.expectedHttpclose { - t.Errorf("Updated backend %d is not correct for Httpclose: %s", i, backend.Httpclose) - } - - } - - // TestDeleteBackend - err = clientTest.DeleteBackend("special-httpconnectionmode", "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } -} diff --git a/configuration/bind.go b/configuration/bind.go index 9d2afbc7..f11ec607 100644 --- a/configuration/bind.go +++ b/configuration/bind.go @@ -653,11 +653,11 @@ func validateParams(data *models.Bind) error { func bindSectionType(parentType string) parser.Section { var sectionType parser.Section switch parentType { - case "frontend": + case FrontendParentName: sectionType = parser.Frontends - case "log_forward": + case LogForwardParentName: sectionType = parser.LogForward - case "peers": + case PeersParentName: sectionType = parser.Peers } return sectionType diff --git a/configuration/capture.go b/configuration/capture.go index 7a15fb4e..dc4b99db 100644 --- a/configuration/capture.go +++ b/configuration/capture.go @@ -49,7 +49,7 @@ func (c *client) GetDeclareCaptures(frontend string, transactionID string) (int6 } captures, err := ParseDeclareCaptures(frontend, p) if err != nil { - return v, nil, c.HandleError("", "frontend", frontend, "", false, err) + return v, nil, c.HandleError("", FrontendParentName, frontend, "", false, err) } return v, captures, nil } @@ -67,9 +67,9 @@ func (c *client) GetDeclareCapture(index int64, frontend string, transactionID s return 0, nil, err } - data, err := p.GetOne("frontend", frontend, "declare capture", int(index)) + data, err := p.GetOne(FrontendParentName, frontend, "declare capture", int(index)) if err != nil { - return v, nil, c.HandleError(strconv.FormatInt(index, 10), "frontend", frontend, "", false, err) + return v, nil, c.HandleError(strconv.FormatInt(index, 10), FrontendParentName, frontend, "", false, err) } declareCapture := ParseDeclareCapture(data.(types.DeclareCapture)) @@ -84,8 +84,8 @@ func (c *client) DeleteDeclareCapture(index int64, frontend string, transactionI if err != nil { return err } - if err := p.Delete("frontend", frontend, "declare capture", int(index)); err != nil { - return c.HandleError(strconv.FormatInt(index, 10), "frontend", frontend, t, transactionID == "", err) + if err := p.Delete(FrontendParentName, frontend, "declare capture", int(index)); err != nil { + return c.HandleError(strconv.FormatInt(index, 10), FrontendParentName, frontend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") } @@ -103,8 +103,8 @@ func (c *client) CreateDeclareCapture(frontend string, data *models.Capture, tra if err != nil { return err } - if err := p.Insert("frontend", frontend, "declare capture", SerializeDeclareCapture(*data), int(*data.Index)); err != nil { - return c.HandleError(strconv.FormatInt(*data.Index, 10), "frontend", frontend, t, transactionID == "", err) + if err := p.Insert(FrontendParentName, frontend, "declare capture", SerializeDeclareCapture(*data), int(*data.Index)); err != nil { + return c.HandleError(strconv.FormatInt(*data.Index, 10), FrontendParentName, frontend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") } @@ -122,15 +122,15 @@ func (c *client) EditDeclareCapture(index int64, frontend string, data *models.C if err != nil { return err } - if _, err := p.GetOne("frontend", frontend, "declare capture", int(index)); err != nil { - return c.HandleError(strconv.FormatInt(index, 10), "frontend", frontend, t, transactionID == "", err) + if _, err := p.GetOne(FrontendParentName, frontend, "declare capture", int(index)); err != nil { + return c.HandleError(strconv.FormatInt(index, 10), FrontendParentName, frontend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") } func ParseDeclareCaptures(frontend string, p parser.Parser) (models.Captures, error) { captures := models.Captures{} - data, err := p.Get("frontend", frontend, "declare capture", false) + data, err := p.Get(FrontendParentName, frontend, "declare capture", false) if err != nil { if errors.Is(err, parser_errors.ErrFetch) { return captures, nil diff --git a/configuration/configuration.go b/configuration/configuration.go index d4ecdbc2..a012c8e8 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -36,6 +36,18 @@ import ( "github.com/haproxytech/client-native/v5/models" ) +const ( + BackendParentName = "backend" + FrontendParentName = "frontend" + DefaultsParentName = "defaults" + LogForwardParentName = "log_forward" + PeersParentName = "peers" + RingParentName = "ring" + GlobalParentName = "global" + FCGIAppParentName = "fcgi-app" + ResolverParentName = "resolvers" +) + // ClientParams is just a placeholder for all client options type ClientParams struct { ConfigurationFile string diff --git a/configuration/defaults_test.go b/configuration/defaults_test.go deleted file mode 100644 index 8465bfc9..00000000 --- a/configuration/defaults_test.go +++ /dev/null @@ -1,670 +0,0 @@ -package configuration - -import ( - "fmt" - "testing" - - "github.com/haproxytech/client-native/v5/misc" - "github.com/haproxytech/client-native/v5/models" -) - -func TestGetDefaults(t *testing.T) { //nolint:gocognit,gocyclo - v, d, err := clientTest.GetDefaultsConfiguration("") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - if *d.Balance.Algorithm != "roundrobin" { - t.Errorf("Balance.Algorithm not roundrobin: %v", d.Balance.Algorithm) - } - if d.Mode != "http" { - t.Errorf("Mode not http: %v", d.Mode) - } - if *d.Backlog != 1024 { - t.Errorf("Backlog not 2048: %v", *d.Backlog) - } - if d.MonitorURI != "/monitor" { - t.Errorf("MonitorURI not /monitor: %v", d.MonitorURI) - } - if d.BindProcess != "1-4" { - t.Errorf("BindProcess not 1-4: %v", d.BindProcess) - } - if d.Clitcpka != "enabled" { - t.Errorf("Clitcpka not enabled: %v", d.Clitcpka) - } - if d.Srvtcpka != "enabled" { - t.Errorf("Srvtcpka not enabled: %v", d.Srvtcpka) - } - if d.Tcpka != "enabled" { - t.Errorf("Tcpka not enabled: %v", d.Tcpka) - } - if d.Dontlognull != "enabled" { - t.Errorf("Dontlognull not enabled: %v", d.Dontlognull) - } - if d.DisableH2Upgrade != "enabled" { - t.Errorf("DisableH2Upgrade not enabled: %v", d.DisableH2Upgrade) - } - if d.HTTPUseHtx != "enabled" { - t.Errorf("HTTPUseHtx not enabled: %v", d.HTTPUseHtx) - } - if !d.Httplog { - t.Errorf("Httplog not enabled: %v", d.Httplog) - } - if d.LogHealthChecks != "enabled" { - t.Errorf("LogHealthChecks not enabled: %v", d.LogHealthChecks) - } - if d.HTTPConnectionMode != "httpclose" { - t.Errorf("HTTPConnectionMode not httpclose: %v", d.HTTPConnectionMode) - } - if d.HTTPRestrictReqHdrNames != "reject" { - t.Errorf("HTTPRestrictReqHdrNames not reject: %v", d.HTTPRestrictReqHdrNames) - } - if d.DefaultBackend != "test" { - t.Errorf("DefaultBackend not test: %v", d.DefaultBackend) - } - if *d.Maxconn != 2000 { - t.Errorf("Maxconn not 2000: %v", *d.Maxconn) - } - if *d.ClientTimeout != 4000 { - t.Errorf("ClientTimeout not 4000: %v", *d.ClientTimeout) - } - if *d.CheckTimeout != 2000 { - t.Errorf("CheckTimeout not 2000: %v", *d.CheckTimeout) - } - if *d.ConnectTimeout != 5000 { - t.Errorf("ConnectTimeout not 5000: %v", *d.ConnectTimeout) - } - if *d.QueueTimeout != 900 { - t.Errorf("QueueTimeout not 900: %v", *d.QueueTimeout) - } - if *d.ServerTimeout != 2000 { - t.Errorf("ServerTimeout not 2000: %v", *d.ServerTimeout) - } - if *d.ServerFinTimeout != 1000 { - t.Errorf("ServerFinTimeout not 1000: %v", *d.ServerFinTimeout) - } - if *d.ClientFinTimeout != 1000 { - t.Errorf("ServerFinTimeout not 1000: %v", *d.ClientFinTimeout) - } - if *d.TarpitTimeout != 2000 { - t.Errorf("TarpitTimeout not 2000: %v", *d.TarpitTimeout) - } - if *d.HTTPRequestTimeout != 2000 { - t.Errorf("HTTPRequestTimeout not 2000: %v", *d.HTTPRequestTimeout) - } - if *d.HTTPKeepAliveTimeout != 3000 { - t.Errorf("HTTPKeepAliveTimeout not 3000: %v", *d.HTTPKeepAliveTimeout) - } - if *d.DefaultServer.Fall != 2000 { - t.Errorf("DefaultServer.Fall not 2000: %v", *d.DefaultServer.Fall) - } - if *d.DefaultServer.Rise != 4000 { - t.Errorf("DefaultServer.Rise not 4000: %v", *d.DefaultServer.Rise) - } - if *d.DefaultServer.Inter != 5000 { - t.Errorf("DefaultServer.Inter not 5000: %v", *d.DefaultServer.Inter) - } - if *d.DefaultServer.HealthCheckPort != 8888 { - t.Errorf("DefaultServer.HealthCheckPort not 8888: %v", *d.DefaultServer.HealthCheckPort) - } - if len(d.ErrorFiles) != 3 { - t.Errorf("ErrorFiles not 3: %v", len(d.ErrorFiles)) - } else { - for _, ef := range d.ErrorFiles { - if ef.Code == 403 { - if ef.File != "/test/403.html" { - t.Errorf("File for %v not 403: %v", ef.Code, ef.File) - } - } - if ef.Code == 500 { - if ef.File != "/test/500.html" { - t.Errorf("File for %v not 500: %v", ef.Code, ef.File) - } - } - if ef.Code == 429 { - if ef.File != "/test/429.html" { - t.Errorf("File for %v not 429: %v", ef.Code, ef.File) - } - } - } - } - if d.ExternalCheck != "enabled" { - t.Errorf("ExternalCheck not enabled: %v", d.ExternalCheck) - } - if d.ExternalCheckPath != "/bin" { - t.Errorf("ExternalCheckPath not /bin: %v", d.ExternalCheckPath) - } - if d.ExternalCheckCommand != "/bin/true" { - t.Errorf("ExternalCheckCommand not /bin/true: %v", d.ExternalCheckCommand) - } - if d.AcceptInvalidHTTPRequest != "enabled" { - t.Errorf("AcceptInvalidHTTPRequest not enabled: %v", d.AcceptInvalidHTTPRequest) - } - if d.AcceptInvalidHTTPResponse != "enabled" { - t.Errorf("AcceptInvalidHTTPResponse not enabled: %v", d.AcceptInvalidHTTPResponse) - } - if d.H1CaseAdjustBogusClient != "enabled" { - t.Errorf("H1CaseAdjustBogusClient not enabled: %v", d.H1CaseAdjustBogusClient) - } - if d.H1CaseAdjustBogusServer != "enabled" { - t.Errorf("H1CaseAdjustBogusServer not enabled: %v", d.H1CaseAdjustBogusServer) - } - if d.Compression == nil { - t.Errorf("Compression is nil") - } else { - if !d.Compression.Offload { - t.Errorf("Compression.Offload wrong: %v", d.Compression.Offload) - } - } - if d.ClitcpkaCnt == nil { - t.Errorf("ClitcpkaCnt is nil") - } else if *d.ClitcpkaCnt != 10 { - t.Errorf("ClitcpkaCnt not 10: %v", *d.ClitcpkaCnt) - } - if d.ClitcpkaIdle == nil { - t.Errorf("ClitcpkaIdle is nil") - } else if *d.ClitcpkaIdle != 10000 { - t.Errorf("ClitcpkaIdle not 10000: %v", *d.ClitcpkaIdle) - } - if d.ClitcpkaIntvl == nil { - t.Errorf("ClitcpkaIntvl is nil") - } else if *d.ClitcpkaIntvl != 10000 { - t.Errorf("ClitcpkaIntvl not 10000: %v", *d.ClitcpkaIntvl) - } - if d.Checkcache != "disabled" { - t.Errorf("Checkcache not disabled: %v", d.Checkcache) - } - if d.HTTPIgnoreProbes != "disabled" { - t.Errorf("HTTPIgnoreProbes not disabled: %v", d.HTTPIgnoreProbes) - } - if d.HTTPUseProxyHeader != "disabled" { - t.Errorf("HTTPUseProxyHeader not disabled: %v", d.HTTPUseProxyHeader) - } - if d.Httpslog != "disabled" { - t.Errorf("Httpslog not disabled: %v", d.Httpslog) - } - if d.IndependentStreams != "disabled" { - t.Errorf("IndependentStreams not disabled: %v", d.IndependentStreams) - } - if d.Nolinger != "disabled" { - t.Errorf("Nolinger not disabled: %v", d.Nolinger) - } - if d.Originalto == nil { - t.Error("Originalto is nil, expected not nil") - } else { - if *d.Originalto.Enabled != "enabled" { - t.Errorf("Originalto.Enabled is not enabled: %v", *d.Originalto.Enabled) - } - if d.Originalto.Except != "" { - t.Errorf("Originalto.Except is not empty: %v", d.Originalto.Except) - } - if d.Originalto.Header != "" { - t.Errorf("Originalto.Header is not empty: %v", d.Originalto.Header) - } - } - if d.Persist != "enabled" { - t.Errorf("Persist not enabled: %v", d.Persist) - } - if d.PreferLastServer != "enabled" { - t.Errorf("PreferLastServer not enabled: %v", d.PreferLastServer) - } - if d.SocketStats != "enabled" { - t.Errorf("SocketStats not enabled: %v", d.SocketStats) - } - if d.TCPSmartAccept != "enabled" { - t.Errorf("TCPSmartAccept not enabled: %v", d.TCPSmartAccept) - } - if d.TCPSmartConnect != "enabled" { - t.Errorf("TCPSmartConnect not enabled: %v", d.TCPSmartConnect) - } - if d.Transparent != "enabled" { - t.Errorf("Transparent not enabled: %v", d.Transparent) - } - if d.DontlogNormal != "enabled" { - t.Errorf("DontlogNormal not enabled: %v", d.DontlogNormal) - } - if d.HTTPNoDelay != "enabled" { - t.Errorf("HTTPNoDelay not enabled: %v", d.HTTPNoDelay) - } - if d.SpliceAuto != "enabled" { - t.Errorf("SpliceAuto not enabled: %v", d.SpliceAuto) - } - if d.SpliceRequest != "enabled" { - t.Errorf("SpliceRequest not enabled: %v", d.SpliceRequest) - } - if d.SpliceResponse != "enabled" { - t.Errorf("SpliceResponse not enabled: %v", d.SpliceResponse) - } - if d.IdleCloseOnResponse != "enabled" { - t.Errorf("IdleCloseOnResponse not enabled: %v", d.IdleCloseOnResponse) - } - - if d.SrvtcpkaCnt == nil { - t.Errorf("SrvtcpkaCnt is nil") - } else if *d.SrvtcpkaCnt != 10 { - t.Errorf("SrvtcpkaCnt not 10: %v", *d.SrvtcpkaCnt) - } - if d.SrvtcpkaIdle == nil { - t.Errorf("SrvtcpkaIdle is nil") - } else if *d.SrvtcpkaIdle != 10000 { - t.Errorf("SrvtcpkaIdle not 10000: %v", *d.SrvtcpkaIdle) - } - if d.SrvtcpkaIntvl == nil { - t.Errorf("SrvtcpkaIntvl is nil") - } else if *d.SrvtcpkaIntvl != 10000 { - t.Errorf("SrvtcpkaIntvl not 10000: %v", *d.SrvtcpkaIntvl) - } - if d.StatsOptions == nil { - t.Errorf("StatsOptions is nil") - } - if d.StatsOptions.StatsShowModules != true { - t.Error("StatsShowModules not set") - } - if d.StatsOptions.StatsRealm != true { - t.Error("StatsRealm not set") - } - if d.StatsOptions.StatsRealmRealm == nil { - t.Errorf("StatsRealmRealm is nil") - } else if *d.StatsOptions.StatsRealmRealm != `HAProxy\\ Statistics` { - t.Errorf("StatsRealmRealm not 'HAProxy Statistics': %v", *d.StatsOptions.StatsRealmRealm) - } - if len(d.StatsOptions.StatsAuths) != 2 { - t.Errorf("StatsAuths expected 2 instances got: %v", len(d.StatsOptions.StatsAuths)) - } - if d.StatsOptions.StatsAuths[0].User == nil { - t.Errorf("StatsAuths 0 User is nil") - } else if *d.StatsOptions.StatsAuths[0].User != "admin" { - t.Errorf("StatsAuths 0 User not admin: %v", *d.StatsOptions.StatsAuths[0].User) - } - if d.StatsOptions.StatsAuths[0].Passwd == nil { - t.Errorf("StatsAuths 0 Passwd is nil") - } else if *d.StatsOptions.StatsAuths[0].Passwd != "AdMiN123" { - t.Errorf("StatsAuths 0 Passwd not AdMiN123: %v", *d.StatsOptions.StatsAuths[0].Passwd) - } - if d.StatsOptions.StatsAuths[1].User == nil { - t.Errorf("StatsAuths 1 User is nil") - } else if *d.StatsOptions.StatsAuths[1].User != "admin2" { - t.Errorf("StatsAuths 1 User not admin2: %v", *d.StatsOptions.StatsAuths[1].User) - } - if d.StatsOptions.StatsAuths[1].Passwd == nil { - t.Errorf("StatsAuths 1 Passwd is nil") - } else if *d.StatsOptions.StatsAuths[1].Passwd != "AdMiN1234" { - t.Errorf("StatsAuths 1 Passwd not AdMiN1234: %v", *d.StatsOptions.StatsAuths[1].Passwd) - } - if d.LoadServerStateFromFile != "global" { - t.Errorf("LoadServerStateFromFile not global: %v", d.LoadServerStateFromFile) - } - - if d.EmailAlert == nil { - t.Error("EmailAlert is nil") - } else if *d.EmailAlert.From != "srv01@example.com" { - t.Errorf("EmailAlert.From is not srv01@example.com: %v", *d.EmailAlert.From) - } else if *d.EmailAlert.To != "support@example.com" { - t.Errorf("EmailAlert.To is not support@example.com: %v", *d.EmailAlert.To) - } else if d.EmailAlert.Level != "err" { - t.Errorf("EmailAlert.Level is not err: %v", d.EmailAlert.Level) - } else if d.EmailAlert.Myhostname != "srv01" { - t.Errorf("EmailAlert.Myhostname is not srv01: %v", d.EmailAlert.Myhostname) - } else if *d.EmailAlert.Mailers != "localmailer1" { - t.Errorf("EmailAlert.Mailers is not localmailer1: %v", *d.EmailAlert.Mailers) - } - - if *d.Fullconn != 10 { - t.Errorf("Fullconn not 10: %v", *d.Fullconn) - } - if *d.HTTPSendNameHeader != "" { - t.Errorf("HTTPSendNameHeader not empty: %v", *d.HTTPSendNameHeader) - } - if *d.MaxKeepAliveQueue != 100 { - t.Errorf("MaxKeepAliveQueue not 100: %v", *d.MaxKeepAliveQueue) - } - if d.RetryOn != "503 504" { - t.Errorf("RetryOn not 503 504: %v", d.RetryOn) - } - if d.PersistRule.RdpCookieName != "" { - t.Errorf("PersistRule.RdpCookieName not empty: %v", d.PersistRule.RdpCookieName) - } - if *d.Source.Address != "192.168.1.200" { - t.Errorf("Source Address not 192.168.1.200: %v", *d.Source.Address) - } - if d.Source.Port != 80 { - t.Errorf("Source Port not 80: %v", d.Source.Port) - } - if d.Source.Usesrc != "address" { - t.Errorf("Source Usesrc not address: %v", d.Source.Usesrc) - } - if d.Source.Hdr != "" { - t.Errorf("Source Hdr not empty: %v", d.Source.Hdr) - } - if d.Source.Occ != "" { - t.Errorf("Source Occ not empty: %v", d.Source.Occ) - } - if d.Source.AddressSecond != "192.168.1.201" { - t.Errorf("Source Address not 192.168.1.201 %v", d.Source.AddressSecond) - } - if d.Source.PortSecond != 443 { - t.Errorf("Source PortSecond not 443: %v", d.Source.PortSecond) - } - if d.Source.Interface != "" { - t.Errorf("Source Interface not empty: %v", d.Source.Interface) - } -} - -func TestPushDefaults(t *testing.T) { - tOut := int64(6000) - tOutS := int64(200) - balanceAlgorithm := "leastconn" - cpkaCnt := int64(10) - cpkaTimeout := int64(10000) - statsRealm := "Haproxy Stats" - d := &models.Defaults{ - Clitcpka: "disabled", - BindProcess: "1-4", - DefaultBackend: "test2", - ErrorFiles: []*models.Errorfile{ - { - Code: 400, - File: "/test/400.html", - }, - { - Code: 403, - File: "/test/403.html", - }, - { - Code: 429, - File: "/test/429.html", - }, - { - Code: 500, - File: "/test/500.html", - }, - }, - CheckTimeout: &tOutS, - ConnectTimeout: &tOut, - ServerTimeout: &tOutS, - QueueTimeout: &tOutS, - Mode: "tcp", - MonitorURI: "/healthz", - HTTPUseHtx: "enabled", - Balance: &models.Balance{ - Algorithm: &balanceAlgorithm, - }, - ExternalCheck: "", - ExternalCheckPath: "/bin", - ExternalCheckCommand: "/bin/false", - Logasap: "disabled", - Allbackups: "enabled", - HTTPCheck: &models.HTTPCheck{ - Index: misc.Int64P(0), - Type: "send-state", - }, - AcceptInvalidHTTPRequest: "disabled", - AcceptInvalidHTTPResponse: "disabled", - DisableH2Upgrade: "disabled", - LogHealthChecks: "disabled", - ClitcpkaCnt: &cpkaCnt, - ClitcpkaIdle: &cpkaTimeout, - ClitcpkaIntvl: &cpkaTimeout, - SrvtcpkaCnt: &cpkaCnt, - SrvtcpkaIdle: &cpkaTimeout, - SrvtcpkaIntvl: &cpkaTimeout, - Checkcache: "enabled", - HTTPIgnoreProbes: "enabled", - HTTPUseProxyHeader: "enabled", - Httpslog: "enabled", - IndependentStreams: "enabled", - Nolinger: "enabled", - Originalto: &models.Originalto{ - Enabled: misc.StringP("enabled"), - Except: "127.0.0.1", - Header: "X-Client-Dst", - }, - Persist: "disabled", - PreferLastServer: "disabled", - SocketStats: "disabled", - TCPSmartAccept: "disabled", - TCPSmartConnect: "disabled", - Transparent: "disabled", - DontlogNormal: "disabled", - HTTPNoDelay: "disabled", - SpliceAuto: "disabled", - SpliceRequest: "disabled", - SpliceResponse: "disabled", - IdleCloseOnResponse: "disabled", - StatsOptions: &models.StatsOptions{ - StatsShowModules: true, - StatsRealm: true, - StatsRealmRealm: &statsRealm, - StatsAuths: []*models.StatsAuth{ - {User: misc.StringP("user1"), Passwd: misc.StringP("pwd1")}, - {User: misc.StringP("user2"), Passwd: misc.StringP("pwd2")}, - }, - }, - EmailAlert: &models.EmailAlert{ - From: misc.StringP("srv01@example.com"), - To: misc.StringP("support@example.com"), - Level: "err", - Myhostname: "srv01", - Mailers: misc.StringP("localmailer1"), - }, - HTTPSendNameHeader: misc.StringP(""), - Source: &models.Source{ - Address: misc.StringP("127.0.0.1"), - Interface: "lo", - }, - } - - err := clientTest.PushDefaultsConfiguration(d, "", version) - - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - ver, defaults, err := clientTest.GetDefaultsConfiguration("") - if err != nil { - t.Error(err.Error()) - } - - var givenJSON []byte - givenJSON, err = d.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - var ondiskJSON []byte - ondiskJSON, err = defaults.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - if string(givenJSON) != string(ondiskJSON) { - fmt.Printf("Created defaults: %v\n", string(ondiskJSON)) - fmt.Printf("Given defaults: %v\n", string(givenJSON)) - t.Error("Created defaults not equal to given defaults") - } - - if ver != version { - t.Error("Version not incremented!") - } - - err = clientTest.PushDefaultsConfiguration(d, "", 1055) - - if err == nil { - t.Error("Should have returned version conflict.") - } -} - -func TestGetDefaultsSections(t *testing.T) { - v, defaults, err := clientTest.GetDefaultsSections("") - if err != nil { - t.Error(err.Error()) - } - - if len(defaults) != 3 { - t.Errorf("%v defaults returned, expected 2", len(defaults)) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - unnamedSectionFound := false - for _, d := range defaults { - if d.Name == "test_defaults" { - if d.From != "" { - t.Errorf("%s: From not empty string: %s", d.Name, d.From) - } - } - if d.Name == "test_defaults_2" { - if d.From != "test_defaults" { - t.Errorf("%s: From not test_defaults: %s", d.Name, d.From) - } - } - if d.Name == "unnamed_defaults_1" { - unnamedSectionFound = true - } - } - - if !unnamedSectionFound { - t.Errorf("Unnamed section not found") - } -} - -func TestGetDefaultsSection(t *testing.T) { - v, d, err := clientTest.GetDefaultsSection("test_defaults", "") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - if d.Name != "test_defaults" { - t.Errorf("%s: Name not test_defaults: %s", d.Name, d.Name) - } - if d.From != "" { - t.Errorf("%s: From not empty string: %s", d.Name, d.From) - } -} - -func TestEditCreateDeleteDefaultsSection(t *testing.T) { - // test creating a new section - d := &models.Defaults{ - Name: "created", - Clitcpka: "disabled", - BindProcess: "1-4", - DefaultBackend: "test2", - } - err := clientTest.CreateDefaultsSection(d, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, defaults, err := clientTest.GetDefaultsSection("created", "") - if err != nil { - t.Error(err.Error()) - } - - var givenJSON []byte - givenJSON, err = d.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - var ondiskJSON []byte - ondiskJSON, err = defaults.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - if string(givenJSON) != string(ondiskJSON) { - fmt.Printf("Created defaults: %v\n", string(ondiskJSON)) - fmt.Printf("Given defaults: %v\n", string(givenJSON)) - t.Error("Created defaults not equal to given defaults") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - err = clientTest.CreateDefaultsSection(d, "", version) - if err == nil { - t.Error("Should throw error defaults section already exists") - version++ - } - - d = &models.Defaults{ - From: "unnamed_defaults_1", - Name: "created", - Clitcpka: "enabled", - BindProcess: "1-4", - DefaultBackend: "test2", - } - err = clientTest.EditDefaultsSection("created", d, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, defaults, err = clientTest.GetDefaultsSection("created", "") - if err != nil { - t.Error(err.Error()) - } - - givenJSON, err = d.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - ondiskJSON, err = defaults.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - if string(givenJSON) != string(ondiskJSON) { - fmt.Printf("Created defaults: %v\n", string(ondiskJSON)) - fmt.Printf("Given defaults: %v\n", string(givenJSON)) - t.Error("Created defaults not equal to given defaults") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - err = clientTest.EditDefaultsSection("i_dont_exist", d, "", version) - if err == nil { - t.Error("editing non-existing defaults section succeeded") - } - - // TestDeleteDefaultsSection - err = clientTest.DeleteDefaultsSection("created", "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - if v, _ := clientTest.GetVersion(""); v != version { - t.Error("Version not incremented") - } - - _, _, err = clientTest.GetDefaultsSection("created", "") - if err == nil { - t.Error("DeleteDefaultsSection failed, defaults section created still exists") - } - - err = clientTest.DeleteDefaultsSection("i_dont_exist", "", version) - if err == nil { - t.Error("Should throw error, non existent defaults section") - version++ - } -} diff --git a/configuration/filter.go b/configuration/filter.go index 332b69df..00e3edfc 100644 --- a/configuration/filter.go +++ b/configuration/filter.go @@ -72,9 +72,9 @@ func (c *client) GetFilter(id int64, parentType, parentName string, transactionI } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -98,9 +98,9 @@ func (c *client) DeleteFilter(id int64, parentType string, parentName string, tr } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -127,9 +127,9 @@ func (c *client) CreateFilter(parentType string, parentName string, data *models } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -155,9 +155,9 @@ func (c *client) EditFilter(id int64, parentType string, parentName string, data } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -174,9 +174,9 @@ func (c *client) EditFilter(id int64, parentType string, parentName string, data func ParseFilters(t, pName string, p parser.Parser) (models.Filters, error) { section := parser.Global - if t == "frontend" { + if t == FrontendParentName { section = parser.Frontends - } else if t == "backend" { + } else if t == BackendParentName { section = parser.Backends } @@ -240,7 +240,7 @@ func ParseFilter(f types.Filter) *models.Filter { return filter case *filters.FcgiApp: return &models.Filter{ - Type: "fcgi-app", + Type: FCGIAppParentName, AppName: v.Name, } case *filters.Trace: diff --git a/configuration/filter_test.go b/configuration/filter_test.go deleted file mode 100644 index facf9d0f..00000000 --- a/configuration/filter_test.go +++ /dev/null @@ -1,249 +0,0 @@ -// 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. -// - -package configuration - -import ( - "fmt" - "reflect" - "testing" - - "github.com/haproxytech/client-native/v5/models" -) - -func TestGetFilters(t *testing.T) { //nolint:gocognit - v, filters, err := clientTest.GetFilters("frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if len(filters) != 6 { - t.Errorf("%v filters returned, expected 3", len(filters)) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - for _, f := range filters { - switch *f.Index { - case 0: - if f.Type != "trace" { - t.Errorf("%v: Type not trace: %v", *f.Index, f.Type) - } - if f.TraceName != "BEFORE-HTTP-COMP" { - t.Errorf("%v: TraceName not BEFORE-HTTP-COMP: %v", *f.Index, f.TraceName) - } - if f.TraceRndParsing != true { - t.Errorf("%v: TraceRndParsing not true: %v", *f.Index, f.TraceRndParsing) - } - if f.TraceHexdump != true { - t.Errorf("%v: TraceHexdump not true: %v", *f.Index, f.TraceHexdump) - } - case 1: - if f.Type != "compression" { - t.Errorf("%v: Type not compression: %v", *f.Index, f.Type) - } - case 2: - if f.Type != "trace" { - t.Errorf("%v: Type not trace: %v", *f.Index, f.Type) - } - if f.TraceName != "AFTER-HTTP-COMP" { - t.Errorf("%v: TraceName not AFTER-HTTP-COMP: %v", *f.Index, f.TraceName) - } - if f.TraceRndForwarding != true { - t.Errorf("%v: TraceRndForwarding not true: %v", *f.Index, f.TraceRndForwarding) - } - case 3: - if f.Type != "fcgi-app" { - t.Errorf("%v: Type not fcgi-app: %v", *f.Index, f.Type) - } - if f.AppName != "my-app" { - t.Errorf("%v: AppName not my-app: %v", *f.Index, f.AppName) - } - case 4: - if f.Type != "bwlim-in" { - t.Errorf("%v: Type not bwlim-in: %v", *f.Index, f.Type) - } - if f.BandwidthLimitName != "in" { - t.Errorf("%v: BandwidthLimitName not in: %v", *f.Index, f.BandwidthLimitName) - } - if f.DefaultLimit != 1024 { - t.Errorf("%v: DefaultLimit not 1024: %v", *f.Index, f.DefaultLimit) - } - if f.DefaultPeriod != 1000 { - t.Errorf("%v: DefaultPeriod not 1000: %v", *f.Index, f.DefaultPeriod) - } - if f.MinSize != 1048576 { - t.Errorf("%v: MinSize not 1048576: %v", *f.Index, f.MinSize) - } - case 5: - if f.Type != "bwlim-out" { - t.Errorf("%v: Type not bwlim-out: %v", *f.Index, f.Type) - } - if f.BandwidthLimitName != "out" { - t.Errorf("%v: BandwidthLimitName not out: %v", *f.Index, f.BandwidthLimitName) - } - if f.Limit != 1024 { - t.Errorf("%v: Limit not 1024: %v", *f.Index, f.Limit) - } - if f.Key != "name(arg1)" { - t.Errorf("%v: Limit not name(arg1): %v", *f.Index, f.Key) - } - if f.Table != "st_src_global" { - t.Errorf("%v: Limit not st_src_global: %v", *f.Index, f.Table) - } - if f.MinSize != 32 { - t.Errorf("%v: MinSize not 32: %v", *f.Index, f.MinSize) - } - default: - t.Errorf("Expect only filter 1, 2 or 3, %v found", *f.Index) - } - } - - _, filters, err = clientTest.GetFilters("backend", "test_2", "") - if err != nil { - t.Error(err.Error()) - } - if len(filters) > 0 { - t.Errorf("%v filters returned, expected 0", len(filters)) - } -} - -func TestGetFilter(t *testing.T) { - v, f, err := clientTest.GetFilter(0, "frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - if *f.Index != 0 { - t.Errorf("Filter ID 0, %v found", *f.Index) - } - if f.Type != "trace" { - t.Errorf("%v: Type not trace: %v", *f.Index, f.Type) - } - if f.TraceName != "BEFORE-HTTP-COMP" { - t.Errorf("%v: TraceName not BEFORE-HTTP-COMP: %v", *f.Index, f.TraceName) - } - if f.TraceRndParsing != true { - t.Errorf("%v: TraceRndParsing not true: %v", *f.Index, f.TraceRndParsing) - } - if f.TraceHexdump != true { - t.Errorf("%v: TraceHexdump not true: %v", *f.Index, f.TraceHexdump) - } - - _, err = f.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - _, _, err = clientTest.GetFilter(3, "backend", "test2", "") - if err == nil { - t.Error("Should throw error, non existent filter") - } -} - -func TestCreateEditDeleteFilter(t *testing.T) { - // TestCreateFilter - id := int64(1) - f := &models.Filter{ - Index: &id, - Type: "spoe", - SpoeEngine: "test", - SpoeConfig: "test.cfg", - } - - err := clientTest.CreateFilter("frontend", "test", f, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, ondiskF, err := clientTest.GetFilter(1, "frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if !reflect.DeepEqual(ondiskF, f) { - fmt.Printf("Created filter: %v\n", ondiskF) - fmt.Printf("Given filter: %v\n", f) - t.Error("Created filter not equal to given filter") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestEditFilter - f = &models.Filter{ - Index: &id, - Type: "spoe", - SpoeConfig: "bla.cfg", - SpoeEngine: "bla", - } - - err = clientTest.EditFilter(1, "frontend", "test", f, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, ondiskF, err = clientTest.GetFilter(1, "frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if !reflect.DeepEqual(ondiskF, f) { - fmt.Printf("Edited filter: %v\n", ondiskF) - fmt.Printf("Given filter: %v\n", f) - t.Error("Edited filter not equal to given filter") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestDeleteFilter - err = clientTest.DeleteFilter(3, "frontend", "test", "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - if v, _ := clientTest.GetVersion(""); v != version { - t.Error("Version not incremented") - } - - _, filters, _ := clientTest.GetFilters("frontend", "test", "") - _ = filters - - _, _, err = clientTest.GetFilter(6, "frontend", "test", "") - if err == nil { - t.Error("DeleteFilter failed, filter 5 still exists") - } - - err = clientTest.DeleteFilter(1, "backend", "test_2", "", version) - if err == nil { - t.Error("Should throw error, non existent filter") - version++ - } -} diff --git a/configuration/frontend_test.go b/configuration/frontend_test.go deleted file mode 100644 index 2a474b36..00000000 --- a/configuration/frontend_test.go +++ /dev/null @@ -1,675 +0,0 @@ -// 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. -// - -package configuration - -import ( - "fmt" - "reflect" - "testing" - - "github.com/haproxytech/client-native/v5/misc" - "github.com/haproxytech/client-native/v5/models" -) - -func TestGetFrontends(t *testing.T) { //nolint:gocognit - v, frontends, err := clientTest.GetFrontends("") - if err != nil { - t.Error(err.Error()) - } - - if len(frontends) != 2 { - t.Errorf("%v frontends returned, expected 2", len(frontends)) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - for _, f := range frontends { - if f.Name != "test" && f.Name != "test_2" { - t.Errorf("Expected only test or test_2 frontend, %v found", f.Name) - } - optionValue := "disabled" - if f.Name == "test" { - optionValue = "enabled" - if f.BindProcess != "odd" { - t.Errorf("%v: BindProcess not all: %v", f.Name, f.BindProcess) - } - } - if f.Name == "test_2" { - if f.From != "test_defaults" { - t.Errorf("%v: From not test_defaults: %v", f.Name, f.From) - } - } - - if f.Mode != "http" { - t.Errorf("%v: Mode not http: %v", f.Name, f.Mode) - } - if f.Dontlognull != "enabled" { - t.Errorf("%v: Dontlognull not enabled: %v", f.Name, f.Dontlognull) - } - if f.HTTPConnectionMode != "httpclose" { - t.Errorf("%v: HTTPConnectionMode not httpclose: %v", f.Name, f.HTTPConnectionMode) - } - if f.Contstats != "enabled" { - t.Errorf("%v: Contstats not enabled: %v", f.Name, f.Contstats) - } - if *f.HTTPRequestTimeout != 2000 { - t.Errorf("%v: HTTPRequestTimeout not 2: %v", f.Name, *f.HTTPRequestTimeout) - } - if *f.HTTPKeepAliveTimeout != 3000 { - t.Errorf("%v: HTTPKeepAliveTimeout not 3: %v", f.Name, *f.HTTPKeepAliveTimeout) - } - if f.DefaultBackend != "test" && f.DefaultBackend != "test_2" { - t.Errorf("%v: DefaultFarm not test or test_2: %v", f.Name, f.DefaultBackend) - } - if *f.Maxconn != 2000 { - t.Errorf("%v: Maxconn not 2000: %v", f.Name, *f.Maxconn) - } - if *f.Backlog != 2048 { - t.Errorf("%v: Backlog not 2048: %v", f.Name, *f.Backlog) - } - if *f.ClientTimeout != 4000 { - t.Errorf("%v: ClientTimeout not 4: %v", f.Name, *f.ClientTimeout) - } - if f.Tcpka != "enabled" { - t.Errorf("%v: Tcpka not enabled: %v", f.Name, f.Tcpka) - } - if f.Clitcpka != "enabled" { - t.Errorf("%v: Clitcpka not enabled: %v", f.Name, f.Clitcpka) - } - if f.ClitcpkaCnt == nil { - t.Errorf("%v: ClitcpkaCnt is nil", f.Name) - } else if *f.ClitcpkaCnt != 10 { - t.Errorf("%v: ClitcpkaCnt not 10: %v", f.Name, *f.ClitcpkaCnt) - } - if f.ClitcpkaIdle == nil { - t.Errorf("%v: ClitcpkaIdle is nil", f.Name) - } else if *f.ClitcpkaIdle != 10000 { - t.Errorf("%v: ClitcpkaIdle not 10000: %v", f.Name, *f.ClitcpkaIdle) - } - if f.ClitcpkaIntvl == nil { - t.Errorf("%v: ClitcpkaIntvl is nil", f.Name) - } else if *f.ClitcpkaIntvl != 10000 { - t.Errorf("%v: ClitcpkaIntvl not 10000: %v", f.Name, *f.ClitcpkaIntvl) - } - if f.HTTPIgnoreProbes != optionValue { - t.Errorf("%v: HTTPIgnoreProbes not %s: %v", f.Name, optionValue, f.HTTPIgnoreProbes) - } - if f.HTTPUseProxyHeader != optionValue { - t.Errorf("%v: HTTPUseProxyHeader not %s: %v", f.Name, optionValue, f.HTTPUseProxyHeader) - } - if f.Httpslog != optionValue { - t.Errorf("%v: Httpslog not %s: %v", f.Name, optionValue, f.Httpslog) - } - if f.IndependentStreams != optionValue { - t.Errorf("%v: IndependentStreams not %s: %v", f.Name, optionValue, f.IndependentStreams) - } - if f.Nolinger != optionValue { - t.Errorf("%v: Nolinger not %s: %v", f.Name, optionValue, f.Nolinger) - } - if f.Originalto == nil { - t.Errorf("%v: Originalto is nil, expected not nil", f.Name) - } else { - if *f.Originalto.Enabled != "enabled" { - t.Errorf("%v: Originalto.Enabled is not enabled: %v", f.Name, *f.Originalto.Enabled) - } - if f.Originalto.Except != "127.0.0.1" { - t.Errorf("%v: Originalto.Except is not 127.0.0.1: %v", f.Name, f.Originalto.Except) - } - if f.Name == "test" && f.Originalto.Header != "" { - t.Errorf("%v: Originalto.Header is not empty: %v", f.Name, f.Originalto.Header) - } - if f.Name == "test_2" && f.Originalto.Header != "X-Client-Dst" { - t.Errorf("%v: Originalto.Header is not X-Client-Dst: %v", f.Name, f.Originalto.Header) - } - } - if f.SocketStats != optionValue { - t.Errorf("%v: SocketStats not %s: %v", f.Name, optionValue, f.SocketStats) - } - if f.TCPSmartAccept != optionValue { - t.Errorf("%v: TCPSmartAccept not %s: %v", f.Name, optionValue, f.TCPSmartAccept) - } - if f.DontlogNormal != optionValue { - t.Errorf("%v: DontlogNormal not %s: %v", f.Name, optionValue, f.DontlogNormal) - } - if f.HTTPNoDelay != optionValue { - t.Errorf("%v: HTTPNoDelay not %s: %v", f.Name, optionValue, f.HTTPNoDelay) - } - if f.SpliceAuto != optionValue { - t.Errorf("%v: SpliceAuto not %s: %v", f.Name, optionValue, f.SpliceAuto) - } - if f.SpliceRequest != optionValue { - t.Errorf("%v: SpliceRequest not %s: %v", f.Name, optionValue, f.SpliceRequest) - } - if f.SpliceResponse != optionValue { - t.Errorf("%v: SpliceResponse not %s: %v", f.Name, optionValue, f.SpliceResponse) - } - if f.IdleCloseOnResponse != optionValue { - t.Errorf("%v: IdleCloseOnResponse not %s: %v", f.Name, optionValue, f.IdleCloseOnResponse) - } - if f.StatsOptions == nil { - t.Errorf("%v: StatsOptions is nil", f.Name) - } - if f.StatsOptions.StatsShowModules != true { - t.Errorf("%v: StatsShowModules not set", f.Name) - } - if f.StatsOptions.StatsRealm != true { - t.Errorf("%v: StatsRealm not set", f.Name) - } - if f.StatsOptions.StatsRealmRealm == nil { - t.Errorf("%v: StatsRealmRealm is nil", f.Name) - } else if *f.StatsOptions.StatsRealmRealm != `HAProxy\\ Statistics` { - t.Errorf("%v: StatsRealmRealm not 'HAProxy Statistics': %v", f.Name, *f.StatsOptions.StatsRealmRealm) - } - if len(f.StatsOptions.StatsAuths) != 2 { - t.Errorf("%v: StatsAuths expected 2 instances got: %v", f.Name, len(f.StatsOptions.StatsAuths)) - } - if f.StatsOptions.StatsAuths[0].User == nil { - t.Errorf("%v: StatsAuths 0 User is nil", f.Name) - } else if *f.StatsOptions.StatsAuths[0].User != "admin" { - t.Errorf("%v: StatsAuths 0 User not admin: %v", f.Name, *f.StatsOptions.StatsAuths[0].User) - } - if f.StatsOptions.StatsAuths[0].Passwd == nil { - t.Errorf("%v: StatsAuths 0 Passwd is nil", f.Name) - } else if *f.StatsOptions.StatsAuths[0].Passwd != "AdMiN123" { - t.Errorf("%v: StatsAuths 0 Passwd not AdMiN123: %v", f.Name, *f.StatsOptions.StatsAuths[0].Passwd) - } - if f.StatsOptions.StatsAuths[1].User == nil { - t.Errorf("%v: StatsAuths 1 User is nil", f.Name) - } else if *f.StatsOptions.StatsAuths[1].User != "admin2" { - t.Errorf("%v: StatsAuths 1 User not admin2: %v", f.Name, *f.StatsOptions.StatsAuths[1].User) - } - if f.StatsOptions.StatsAuths[1].Passwd == nil { - t.Errorf("%v: StatsAuths 1 Passwd is nil", f.Name) - } else if *f.StatsOptions.StatsAuths[1].Passwd != "AdMiN1234" { - t.Errorf("%v: StatsAuths 1 Passwd not AdMiN1234: %v", f.Name, *f.StatsOptions.StatsAuths[1].Passwd) - } - } -} - -func TestGetFrontend(t *testing.T) { - v, f, err := clientTest.GetFrontend("test", "") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - if f.Name != "test" { - t.Errorf("Expected only test, %v found", f.Name) - } - if f.BindProcess != "odd" { - t.Errorf("%v: BindProcess not all: %v", f.Name, f.BindProcess) - } - if f.Mode != "http" { - t.Errorf("%v: Mode not http: %v", f.Name, f.Mode) - } - if f.MonitorURI != "/healthz" { - t.Errorf("%v: MonitorURI not /healthz: %v", f.Name, f.MonitorURI) - } - if f.MonitorFail == nil { - t.Errorf("%v: MonitorFail is nil", f.Name) - } - if *f.MonitorFail.Cond != "if" { - t.Errorf("%v: MonitorFail condition not if: %v", f.Name, *f.MonitorFail.Cond) - } - if *f.MonitorFail.CondTest != "site_dead" { - t.Errorf("%v: MonitorFail condition test not site_dead: %v", f.Name, *f.MonitorFail.CondTest) - } - if f.Dontlognull != "enabled" { - t.Errorf("%v: Dontlognull not enabled: %v", f.Name, f.Dontlognull) - } - if f.HTTPConnectionMode != "httpclose" { - t.Errorf("%v: HTTPConnectionMode not httpclose: %v", f.Name, f.HTTPConnectionMode) - } - if f.HTTPRestrictReqHdrNames != "delete" { - t.Errorf("%v: HTTPRestrictReqHdrNames not delete: %v", f.Name, f.HTTPRestrictReqHdrNames) - } - if f.Contstats != "enabled" { - t.Errorf("%v: Contstats not enabled: %v", f.Name, f.Contstats) - } - if *f.HTTPRequestTimeout != 2000 { - t.Errorf("%v: HTTPRequestTimeout not 2000: %v", f.Name, *f.HTTPRequestTimeout) - } - if *f.HTTPKeepAliveTimeout != 3000 { - t.Errorf("%v: HTTPKeepAliveTimeout not 3000: %v", f.Name, *f.HTTPKeepAliveTimeout) - } - if f.DefaultBackend != "test" { - t.Errorf("%v: DefaultBackend not test: %v", f.Name, f.DefaultBackend) - } - if *f.Maxconn != 2000 { - t.Errorf("%v: Maxconn not 2000: %v", f.Name, *f.Maxconn) - } - if *f.Backlog != 2048 { - t.Errorf("%v: Backlog not 2048: %v", f.Name, *f.Backlog) - } - if *f.ClientTimeout != 4000 { - t.Errorf("%v: ClientTimeout not 4000: %v", f.Name, *f.ClientTimeout) - } - if *f.ClientFinTimeout != 1000 { - t.Errorf("%v: ServerFinTimeout not 1000: %v", f.Name, *f.ClientFinTimeout) - } - if *f.TarpitTimeout != 2000 { - t.Errorf("%v: TarpitTimeout not 2000: %v", f.Name, *f.TarpitTimeout) - } - if f.AcceptInvalidHTTPRequest != "disabled" { - t.Errorf("%v: AcceptInvalidHTTPRequest not disabled: %v", f.Name, f.AcceptInvalidHTTPRequest) - } - if f.H1CaseAdjustBogusClient != "disabled" { - t.Errorf("%v: H1CaseAdjustBogusClient not disabled: %v", f.Name, f.H1CaseAdjustBogusClient) - } - if f.Tcpka != "enabled" { - t.Errorf("%v: Tcpka not enabled: %v", f.Name, f.Tcpka) - } - if f.Clitcpka != "enabled" { - t.Errorf("%v: Clitcpka not enabled: %v", f.Name, f.Clitcpka) - } - if f.ClitcpkaCnt == nil { - t.Errorf("%v: ClitcpkaCnt is nil", f.Name) - } else if *f.ClitcpkaCnt != 10 { - t.Errorf("%v: ClitcpkaCnt not 10: %v", f.Name, *f.ClitcpkaCnt) - } - if f.ClitcpkaIdle == nil { - t.Errorf("%v: ClitcpkaIdle is nil", f.Name) - } else if *f.ClitcpkaIdle != 10000 { - t.Errorf("%v: ClitcpkaIdle not 10000: %v", f.Name, *f.ClitcpkaIdle) - } - if f.ClitcpkaIntvl == nil { - t.Errorf("%v: ClitcpkaIntvl is nil", f.Name) - } else if *f.ClitcpkaIntvl != 10000 { - t.Errorf("%v: ClitcpkaIntvl not 10000: %v", f.Name, *f.ClitcpkaIntvl) - } - if f.Compression == nil { - t.Errorf("%v: Compression is nil", f.Name) - } else { - if len(f.Compression.Algorithms) != 2 { - t.Errorf("%v: len Compression.Algorithms not 2: %v", f.Name, len(f.Compression.Algorithms)) - } else { - if !(f.Compression.Algorithms[0] == "identity" || f.Compression.Algorithms[0] != "gzip") { - t.Errorf("%v: Compression.Algorithms[0] wrong: %v", f.Name, f.Compression.Algorithms[0]) - } - if !(f.Compression.Algorithms[1] != "identity" || f.Compression.Algorithms[0] != "gzip") { - t.Errorf("%v: Compression.Algorithms[1] wrong: %v", f.Name, f.Compression.Algorithms[1]) - } - } - if len(f.Compression.Types) != 1 { - t.Errorf("%v: len Compression.Types not 1: %v", f.Name, len(f.Compression.Types)) - } else { - if f.Compression.Types[0] != "text/plain" { - t.Errorf("%v: Compression.Types[0] wrong: %v", f.Name, f.Compression.Types[0]) - } - } - if !f.Compression.Offload { - t.Errorf("%v: Compression.Offload wrong: %v", f.Name, f.Compression.Offload) - } - } - - if f.HTTPIgnoreProbes != "enabled" { - t.Errorf("%v: HTTPIgnoreProbes not enablesd: %v", f.Name, f.HTTPIgnoreProbes) - } - if f.HTTPUseProxyHeader != "enabled" { - t.Errorf("%v: HTTPUseProxyHeader not enablesd: %v", f.Name, f.HTTPUseProxyHeader) - } - if f.Httpslog != "enabled" { - t.Errorf("%v: Httpslog not enablesd: %v", f.Name, f.Httpslog) - } - if f.IndependentStreams != "enabled" { - t.Errorf("%v: IndependentStreams not enablesd: %v", f.Name, f.IndependentStreams) - } - if f.Nolinger != "enabled" { - t.Errorf("%v: Nolinger not enablesd: %v", f.Name, f.Nolinger) - } - if f.Originalto == nil { - t.Errorf("%v: Originalto is nil, expected not nil", f.Name) - } else { - if *f.Originalto.Enabled != "enabled" { - t.Errorf("%v: Originalto.Enabled is not enabled: %v", f.Name, *f.Originalto.Enabled) - } - if f.Originalto.Except != "127.0.0.1" { - t.Errorf("%v: Originalto.Except is not 127.0.0.1: %v", f.Name, f.Originalto.Except) - } - if f.Originalto.Header != "" { - t.Errorf("%v: Originalto.Header is not empty: %v", f.Name, f.Originalto.Header) - } - } - if f.SocketStats != "enabled" { - t.Errorf("%v: SocketStats not enablesd: %v", f.Name, f.SocketStats) - } - if f.TCPSmartAccept != "enabled" { - t.Errorf("%v: TCPSmartAccept not enablesd: %v", f.Name, f.TCPSmartAccept) - } - if f.DontlogNormal != "enabled" { - t.Errorf("%v: DontlogNormal not enablesd: %v", f.Name, f.DontlogNormal) - } - if f.HTTPNoDelay != "enabled" { - t.Errorf("%v: HTTPNoDelay not enablesd: %v", f.Name, f.HTTPNoDelay) - } - if f.SpliceAuto != "enabled" { - t.Errorf("%v: SpliceAuto not enablesd: %v", f.Name, f.SpliceAuto) - } - if f.SpliceRequest != "enabled" { - t.Errorf("%v: SpliceRequest not enablesd: %v", f.Name, f.SpliceRequest) - } - if f.SpliceResponse != "enabled" { - t.Errorf("%v: SpliceResponse not enablesd: %v", f.Name, f.SpliceResponse) - } - if f.IdleCloseOnResponse != "enabled" { - t.Errorf("%v: IdleCloseOnResponse not enablesd: %v", f.Name, f.IdleCloseOnResponse) - } - if f.StatsOptions == nil { - t.Errorf("%v: StatsOptions is nil", f.Name) - } - if f.StatsOptions.StatsShowModules != true { - t.Errorf("%v: StatsShowModules not set", f.Name) - } - if f.StatsOptions.StatsRealm != true { - t.Errorf("%v: StatsRealm not set", f.Name) - } - if f.StatsOptions.StatsRealmRealm == nil { - t.Errorf("%v: StatsRealmRealm is nil", f.Name) - } else if *f.StatsOptions.StatsRealmRealm != `HAProxy\\ Statistics` { - t.Errorf("%v: StatsRealmRealm not 'HAProxy Statistics': %v", f.Name, *f.StatsOptions.StatsRealmRealm) - } - if len(f.StatsOptions.StatsAuths) != 2 { - t.Errorf("%v: StatsAuths expected 2 instances got: %v", f.Name, len(f.StatsOptions.StatsAuths)) - } - if f.StatsOptions.StatsAuths[0].User == nil { - t.Errorf("%v: StatsAuths 0 User is nil", f.Name) - } else if *f.StatsOptions.StatsAuths[0].User != "admin" { - t.Errorf("%v: StatsAuths 0 User not admin: %v", f.Name, *f.StatsOptions.StatsAuths[0].User) - } - if f.StatsOptions.StatsAuths[0].Passwd == nil { - t.Errorf("%v: StatsAuths 0 Passwd is nil", f.Name) - } else if *f.StatsOptions.StatsAuths[0].Passwd != "AdMiN123" { - t.Errorf("%v: StatsAuths 0 Passwd not AdMiN123: %v", f.Name, *f.StatsOptions.StatsAuths[0].Passwd) - } - if f.StatsOptions.StatsAuths[1].User == nil { - t.Errorf("%v: StatsAuths 1 User is nil", f.Name) - } else if *f.StatsOptions.StatsAuths[1].User != "admin2" { - t.Errorf("%v: StatsAuths 1 User not admin2: %v", f.Name, *f.StatsOptions.StatsAuths[1].User) - } - if f.StatsOptions.StatsAuths[1].Passwd == nil { - t.Errorf("%v: StatsAuths 1 Passwd is nil", f.Name) - } else if *f.StatsOptions.StatsAuths[1].Passwd != "AdMiN1234" { - t.Errorf("%v: StatsAuths 1 Passwd not AdMiN1234: %v", f.Name, *f.StatsOptions.StatsAuths[1].Passwd) - } - if f.Description != "this is a frontend description" { - t.Errorf("%v: Description not `this is a frontend description`: %v", f.Name, f.Description) - } - if !f.Disabled { - t.Errorf("%v: Disabled not enabled", f.Name) - } - if *f.ID != 123 { - t.Errorf("ID not 123: %v", *f.ID) - } - if *f.Errorloc302.Code != 404 { - t.Errorf("%v: Errorloc302 Code not 404: %v", f.Name, *f.Errorloc302.Code) - } - if *f.Errorloc302.URL != "http://www.myawesomesite.com/not_found" { - t.Errorf("%v: Errorloc302 Code not http://www.myawesomesite.com/not_found: %v", f.Name, *f.Errorloc302.URL) - } - if *f.Errorloc303.Code != 404 { - t.Errorf("%v: Errorloc302 Code not 404: %v", f.Name, *f.Errorloc303.Code) - } - if *f.Errorloc303.URL != "http://www.myawesomesite.com/not_found" { - t.Errorf("%v: Errorloc302 Code not http://www.myawesomesite.com/not_found: %v", f.Name, *f.Errorloc303.URL) - } - if f.ErrorLogFormat != "%T\\ %t\\ Some\\ Text" { - t.Errorf("%v: Errorloc302 Code not %%T\\ %%t\\ Some\\ Text: %v", f.Name, *f.Errorloc302.URL) - } - if len(f.ErrorFiles) != 3 { - t.Errorf("ErrorFiles not 3: %v", len(f.ErrorFiles)) - } else { - for _, ef := range f.ErrorFiles { - if ef.Code == 403 { - if ef.File != "/test/403.html" { - t.Errorf("File for %v not 403: %v", ef.Code, ef.File) - } - } - if ef.Code == 500 { - if ef.File != "/test/500.html" { - t.Errorf("File for %v not 500: %v", ef.Code, ef.File) - } - } - if ef.Code == 429 { - if ef.File != "/test/429.html" { - t.Errorf("File for %v not 429: %v", ef.Code, ef.File) - } - } - } - } - - if f.EmailAlert == nil { - t.Errorf("EmailAlert is nil") - } else if *f.EmailAlert.From != "srv01@example.com" { - t.Errorf("EmailAlert.From is not srv01@example.com: %v", *f.EmailAlert.From) - } else if *f.EmailAlert.To != "problems@example.com" { - t.Errorf("EmailAlert.To is not problems@example.com: %v", *f.EmailAlert.To) - } else if f.EmailAlert.Level != "warning" { - t.Errorf("EmailAlert.Level is not warning: %v", f.EmailAlert.Level) - } else if f.EmailAlert.Myhostname != "srv01" { - t.Errorf("EmailAlert.Myhostname is not srv01: %v", f.EmailAlert.Myhostname) - } else if *f.EmailAlert.Mailers != "localmailer1" { - t.Errorf("EmailAlert.Mailers is not localmailer1: %v", *f.EmailAlert.Mailers) - } - - _, err = f.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - _, _, err = clientTest.GetFrontend("doesnotexist", "") - if err == nil { - t.Error("Should throw error, non existent frontend") - } -} - -func TestCreateEditDeleteFrontend(t *testing.T) { - // TestCreateFrontend - mConn := int64(3000) - tOut := int64(2) - clitcpkaCnt := int64(10) - clitcpkaTimeout := int64(10000) - statsRealm := "Haproxy Stats" - f := &models.Frontend{ - From: "unnamed_defaults_1", - Name: "created", - Mode: "tcp", - Maxconn: &mConn, - Httplog: true, - HTTPConnectionMode: "http-keep-alive", - HTTPKeepAliveTimeout: &tOut, - BindProcess: "4", - Logasap: "disabled", - UniqueIDFormat: "%{+X}o_%fi:%fp_%Ts_%rt:%pid", - UniqueIDHeader: "X-Unique-Id", - AcceptInvalidHTTPRequest: "enabled", - DisableH2Upgrade: "enabled", - ClitcpkaCnt: &clitcpkaCnt, - ClitcpkaIdle: &clitcpkaTimeout, - ClitcpkaIntvl: &clitcpkaTimeout, - HTTPIgnoreProbes: "enabled", - HTTPUseProxyHeader: "enabled", - Httpslog: "enabled", - IndependentStreams: "enabled", - Nolinger: "enabled", - Originalto: &models.Originalto{ - Enabled: misc.StringP("enabled"), - Except: "127.0.0.1", - Header: "X-Client-Dst", - }, - SocketStats: "enabled", - TCPSmartAccept: "enabled", - DontlogNormal: "enabled", - HTTPNoDelay: "enabled", - SpliceAuto: "enabled", - SpliceRequest: "enabled", - SpliceResponse: "enabled", - IdleCloseOnResponse: "enabled", - StatsOptions: &models.StatsOptions{ - StatsShowModules: true, - StatsRealm: true, - StatsRealmRealm: &statsRealm, - StatsAuths: []*models.StatsAuth{ - {User: misc.StringP("user1"), Passwd: misc.StringP("pwd1")}, - {User: misc.StringP("user2"), Passwd: misc.StringP("pwd2")}, - }, - }, - Enabled: true, - } - - err := clientTest.CreateFrontend(f, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, frontend, err := clientTest.GetFrontend("created", "") - if err != nil { - t.Error(err.Error()) - } - - if !reflect.DeepEqual(frontend, f) { - fmt.Printf("Created frontend: %v\n", frontend) - fmt.Printf("Given frontend: %v\n", f) - t.Error("Created frontend not equal to given frontend") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - err = clientTest.CreateFrontend(f, "", version) - if err == nil { - t.Error("Should throw error frontend already exists") - version++ - } - - // TestEditFrontend - mConn = int64(4000) - f = &models.Frontend{ - Name: "created", - Mode: "tcp", - Maxconn: &mConn, - Backlog: misc.Int64P(1024), - Clflog: true, - HTTPConnectionMode: "httpclose", - BindProcess: "3", - MonitorURI: "/healthz", - MonitorFail: &models.MonitorFail{ - Cond: misc.StringP("if"), - CondTest: misc.StringP("site_is_dead"), - }, - Compression: &models.Compression{ - Offload: true, - }, - ClitcpkaCnt: &clitcpkaCnt, - ClitcpkaIdle: &clitcpkaTimeout, - ClitcpkaIntvl: &clitcpkaTimeout, - HTTPIgnoreProbes: "disabled", - HTTPUseProxyHeader: "disabled", - Httpslog: "disabled", - IndependentStreams: "disabled", - Nolinger: "disabled", - Originalto: &models.Originalto{ - Enabled: misc.StringP("enabled"), - Except: "127.0.0.1", - Header: "X-Client-Dst", - }, - SocketStats: "disabled", - TCPSmartAccept: "disabled", - DontlogNormal: "disabled", - HTTPNoDelay: "disabled", - SpliceAuto: "disabled", - SpliceRequest: "disabled", - SpliceResponse: "disabled", - IdleCloseOnResponse: "disabled", - StatsOptions: &models.StatsOptions{ - StatsShowModules: true, - StatsRealm: true, - StatsRealmRealm: &statsRealm, - StatsAuths: []*models.StatsAuth{ - {User: misc.StringP("new_user1"), Passwd: misc.StringP("new_pwd1")}, - {User: misc.StringP("new_user2"), Passwd: misc.StringP("new_pwd2")}, - }, - }, - EmailAlert: &models.EmailAlert{ - From: misc.StringP("srv01@example.com"), - To: misc.StringP("problems@example.com"), - Level: "warning", - Mailers: misc.StringP("localmailer1"), - }, - } - - err = clientTest.EditFrontend("created", f, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, frontend, err = clientTest.GetFrontend("created", "") - if err != nil { - t.Error(err.Error()) - } - - if !reflect.DeepEqual(frontend, f) { - fmt.Printf("Edited frontend: %v\n", frontend) - fmt.Printf("Given frontend: %v\n", f) - t.Error("Edited frontend not equal to given frontend") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestDeleteFrontend - err = clientTest.DeleteFrontend("created", "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - if v, _ := clientTest.GetVersion(""); v != version { - t.Error("Version not incremented") - } - - err = clientTest.DeleteFrontend("created", "", 999999) - if err != nil { - if confErr, ok := err.(*ConfError); ok { - if !confErr.Is(ErrVersionMismatch) { - t.Error("Should throw ErrVersionMismatch error") - } - } else { - t.Error("Should throw ErrVersionMismatch error") - } - } - _, _, err = clientTest.GetFrontend("created", "") - if err == nil { - t.Error("DeleteFrontend failed, frontend test still exists") - } - - err = clientTest.DeleteFrontend("doesnotexist", "", version) - if err == nil { - t.Error("Should throw error, non existent frontend") - version++ - } -} diff --git a/configuration/global_test.go b/configuration/global_test.go deleted file mode 100644 index 05b38807..00000000 --- a/configuration/global_test.go +++ /dev/null @@ -1,840 +0,0 @@ -// 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. -// - -package configuration - -import ( - "fmt" - "testing" - - "github.com/haproxytech/client-native/v5/misc" - "github.com/haproxytech/client-native/v5/models" -) - -func TestGetGlobal(t *testing.T) { - v, global, err := clientTest.GetGlobalConfiguration("") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - if global.Daemon != "enabled" { - t.Errorf("Daemon is %v, expected enabled", global.Daemon) - } - if *global.Anonkey != 25 { - t.Errorf("Anonkey is %v, expected 25", *global.Anonkey) - } - if len(global.RuntimeAPIs) == 1 { - if *global.RuntimeAPIs[0].Address != "/var/run/haproxy.sock" { - t.Errorf("RuntimeAPI.Address is %v, expected /var/run/haproxy.sock", *global.RuntimeAPIs[0].Address) - } - if global.RuntimeAPIs[0].Level != "admin" { - t.Errorf("RuntimeAPI.Level is %v, expected admin", global.RuntimeAPIs[0].Level) - } - if global.RuntimeAPIs[0].Mode != "0660" { - t.Errorf("RuntimeAPI.Mode is %v, expected 0660", global.RuntimeAPIs[0].Mode) - } - } else { - t.Errorf("RuntimeAPI is not set") - } - if global.ClusterSecret != "my_secret" { - t.Errorf("ClusterSecret is %v, expected my_secret", global.ClusterSecret) - } - if global.CaBase != "/etc/ssl/certs" { - t.Errorf("CaBase is %v, expected /etc/ssl/certs", global.CaBase) - } - if global.CrtBase != "/etc/ssl/private" { - t.Errorf("CrtBase is %v, expected /etc/ssl/private", global.CrtBase) - } - if global.Nbproc != 4 { - t.Errorf("Nbproc is %v, expected 4", global.Nbproc) - } - if global.Maxconn != 2000 { - t.Errorf("Maxconn is %v, expected 2000", global.Maxconn) - } - if global.ExternalCheck != true { - t.Errorf("ExternalCheck is false, expected true") - } - if len(global.LuaPrependPath) == 2 { - if *global.LuaPrependPath[0].Path != "/usr/share/haproxy-lua/?/init.lua" { - t.Errorf("LuaPrependPath.Path is %v, expected /usr/share/haproxy-lua/?/init.lua", *global.LuaPrependPath[0].Path) - } - if *global.LuaPrependPath[1].Path != "/usr/share/haproxy-lua/?.lua" { - t.Errorf("LuaPrependPath.Path is %v, expected /usr/share/haproxy-lua/?.lua", global.LuaPrependPath[1].Path) - } - typ := "cpath" - if global.LuaPrependPath[1].Type != typ { - t.Errorf("LuaPrependPath.Type is %v, expected cpath", global.LuaPrependPath[1].Type) - } - } else { - t.Errorf("%v LuaPrependPath returned, expected 2", len(global.LuaPrependPath)) - } - if len(global.LuaLoads) == 2 { - if *global.LuaLoads[0].File != "/etc/foo.lua" { - t.Errorf("LuaLoad.File is %v, expected /etc/foo.lua", *global.LuaLoads[0].File) - } - if *global.LuaLoads[1].File != "/etc/bar.lua" { - t.Errorf("LuaLoad.File is %v, expected /etc/bar.lua", global.LuaLoads[1].File) - } - } else { - t.Errorf("%v LuaLoads returned, expected 2", len(global.LuaLoads)) - } - if len(global.H1CaseAdjusts) == 2 { - if *global.H1CaseAdjusts[0].From != "host" { - t.Errorf("H1CaseAdjusts[0].From is %v, expected host", *global.H1CaseAdjusts[0].From) - } - if *global.H1CaseAdjusts[0].To != "Host" { - t.Errorf("H1CaseAdjusts[0].To is %v, expected Host", *global.H1CaseAdjusts[0].To) - } - if *global.H1CaseAdjusts[1].From != "content-type" { - t.Errorf("H1CaseAdjusts[1].From is %v, expected content-type", *global.H1CaseAdjusts[1].From) - } - if *global.H1CaseAdjusts[1].To != "Content-Type" { - t.Errorf("H1CaseAdjusts[1].To is %v, expected Content-Type", *global.H1CaseAdjusts[1].To) - } - } - if global.H1CaseAdjustFile != "/etc/headers.adjust" { - t.Errorf("H1CaseAdjustFile is %v, expected /etc/headers.adjust", global.H1CaseAdjustFile) - } - if global.UID != 1 { - t.Errorf("UID is %v, expected 1", global.UID) - } - if global.Gid != 1 { - t.Errorf("Gid is %v, expected 1", global.Gid) - } - if global.BusyPolling != true { - t.Errorf("BusyPolling is false, expected true") - } - if *global.CloseSpreadTime != 1000 { - t.Errorf("CloseSpreadTime is %v, expected 1000", global.CloseSpreadTime) - } - if *global.MaxSpreadChecks != 1 { - t.Errorf("MaxSpreadChecks is %v, expected 1", global.MaxSpreadChecks) - } - if global.Maxconnrate != 2 { - t.Errorf("Maxconnrate is %v, expected 2", global.Maxconnrate) - } - if global.Maxcomprate != 3 { - t.Errorf("Maxcomprate is %v, expected 3", global.Maxcomprate) - } - if global.Maxcompcpuusage != 4 { - t.Errorf("Maxcompcpuusage is %v, expected 4", global.Maxcompcpuusage) - } - if global.Maxpipes != 5 { - t.Errorf("Maxpipes is %v, expected 5", global.Maxpipes) - } - if global.Maxsessrate != 6 { - t.Errorf("Maxsessrate is %v, expected 6", global.Maxsessrate) - } - if global.Maxsslconn != 7 { - t.Errorf("Maxsslconn is %v, expected 7", global.Maxsslconn) - } - if global.Maxsslrate != 8 { - t.Errorf("Maxsslrate is %v, expected 8", global.Maxsslrate) - } - if global.Maxzlibmem != 9 { - t.Errorf("Maxzlibmem is %v, expected 9", global.Maxzlibmem) - } - if global.NoQuic != true { - t.Errorf("NoQuic is false, expected true") - } - if global.Noepoll != true { - t.Errorf("Noepoll is false, expected true") - } - if global.Nosplice != true { - t.Errorf("Nosplice is false, expected true") - } - if global.Nogetaddrinfo != true { - t.Errorf("Nogetaddrinfo is false, expected true") - } - if global.Noreuseport != true { - t.Errorf("Noreuseport is false, expected true") - } - if global.ProfilingTasks != "enabled" { - t.Errorf("ProfilingTasks is %s, expected on", global.ProfilingTasks) - } - if global.SpreadChecks != 10 { - t.Errorf("SpreadChecks is %v, expected 10", global.SpreadChecks) - } - if global.ServerStateBase != "/path" { - t.Errorf("ServerStateBase is %v, expected /path", global.ServerStateBase) - } - if global.ServerStateFile != "serverstatefile" { - t.Errorf("ServerStateFile is %v, expected serverstatefile", global.ServerStateFile) - } - if global.WurflOptions.DataFile != "path" { - t.Errorf("WurflDataFile is %v, expected path", global.WurflOptions.DataFile) - } - if global.WurflOptions.InformationList != "wurfl_id,wurfl_root_id,wurfl_isdevroot,wurfl_useragent,wurfl_api_version,wurfl_info,wurfl_last_load_time,wurfl_normalized_useragent" { - t.Errorf("WurflInformationList is %v, expected wurfl_id,wurfl_root_id,wurfl_isdevroot,wurfl_useragent,wurfl_api_version,wurfl_info,wurfl_last_load_time,wurfl_normalized_useragent", global.WurflOptions.InformationList) - } - if global.WurflOptions.InformationListSeparator != "," { - t.Errorf("WurflInformationListSeparator is %v, expected ,", global.WurflOptions.InformationListSeparator) - } - if global.WurflOptions.PatchFile != "path1,path2" { - t.Errorf("WurflPatchFile is %v, expected path1,path2", global.WurflOptions.PatchFile) - } - if global.WurflOptions.CacheSize != 64 { - t.Errorf("WurflCacheSize is %v, expected 64", global.WurflOptions.CacheSize) - } - if global.SslDefaultBindCurves != "X25519:P-256" { - t.Errorf("SslDefaultBindCurves is %v, expected X25519:P-256", global.SslDefaultBindCurves) - } - if global.SslDefaultServerCurves != "brainpoolP384r1,brainpoolP512r1" { - t.Errorf("SslDefaultServerCurves is %v, expected brainpoolP384r1,brainpoolP512r1", global.SslDefaultServerCurves) - } - if global.SslSkipSelfIssuedCa != true { - t.Errorf("SslSkipSelfIssuedCa is %v, expected enabled", global.SslSkipSelfIssuedCa) - } - if global.Node != "node" { - t.Errorf("Node is %v, expected node", global.Node) - } - if global.Description != "description" { - t.Errorf("Description is %v, expected description", global.Description) - } - if global.ExposeExperimentalDirectives != true { - t.Errorf("ExposeExperimentalDirectives is %v, expected enabled", global.ExposeExperimentalDirectives) - } - if global.InsecureForkWanted != true { - t.Errorf("InsecureForkWanted is %v, expected enabled", global.InsecureForkWanted) - } - if global.InsecureSetuidWanted != true { - t.Errorf("InsecureSetuidWanted is %v, expected enabled", global.InsecureSetuidWanted) - } - if global.IssuersChainPath != "issuers-chain-path" { - t.Errorf("IssuersChainPath is %v, expected issuers-chain-path", global.IssuersChainPath) - } - if global.H2WorkaroundBogusWebsocketClients != true { - t.Errorf("H2WorkaroundBogusWebsocketClients is %v, expected enabled", global.H2WorkaroundBogusWebsocketClients) - } - if global.LuaLoadPerThread != "file.ext" { - t.Errorf("LuaLoadPerThread is %v, expected file.ext", global.LuaLoadPerThread) - } - if *global.MworkerMaxReloads != 5 { - t.Errorf("MworkerMaxReloads is %v, expected 5", global.MworkerMaxReloads) - } - if global.NumaCPUMapping != "enabled" { - t.Errorf("NumaCPUMapping is %v, expected enabled", global.NumaCPUMapping) - } - if global.Pp2NeverSendLocal != true { - t.Errorf("Pp2NeverSendLocal is %v, expected enabled", global.Pp2NeverSendLocal) - } - if global.Ulimitn != 10 { - t.Errorf("Ulimitn is %v, expected 10", global.Ulimitn) - } - if global.SetDumpable != true { - t.Errorf("SetDumpable is %v, expected enabled", global.SetDumpable) - } - if global.StrictLimits != true { - t.Errorf("StrictLimits is %v, expected enabled", global.StrictLimits) - } - if *global.Grace != 10000 { - t.Errorf("Grace is %v, expected 10000", global.Grace) - } - if global.SslDefaultServerCiphers != "ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES256:ECDH+AES128:!aNULL:!SHA1:!AESCCM" { - t.Errorf("SslDefaultServerCiphers is %v, expected %v", global.SslDefaultServerCiphers, "ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES256:ECDH+AES128:!aNULL:!SHA1:!AESCCM") - } - if global.SslDefaultServerCiphersuites != "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256" { - t.Errorf("SslDefaultServerCiphersuites is %v, expected %v", global.SslDefaultServerCiphersuites, "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256") - } - if global.Chroot != "/var/www" { - t.Errorf("Chroot is %v, expected /var/www", global.Chroot) - } - if *global.HardStopAfter != 2000 { - t.Errorf("HardStopAfter is %v, expected 20000", global.HardStopAfter) - } - if global.Localpeer != "test" { - t.Errorf("Localpeer is %v, expected test", global.Localpeer) - } - if global.User != "thomas" { - t.Errorf("User is %v, expected thomas", global.User) - } - if global.Group != "anderson" { - t.Errorf("Group is %v, expected anderson", global.Group) - } - if global.Nbthread != 128 { - t.Errorf("Nbthread is %v, expected 128", global.Nbthread) - } - if global.Pidfile != "pidfile.text" { - t.Errorf("Pidfile is %v, expected pidfile.text", global.Pidfile) - } - if global.SslDefaultBindCiphers != "ECDH+AESGCM:ECDH+CHACHA20" { - t.Errorf("SslDefaultBindCiphers is %v, expected %v", global.SslDefaultBindCiphers, "ECDH+AESGCM:ECDH+CHACHA20") - } - if global.SslDefaultBindCiphersuites != "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384" { - t.Errorf("SslDefaultBindCiphersuites is %v, expected %v", global.SslDefaultBindCiphersuites, "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384") - } - if global.SslDefaultServerOptions != "ssl-min-ver TLSv1.1 no-tls-tickets" { - t.Errorf("SslDefaultServerOptions is %v, expected ssl-min-ver TLSv1.1 no-tls-tickets", global.SslDefaultServerOptions) - } - if *global.TuneOptions.BuffersLimit != 11 { - t.Errorf("BuffersLimit is %v, expected 11", global.TuneOptions.BuffersLimit) - } - if global.TuneOptions.BuffersReserve != 12 { - t.Errorf("BuffersReserve is %v, expected 12", global.TuneOptions.BuffersReserve) - } - if global.TuneOptions.Bufsize != 13 { - t.Errorf("Bufsize is %v, expected 13", global.TuneOptions.Bufsize) - } - if global.TuneOptions.CompMaxlevel != 14 { - t.Errorf("CompMaxlevel is %v, expected 14", global.TuneOptions.CompMaxlevel) - } - if !global.TuneOptions.DisableZeroCopyForwarding { - t.Errorf("DisableZeroCopyForwarding is %v, expected true", global.TuneOptions.DisableZeroCopyForwarding) - } - if global.TuneOptions.EventsMaxEventsAtOnce != 10 { - t.Errorf("TuneOptions.EventsMaxEventsAtOnce is %v, expected 10", global.TuneOptions.EventsMaxEventsAtOnce) - } - if global.TuneOptions.H1ZeroCopyFwdRecv != "enabled" { - t.Errorf("H1ZeroCopyFwdRecv is %v, expected enabled", global.TuneOptions.H1ZeroCopyFwdRecv) - } - if global.TuneOptions.H1ZeroCopyFwdSend != "enabled" { - t.Errorf("H1ZeroCopyFwdSend is %v, expected enabled", global.TuneOptions.H1ZeroCopyFwdSend) - } - if global.TuneOptions.H2HeaderTableSize != 15 { - t.Errorf("H2HeaderTableSize is %v, expected 15", global.TuneOptions.H2HeaderTableSize) - } - if *global.TuneOptions.H2InitialWindowSize != 16 { - t.Errorf("H2InitialWindowSize is %v, expected 16", global.TuneOptions.H2InitialWindowSize) - } - if global.TuneOptions.H2MaxConcurrentStreams != 17 { - t.Errorf("H2MaxConcurrentStreams is %v, expected 17", global.TuneOptions.H2MaxConcurrentStreams) - } - if global.TuneOptions.H2MaxFrameSize != 18 { - t.Errorf("H2MaxFrameSize is %v, expected 18", global.TuneOptions.H2MaxFrameSize) - } - if global.TuneOptions.H2ZeroCopyFwdSend != "enabled" { - t.Errorf("H2ZeroCopyFwdSend is %v, expected enabled", global.TuneOptions.H2ZeroCopyFwdSend) - } - if global.TuneOptions.HTTPCookielen != 19 { - t.Errorf("HTTPCookielen is %v, expected 19", global.TuneOptions.HTTPCookielen) - } - if global.TuneOptions.HTTPLogurilen != 20 { - t.Errorf("HTTPLogurilen is %v, expected 20", global.TuneOptions.HTTPLogurilen) - } - if global.TuneOptions.HTTPMaxhdr != 21 { - t.Errorf("HTTPMaxhdr is %v, expected 21", global.TuneOptions.HTTPMaxhdr) - } - if *global.TuneOptions.Idletimer != 22 { - t.Errorf("Idletimer is %v, expected 22", global.TuneOptions.Idletimer) - } - if global.TuneOptions.ListenerDefaultShards != "by-process" { - t.Errorf("ListenerDefaultShards is %v, expected by-process", global.TuneOptions.ListenerDefaultShards) - } - if global.TuneOptions.LuaForcedYield != 23 { - t.Errorf("LuaForcedYield is %v, expected 23", global.TuneOptions.LuaForcedYield) - } - if global.TuneOptions.LuaLogLoggers != "enabled" { - t.Errorf("LuaLogLoggers is %v, expected on", global.TuneOptions.LuaLogLoggers) - } - if global.TuneOptions.LuaLogStderr != "auto" { - t.Errorf("LuaLogStderr is %v, expected auto", global.TuneOptions.LuaLogStderr) - } - if global.TuneOptions.LuaMaxmem != true { - t.Errorf("Maxzlibmem is false, expected true") - } - if *global.TuneOptions.LuaSessionTimeout != 25 { - t.Errorf("LuaSessionTimeout is %v, expected 25", global.TuneOptions.LuaSessionTimeout) - } - if *global.TuneOptions.LuaBurstTimeout != 205 { - t.Errorf("LuaSessionTimeout is %v, expected 205", global.TuneOptions.LuaBurstTimeout) - } - if *global.TuneOptions.LuaTaskTimeout != 26 { - t.Errorf("LuaTaskTimeout is %v, expected 26", global.TuneOptions.LuaTaskTimeout) - } - if *global.TuneOptions.LuaServiceTimeout != 27 { - t.Errorf("LuaServiceTimeout is %v, expected 27", global.TuneOptions.LuaServiceTimeout) - } - if *global.TuneOptions.MaxChecksPerThread != 0 { - t.Errorf("MaxChecksPerThread is %v, expected 0", *global.TuneOptions.MaxChecksPerThread) - } - if global.TuneOptions.Maxaccept != 28 { - t.Errorf("Maxaccept is %v, expected 28", global.TuneOptions.Maxaccept) - } - if global.TuneOptions.Maxpollevents != 29 { - t.Errorf("Maxpollevents is %v, expected 29", global.TuneOptions.Maxpollevents) - } - if global.TuneOptions.Maxrewrite != 30 { - t.Errorf("Maxrewrite is %v, expected 30", global.TuneOptions.Maxrewrite) - } - if *global.TuneOptions.PatternCacheSize != 31 { - t.Errorf("PatternCacheSize is %v, expected 31", global.TuneOptions.PatternCacheSize) - } - if global.TuneOptions.PeersMaxUpdatesAtOnce != 200 { - t.Errorf("PeersMaxUpdatesAtOnce is %v, expected 200", global.TuneOptions.PeersMaxUpdatesAtOnce) - } - if global.TuneOptions.Pipesize != 32 { - t.Errorf("Pipesize is %v, expected 32", global.TuneOptions.Pipesize) - } - if global.TuneOptions.PoolHighFdRatio != 33 { - t.Errorf("PoolHighFdRatio is %v, expected 33", global.TuneOptions.PoolHighFdRatio) - } - if global.TuneOptions.PoolLowFdRatio != 34 { - t.Errorf("PoolLowFdRatio is %v, expected 34", global.TuneOptions.PoolLowFdRatio) - } - if global.TuneOptions.PtZeroCopyForwarding != "enabled" { - t.Errorf("PtZeroCopyForwarding is %v, expected enabled", global.TuneOptions.PtZeroCopyForwarding) - } - if *global.TuneOptions.RcvbufBackend != 1024 { - t.Errorf("RcvbufBackend is %v, expected 1024", global.TuneOptions.RcvbufBackend) - } - if *global.TuneOptions.RcvbufClient != 35 { - t.Errorf("RcvbufClient is %v, expected 35", global.TuneOptions.RcvbufClient) - } - if *global.TuneOptions.RcvbufFrontend != 2048 { - t.Errorf("RcvbufFrontend is %v, expected 2048", global.TuneOptions.RcvbufFrontend) - } - if *global.TuneOptions.RcvbufServer != 36 { - t.Errorf("RcvbufServer is %v, expected 36", global.TuneOptions.RcvbufServer) - } - if global.TuneOptions.RecvEnough != 37 { - t.Errorf("RecvEnough is %v, expected 37", global.TuneOptions.RecvEnough) - } - if global.TuneOptions.RunqueueDepth != 38 { - t.Errorf("RunqueueDepth is %v, expected 38", global.TuneOptions.RunqueueDepth) - } - if *global.TuneOptions.SndbufBackend != 1024 { - t.Errorf("SndbufBackend is %v, expected 1024", global.TuneOptions.SndbufBackend) - } - if *global.TuneOptions.SndbufClient != 39 { - t.Errorf("SndbufClient is %v, expected 39", global.TuneOptions.SndbufClient) - } - if *global.TuneOptions.SndbufFrontend != 2048 { - t.Errorf("SndbufFrontend is %v, expected 2048", global.TuneOptions.SndbufFrontend) - } - if *global.TuneOptions.SndbufServer != 40 { - t.Errorf("SndbufServer is %v, expected 40", global.TuneOptions.SndbufServer) - } - if *global.TuneOptions.SslCachesize != 41 { - t.Errorf("SslCachesize is %v, expected 41", global.TuneOptions.SslCachesize) - } - if global.TuneOptions.SslKeylog != "enabled" { - t.Errorf("SslKeylog is %v, expected enabled", global.TuneOptions.SslKeylog) - } - if *global.TuneOptions.SslLifetime != 43 { - t.Errorf("SslLifetime is %v, expected 43", global.TuneOptions.SslLifetime) - } - if *global.TuneOptions.SslMaxrecord != 44 { - t.Errorf("SslMaxrecord is %v, expected 44", global.TuneOptions.SslMaxrecord) - } - if global.TuneOptions.SslDefaultDhParam != 45 { - t.Errorf("SslDefaultDhParam is %v, expected 45", global.TuneOptions.SslDefaultDhParam) - } - if global.TuneOptions.SslCtxCacheSize != 46 { - t.Errorf("SslCtxCacheSize is %v, expected 46", global.TuneOptions.SslCtxCacheSize) - } - if *global.TuneOptions.SslCaptureBufferSize != 47 { - t.Errorf("SslCaptureBufferSize is %v, expected 47", global.TuneOptions.SslCaptureBufferSize) - } - if *global.TuneOptions.SslOcspUpdateMaxDelay != 48 { - t.Errorf("SslCaptureBufferSize is %v, expected 48", global.TuneOptions.SslCaptureBufferSize) - } - if *global.TuneOptions.SslOcspUpdateMinDelay != 49 { - t.Errorf("SslCaptureBufferSize is %v, expected 49", global.TuneOptions.SslCaptureBufferSize) - } - if *global.TuneOptions.StickCounters != 50 { - t.Errorf("SslCaptureBufferSize is %v, expected 50", global.TuneOptions.SslCaptureBufferSize) - } - if *global.TuneOptions.VarsGlobalMaxSize != 51 { - t.Errorf("VarsGlobalMaxSize is %v, expected 51", global.TuneOptions.VarsGlobalMaxSize) - } - if *global.TuneOptions.VarsProcMaxSize != 52 { - t.Errorf("VarsProcMaxSize is %v, expected 52", global.TuneOptions.VarsProcMaxSize) - } - if *global.TuneOptions.VarsReqresMaxSize != 53 { - t.Errorf("VarsReqresMaxSize is %v, expected 53", global.TuneOptions.VarsReqresMaxSize) - } - if *global.TuneOptions.VarsSessMaxSize != 54 { - t.Errorf("VarsSessMaxSize is %v, expected 54", global.TuneOptions.VarsSessMaxSize) - } - if *global.TuneOptions.VarsTxnMaxSize != 55 { - t.Errorf("VarsTxnMaxSize is %v, expected 55", global.TuneOptions.VarsTxnMaxSize) - } - if *global.TuneOptions.QuicFrontendConnTxBuffersLimit != 10 { - t.Errorf("QuicFrontendConnTxBuffersLimit is %v, expected 10", global.TuneOptions.QuicFrontendConnTxBuffersLimit) - } - if *global.TuneOptions.QuicFrontendMaxIdleTimeout != 10000 { - t.Errorf("QuicFrontendMaxIdleTimeout is %v, expected 10000", global.TuneOptions.QuicFrontendMaxIdleTimeout) - } - if *global.TuneOptions.QuicFrontendMaxStreamsBidi != 100 { - t.Errorf("QuicFrontendMaxStreamsBidi is %v, expected 100", global.TuneOptions.QuicFrontendMaxStreamsBidi) - } - if *global.TuneOptions.QuicMaxFrameLoss != 5 { - t.Errorf("QuicMaxFrameLoss is %v, expected 5", global.TuneOptions.QuicMaxFrameLoss) - } - if *global.TuneOptions.QuicRetryThreshold != 5 { - t.Errorf("QuicRetryThreshold is %v, expected 5", global.TuneOptions.QuicRetryThreshold) - } - if global.TuneOptions.QuicSocketOwner != "connection" { - t.Errorf("QuicSocketOwner is %v, expected connection", global.TuneOptions.QuicSocketOwner) - } - if global.TuneOptions.ZlibMemlevel != 54 { - t.Errorf("ZlibMemlevel is %v, expected 54", global.TuneOptions.ZlibMemlevel) - } - if global.TuneOptions.FdEdgeTriggered != "enabled" { - t.Errorf("FdEdgeTriggered is %v, expected enabled", global.TuneOptions.FdEdgeTriggered) - } - if global.TuneOptions.ZlibWindowsize != 55 { - t.Errorf("ZlibWindowsize is %v, expected 55", global.TuneOptions.ZlibWindowsize) - } - if *global.TuneOptions.MemoryHotSize != 56 { - t.Errorf("MemoryHotSize is %v, expected 56", global.TuneOptions.MemoryHotSize) - } - if global.TuneOptions.H2BeInitialWindowSize != 201 { - t.Errorf("H2BeInitialWindowSize is %v, expected 201", global.TuneOptions.H2BeInitialWindowSize) - } - if global.TuneOptions.H2BeMaxConcurrentStreams != 202 { - t.Errorf("H2BeMaxConcurrentStreams is %v, expected 202", global.TuneOptions.H2BeMaxConcurrentStreams) - } - if global.TuneOptions.H2FeInitialWindowSize != 203 { - t.Errorf("H2FeInitialWindowSize is %v, expected 203", global.TuneOptions.H2FeInitialWindowSize) - } - if global.TuneOptions.H2FeMaxConcurrentStreams != 204 { - t.Errorf("H2FeMaxConcurrentStreams is %v, expected 204", global.TuneOptions.H2FeMaxConcurrentStreams) - } - if global.ThreadGroups != 1 { - t.Errorf("ThreadGroups is %v, expected 1", global.ThreadGroups) - } - if len(global.ThreadGroupLines) == 1 { - if *global.ThreadGroupLines[0].Group != "first" { - t.Errorf("ThreadGroup[0] Group is %v, expected first", *global.ThreadGroupLines[0].Group) - } - if *global.ThreadGroupLines[0].NumOrRange != "1-16" { - t.Errorf("ThreadGroup[0] NumOrRange is %v, expected 1-16", *global.ThreadGroupLines[0].NumOrRange) - } - } - if *global.StatsMaxconn != 20 { - t.Errorf("StatsMaxconn is %v, expected 20", *global.StatsMaxconn) - } - if global.DeviceAtlasOptions.JSONFile != "atlas.json" { - t.Errorf("DeviceAtlasOptions.JSONFile is %v, expected atlas.json", global.DeviceAtlasOptions.JSONFile) - } - if global.DeviceAtlasOptions.LogLevel != "1" { - t.Errorf("DeviceAtlasOptions.LogLevel is %v, expected 1", global.DeviceAtlasOptions.LogLevel) - } - if global.DeviceAtlasOptions.Separator != "-" { - t.Errorf("DeviceAtlasOptions.Separator is %v, expected -", global.DeviceAtlasOptions.Separator) - } - if global.DeviceAtlasOptions.PropertiesCookie != "chocolate" { - t.Errorf("DeviceAtlasOptions.PropertiesCookie is %v, expected chocolate", global.DeviceAtlasOptions.PropertiesCookie) - } - if global.FiftyOneDegreesOptions.DataFile != "51.file" { - t.Errorf("FiftyOneDegreesOptions.DataFile is %v, expected 51.file", global.FiftyOneDegreesOptions.DataFile) - } - if global.FiftyOneDegreesOptions.PropertyNameList != "first second third fourth fifth" { - t.Errorf("FiftyOneDegreesOptions.PropertyNameList is %v, expected 'first second third fourth fifth'", global.FiftyOneDegreesOptions.PropertyNameList) - } - if global.FiftyOneDegreesOptions.PropertySeparator != "/" { - t.Errorf("FiftyOneDegreesOptions.PropertySeparator is %v, expected /", global.FiftyOneDegreesOptions.PropertySeparator) - } - if global.FiftyOneDegreesOptions.CacheSize != 51 { - t.Errorf("FiftyOneDegreesOptions.CacheSize is %v, expected 51", global.FiftyOneDegreesOptions.CacheSize) - } - if global.Quiet != true { - t.Errorf("Quiet is false, expected true") - } - if global.ZeroWarning != true { - t.Errorf("ZeroWarning is false, expected true") - } - if global.PreallocFd != true { - t.Errorf("PreallocFd is false, expected true") - } - if global.HttpclientResolversDisabled != "enabled" { - t.Errorf("HttpclientResolversDisabled is %v, expected enabled", global.HttpclientResolversDisabled) - } - if global.HttpclientResolversID != "resolver_1" { - t.Errorf("HttpclientResolversDisabled is %v, expected resolver_1", global.HttpclientResolversID) - } - if global.HttpclientResolversPrefer != "ipv4" { - t.Errorf("HttpclientResolversPrefer is %v, expected ipv4", global.HttpclientResolversPrefer) - } - if global.HttpclientRetries != 3 { - t.Errorf("HttpclientRetries is %v, expected 3", global.HttpclientRetries) - } - if global.HttpclientSslCaFile != "my_test_file.ca" { - t.Errorf("HttpclientSslCaFile is %v, expected my_test_file.ca", global.HttpclientSslCaFile) - } - if *global.HttpclientSslVerify != "none" { - t.Errorf("HttpclientSslVerify is %v, expected \"\"", global.HttpclientSslVerify) - } - if *global.HttpclientTimeoutConnect != 2000 { - t.Errorf("HttpclientTimeoutConnect is %v, expected 2000", global.HttpclientTimeoutConnect) - } - if len(global.SslEngines) == 3 { - if *global.SslEngines[0].Name != "first" { - t.Errorf("SslEngines[0] Name is %v, expected first", *global.SslEngines[0].Name) - } - if *global.SslEngines[0].Algorithms != "" { - t.Errorf("SslEngines[0] Algorithms is %v, expected empty", *global.SslEngines[0].Algorithms) - } - if *global.SslEngines[1].Name != "second" { - t.Errorf("SslEngines[1] Name is %v, expected second", *global.SslEngines[1].Name) - } - if *global.SslEngines[1].Algorithms != "RSA,DSA,DH,EC,RAND" { - t.Errorf("SslEngines[1] Algorithms is %v, expected RSA,DSA,DH,EC,RAND", *global.SslEngines[1].Algorithms) - } - if *global.SslEngines[2].Name != "third" { - t.Errorf("SslEngines[2] Name is %v, expected third", *global.SslEngines[2].Name) - } - if *global.SslEngines[2].Algorithms != "CIPHERS,DIGESTS,PKEY,PKEY_CRYPTO,PKEY_ASN1" { - t.Errorf("SslEngines[2] Algorithms is %v, expected CIPHERS,DIGESTS,PKEY,PKEY_CRYPTO,PKEY_ASN1", *global.SslEngines[2].Algorithms) - } - } - if global.SslDhParamFile != "ssl-dh-param-file.txt" { - t.Errorf("SslDhParamFile is %v, expected ssl-dh-param-file.txt", global.SslDhParamFile) - } - if global.SslServerVerify != "required" { - t.Errorf("SslServerVerify is %v, expected required", global.SslServerVerify) - } - if len(global.SetVars) == 3 { - if *global.SetVars[0].Name != "proc.current_state" { - t.Errorf("SetVars[0] Name is %v, expected proc.current_state", *global.SetVars[0].Name) - } - if *global.SetVars[0].Expr != "str(primary)" { - t.Errorf("SetVars[0] Expr is %v, expected str(primary)", *global.SetVars[0].Expr) - } - if *global.SetVars[1].Name != "proc.prio" { - t.Errorf("SetVars[1] Name is %v, expected proc.prio", *global.SetVars[1].Name) - } - if *global.SetVars[1].Expr != "int(100)" { - t.Errorf("SetVars[1] Expr is %v, expected int(100)", *global.SetVars[1].Expr) - } - if *global.SetVars[2].Name != "proc.threshold" { - t.Errorf("SetVars[2] Name is %v, expected proc.threshold", *global.SetVars[2].Name) - } - if *global.SetVars[2].Expr != "int(200),sub(proc.prio)" { - t.Errorf("SetVars[2] Expr is %v, expected int(200),sub(proc.prio)", *global.SetVars[2].Expr) - } - } else { - t.Errorf("SetVars length is %v, expected 3", len(global.SetVars)) - } - if len(global.SetVarFmts) == 2 { - if *global.SetVarFmts[0].Name != "proc.bootid" { - t.Errorf("SetVars[0] Name is %v, expected proc.bootid", *global.SetVarFmts[0].Name) - } - if *global.SetVarFmts[0].Format != `"%pid|%t"` { - t.Errorf("SetVars[0] Format is %v, expected %%pid|%%t", *global.SetVarFmts[0].Format) - } - if *global.SetVarFmts[1].Name != "proc.current_state" { - t.Errorf("SetVars[1] Name is %v, expected proc.current_state", *global.SetVarFmts[1].Name) - } - if *global.SetVarFmts[1].Format != `"primary"` { - t.Errorf("SetVars[1] Format is %v, expected \"primary\"", *global.SetVarFmts[1].Format) - } - } else { - t.Errorf("SetVarFmts length is %v, expected 2", len(global.SetVarFmts)) - } - if len(global.PresetEnvs) == 1 { - if *global.PresetEnvs[0].Name != "first" { - t.Errorf("esetEnvs[0] Name is %v, expected first", *global.PresetEnvs[0].Name) - } - if *global.PresetEnvs[0].Value != "order" { - t.Errorf("esetEnvs[0] Value is %v, expected order", *global.PresetEnvs[0].Name) - } - } - if len(global.SetEnvs) == 1 { - if *global.SetEnvs[0].Name != "third" { - t.Errorf("setEnvs[0] Name is %v, expected third", *global.PresetEnvs[0].Name) - } - if *global.SetEnvs[0].Value != "sister" { - t.Errorf("setEnvs[0] Value is %v, expected sister", *global.PresetEnvs[0].Name) - } - } - if global.Resetenv != "first second" { - t.Errorf("Resetenv is %v, expected first second", global.Resetenv) - } - if global.Unsetenv != "third fourth" { - t.Errorf("Unsetenv is %v, expected third fourth", global.Resetenv) - } - if global.DefaultPath == nil { - t.Error("DefaultPath is nil, expected not nil") - } else { - if global.DefaultPath.Type != "origin" { - t.Errorf("DefaultPath Type is %v, expected origin", global.DefaultPath.Type) - } - if global.DefaultPath.Path != "/some/path" { - t.Errorf("DefaultPath Path is %v, expected /some/path", global.DefaultPath.Path) - } - } - if global.SslDefaultBindSigalgs != "RSA+SHA256" { - t.Errorf("SslDefaultBindSigalgs is %v, expected RSA+SHA256", global.SslDefaultBindSigalgs) - } - if global.SslDefaultBindClientSigalgs != "ECDSA+SHA256:RSA+SHA256" { - t.Errorf("SslDefaultBindClientSigalgs is %v, expected ECDSA+SHA256:RSA+SHA256", global.SslDefaultBindClientSigalgs) - } - if global.SslDefaultServerSigalgs != "RSA+SHA256" { - t.Errorf("SslDefaultServerSigalgs is %v, expected RSA+SHA256", global.SslDefaultServerSigalgs) - } - if global.SslDefaultServerClientSigalgs != "ECDSA+SHA256:RSA+SHA256" { - t.Errorf("SslDefaultServerClientSigalgs is %v, expected ECDSA+SHA256:RSA+SHA256", global.SslDefaultServerClientSigalgs) - } - if global.SslPropquery != "provider" { - t.Errorf("SslPropquery is %v, expected provider", global.SslPropquery) - } - if global.SslProvider != "default" { - t.Errorf("SslProvider is %v, expected default", global.SslProvider) - } - if global.SslProviderPath != "test" { - t.Errorf("SslProviderPath is %v, expected test", global.SslProviderPath) - } - if global.Setcap != "cap_net_raw,cap_net_bind_service" { - t.Errorf("Setcap is %v, expected cap_net_raw,cap_net_bind_service", global.Setcap) - } - if global.LimitedQuic != true { - t.Errorf("limited_quic in gloabl should be true") - } -} - -func TestPutGlobal(t *testing.T) { - tOut := int64(3600) - n := "1/1" - v := "0" - a := "/var/run/haproxy.sock" - f := "/etc/foo.lua" - luaPrependPath := "/usr/share/haproxy-lua/?/init.lua" - enabled := "enabled" - g := &models.Global{ - Daemon: "enabled", - CPUMaps: []*models.CPUMap{ - { - Process: &n, - CPUSet: &v, - }, - }, - RuntimeAPIs: []*models.RuntimeAPI{ - { - Address: &a, - BindParams: models.BindParams{ - Level: "admin", - }, - }, - }, - Maxconn: 1000, - SslDefaultBindCiphers: "test", - SslDefaultBindOptions: "ssl-min-ver TLSv1.0 no-tls-tickets", - SslDefaultServerCurves: "secp384r1", - StatsTimeout: &tOut, - TuneSslDefaultDhParam: 1024, - ExternalCheck: false, - LuaPrependPath: []*models.LuaPrependPath{ - { - Path: &luaPrependPath, - Type: "cpath", - }, - }, - LuaLoads: []*models.LuaLoad{ - { - File: &f, - }, - }, - LogSendHostname: &models.GlobalLogSendHostname{ - Enabled: &enabled, - Param: "something", - }, - TuneOptions: &models.GlobalTuneOptions{ - DisableZeroCopyForwarding: true, - EventsMaxEventsAtOnce: 50, - H1ZeroCopyFwdRecv: "disabled", - H1ZeroCopyFwdSend: "disabled", - H2ZeroCopyFwdSend: "disabled", - LuaLogLoggers: "disabled", - LuaLogStderr: "disabled", - MaxChecksPerThread: misc.Int64P(20), - PeersMaxUpdatesAtOnce: 100, - PtZeroCopyForwarding: "disabled", - QuicFrontendConnTxBuffersLimit: nil, - QuicFrontendMaxIdleTimeout: misc.Int64P(5000), - QuicSocketOwner: "listener", - RcvbufBackend: misc.Int64P(8192), - RcvbufFrontend: misc.Int64P(4096), - SndbufBackend: misc.Int64P(1234), - SndbufFrontend: misc.Int64P(5678), - SslOcspUpdateMaxDelay: misc.Int64P(48), - SslOcspUpdateMinDelay: misc.Int64P(49), - StickCounters: misc.Int64P(50), - }, - HttpclientResolversDisabled: "disabled", - HttpclientResolversPrefer: "ipv6", - HttpclientResolversID: "my2", - HttpclientRetries: 5, - HttpclientSslCaFile: "my_ca_file.ca", - HttpclientTimeoutConnect: misc.Int64P(5000), - HttpclientSslVerify: misc.StringP(""), - UID: 1234, - WurflOptions: &models.GlobalWurflOptions{}, - DeviceAtlasOptions: &models.GlobalDeviceAtlasOptions{}, - FiftyOneDegreesOptions: &models.GlobalFiftyOneDegreesOptions{}, - StatsMaxconn: misc.Int64P(30), - Anonkey: misc.Int64P(40), - NumaCPUMapping: "disabled", - DefaultPath: &models.GlobalDefaultPath{ - Type: "origin", - Path: "/some/other/path", - }, - NoQuic: false, - ClusterSecret: "", - SslDefaultServerSigalgs: "ECDSA+SHA256", - SslDefaultServerClientSigalgs: "ECDSA+SHA256", - SslPropquery: "foo", - SslProvider: "my_provider", - SslProviderPath: "providers/", - Setcap: "none", - LimitedQuic: true, - } - - err := clientTest.PushGlobalConfiguration(g, "", version) - - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - ver, global, err := clientTest.GetGlobalConfiguration("") - if err != nil { - t.Error(err.Error()) - } - - var givenJSON []byte - givenJSON, err = g.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - var onDiskJSON []byte - onDiskJSON, err = global.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - if string(givenJSON) != string(onDiskJSON) { - fmt.Printf("Created global: %v\n", string(onDiskJSON)) - fmt.Printf("Given global: %v\n", string(givenJSON)) - t.Error("Created global not equal to given global") - } - - if ver != version { - t.Error("Version not incremented!") - } - - err = clientTest.PushGlobalConfiguration(g, "", 55) - - if err == nil { - t.Error("Should have returned version conflict.") - } -} diff --git a/configuration/http_after_response_rule.go b/configuration/http_after_response_rule.go index 6c8fdba3..6cbd9988 100644 --- a/configuration/http_after_response_rule.go +++ b/configuration/http_after_response_rule.go @@ -75,9 +75,9 @@ func (c *client) GetHTTPAfterResponseRule(id int64, parentType, parentName strin } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -101,9 +101,9 @@ func (c *client) DeleteHTTPAfterResponseRule(id int64, parentType string, parent } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -129,9 +129,9 @@ func (c *client) CreateHTTPAfterResponseRule(parentType string, parentName strin } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -164,9 +164,9 @@ func (c *client) EditHTTPAfterResponseRule(id int64, parentType string, parentNa } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -187,9 +187,9 @@ func (c *client) EditHTTPAfterResponseRule(id int64, parentType string, parentNa func ParseHTTPAfterRules(t, pName string, p parser.Parser) (models.HTTPAfterResponseRules, error) { section := parser.Global - if t == "frontend" { + if t == FrontendParentName { section = parser.Frontends - } else if t == "backend" { + } else if t == BackendParentName { section = parser.Backends } diff --git a/configuration/http_after_response_rule_test.go b/configuration/http_after_response_rule_test.go deleted file mode 100644 index 32f09545..00000000 --- a/configuration/http_after_response_rule_test.go +++ /dev/null @@ -1,336 +0,0 @@ -// 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. -// - -package configuration - -import ( - "fmt" - "testing" - - "github.com/haproxytech/client-native/v5/misc" - "github.com/haproxytech/client-native/v5/models" -) - -func TestGetHTTPAfterResponseRules(t *testing.T) { - v, hRules, err := clientTest.GetHTTPAfterResponseRules("frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if expected := 16; len(hRules) != expected { - t.Errorf("%v http after response rules returned, expected %d", len(hRules), expected) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - for _, r := range hRules { - switch *r.Index { - case 0: - if actionType := "set-map"; r.Type != actionType { - t.Errorf("%v: Type not allow: %v", *r.Index, actionType) - } - if mapFile := "map.lst"; r.MapFile != mapFile { - t.Errorf("%v: MapFile not %s: %v", *r.Index, mapFile, r.MapFile) - } - if mapKeyFmt := "%[src]"; r.MapKeyfmt != mapKeyFmt { - t.Errorf("%v: MapKeyfmt not %s: %v", *r.Index, mapKeyFmt, r.MapKeyfmt) - } - if mapValueFmt := "%[res.hdr(X-Value)]"; r.MapValuefmt != mapValueFmt { - t.Errorf("%v: MapValuefmt not %s: %v", *r.Index, mapValueFmt, r.MapValuefmt) - } - case 1: - if actionType := "del-map"; r.Type != actionType { - t.Errorf("%v: Type not %s: %v", *r.Index, actionType, r.Type) - } - if mapFile := "map.lst"; r.MapFile != mapFile { - t.Errorf("%v: MapFile not %s: %v", *r.Index, mapFile, r.MapFile) - } - if mapKeyFmt := "%[src]"; r.MapKeyfmt != mapKeyFmt { - t.Errorf("%v: MapKeyfmt not %s: %v", *r.Index, mapKeyFmt, r.MapKeyfmt) - } - if cond := "if"; r.Cond != cond { - t.Errorf("%v: Cond not %s: %v", *r.Index, cond, r.Cond) - } - if condTest := "FALSE"; r.CondTest != condTest { - t.Errorf("%v: CondTest not %s: %v", *r.Index, condTest, r.CondTest) - } - case 2: - if actionType := "del-acl"; r.Type != actionType { - t.Errorf("%v: Type not %s: %v", *r.Index, actionType, r.Type) - } - if aclFile := "map.lst"; r.ACLFile != aclFile { - t.Errorf("%v: ACLFile not %s: %v", *r.Index, aclFile, r.MapFile) - } - if aclKeyFmt := "%[src]"; r.ACLKeyfmt != aclKeyFmt { - t.Errorf("%v: ACLKeyfmt not %s: %v", *r.Index, aclKeyFmt, r.MapKeyfmt) - } - if cond := "if"; r.Cond != cond { - t.Errorf("%v: Cond not %s: %v", *r.Index, cond, r.Cond) - } - if condTest := "FALSE"; r.CondTest != condTest { - t.Errorf("%v: CondTest not %s: %v", *r.Index, condTest, r.CondTest) - } - case 3: - if actionType := "sc-add-gpc"; r.Type != actionType { - t.Errorf("%v: Type not %s: %v", *r.Index, actionType, r.Type) - } - if scIdx := int64(0); r.ScIdx != scIdx { - t.Errorf("%v: ScIdx not %d: %v", *r.Index, scIdx, r.ScID) - } - if scId := int64(1); r.ScID != scId { - t.Errorf("%v: ScID not %d: %v", *r.Index, scId, r.ScID) - } - if cond := "if"; r.Cond != cond { - t.Errorf("%v: Cond not %s: %v", *r.Index, cond, r.Cond) - } - if condTest := "FALSE"; r.CondTest != condTest { - t.Errorf("%v: CondTest not %s: %v", *r.Index, condTest, r.CondTest) - } - case 4: - if actionType := "sc-inc-gpc"; r.Type != actionType { - t.Errorf("%v: Type not %s: %v", *r.Index, actionType, r.Type) - } - if scIdx := int64(0); r.ScIdx != scIdx { - t.Errorf("%v: ScIdx not %d: %v", *r.Index, scIdx, r.ScID) - } - if scId := int64(1); r.ScID != scId { - t.Errorf("%v: ScID not %d: %v", *r.Index, scId, r.ScID) - } - if cond := "if"; r.Cond != cond { - t.Errorf("%v: Cond not %s: %v", *r.Index, cond, r.Cond) - } - if condTest := "FALSE"; r.CondTest != condTest { - t.Errorf("%v: CondTest not %s: %v", *r.Index, condTest, r.CondTest) - } - case 5: - if actionType := "sc-inc-gpc0"; r.Type != actionType { - t.Errorf("%v: Type not %s: %v", *r.Index, actionType, r.Type) - } - if scId := int64(0); r.ScID != scId { - t.Errorf("%v: ScID not %d: %v", *r.Index, scId, r.ScID) - } - if cond := "if"; r.Cond != cond { - t.Errorf("%v: Cond not %s: %v", *r.Index, cond, r.Cond) - } - if condTest := "FALSE"; r.CondTest != condTest { - t.Errorf("%v: CondTest not %s: %v", *r.Index, condTest, r.CondTest) - } - case 6: - if actionType := "sc-inc-gpc1"; r.Type != actionType { - t.Errorf("%v: Type not %s: %v", *r.Index, actionType, r.Type) - } - if scId := int64(0); r.ScID != scId { - t.Errorf("%v: ScID not %d: %v", *r.Index, scId, r.ScID) - } - if cond := "if"; r.Cond != cond { - t.Errorf("%v: Cond not %s: %v", *r.Index, cond, r.Cond) - } - if condTest := "FALSE"; r.CondTest != condTest { - t.Errorf("%v: CondTest not %s: %v", *r.Index, condTest, r.CondTest) - } - case 7: - if actionType := "sc-set-gpt0"; r.Type != actionType { - t.Errorf("%v: Type not %s: %v", *r.Index, actionType, r.Type) - } - if scId := int64(1); r.ScID != scId { - t.Errorf("%v: ScID not %d: %v", *r.Index, scId, r.ScID) - } - if r.ScInt != nil { - t.Errorf("%v: ScInt not nil: %v", *r.Index, *r.ScInt) - } - if expr := "hdr(Host),lower"; r.ScExpr != expr { - t.Errorf("%v: ScExpr not %s: %v", *r.Index, expr, r.ScExpr) - } - if cond := "if"; r.Cond != cond { - t.Errorf("%v: Cond not %s: %v", *r.Index, cond, r.Cond) - } - if condTest := "FALSE"; r.CondTest != condTest { - t.Errorf("%v: CondTest not %s: %v", *r.Index, condTest, r.CondTest) - } - case 8: - if r.Type != "sc-set-gpt0" { - t.Errorf("%v: Type not sc-set-gpt0: %v", *r.Index, r.Type) - } - if scId := int64(1); r.ScID != scId { - t.Errorf("%v: ScID not %d: %v", *r.Index, scId, r.ScID) - } - if scInt := int64(20); r.ScInt == nil || *r.ScInt != scInt { - if r.ScInt == nil { - t.Errorf("%v: ScInt is nil", *r.Index) - } else { - t.Errorf("%v: ScInt not %d: %v", *r.Index, scInt, *r.ScInt) - } - } - if r.ScExpr != "" { - t.Errorf("%v: ScExpr not empty string: %v", *r.Index, r.ScExpr) - } - if cond := "if"; r.Cond != cond { - t.Errorf("%v: Cond not %s: %v", *r.Index, cond, r.Cond) - } - if condTest := "FALSE"; r.CondTest != condTest { - t.Errorf("%v: CondTest not %s: %v", *r.Index, condTest, r.CondTest) - } - case 9: - if actionType := "set-header"; r.Type != actionType { - t.Errorf("%v: Type not allow: %v", *r.Index, actionType) - } - if headerName := "Strict-Transport-Security"; r.HdrName != headerName { - t.Errorf("%v: HdrName not %s: %v", *r.Index, headerName, r.HdrName) - } - if headerFmt := `"max-age=31536000"`; r.HdrFormat != headerFmt { - t.Errorf("%v: HdrFmt not %s: %v", *r.Index, headerFmt, r.HdrName) - } - case 10: - if actionType := "set-log-level"; r.Type != actionType { - t.Errorf("%v: Action not %s: %v", *r.Index, actionType, r.Type) - } - if logLevel := "silent"; r.LogLevel != logLevel { - t.Errorf("%v: LogLevel not %s %v", *r.Index, logLevel, r.LogLevel) - } - if cond := "if"; r.Cond != cond { - t.Errorf("%v: Cond not %s: %v", *r.Index, cond, r.Cond) - } - if condTest := "FALSE"; r.CondTest != condTest { - t.Errorf("%v: CondTest not %s: %v", *r.Index, condTest, r.CondTest) - } - case 11: - if actionType := "replace-header"; r.Type != actionType { - t.Errorf("%v: Type not allow: %v", *r.Index, actionType) - } - if headerName := "Set-Cookie"; r.HdrName != headerName { - t.Errorf("%v: HdrName not %s: %v", *r.Index, headerName, r.HdrName) - } - if headerMatch := "(C=[^;]*);(.*)"; r.HdrMatch != headerMatch { - t.Errorf("%v: HdrMatch not %s: %v", *r.Index, headerMatch, r.HdrName) - } - if headerFmt := `\1;ip=%bi;\2`; r.HdrFormat != headerFmt { - t.Errorf("%v: HdrFmt not %s: %v", *r.Index, headerFmt, r.HdrName) - } - case 12: - if actionType := "replace-value"; r.Type != actionType { - t.Errorf("%v: Type not allow: %v", *r.Index, actionType) - } - if headerName := "Cache-control"; r.HdrName != headerName { - t.Errorf("%v: HdrName not %s: %v", *r.Index, headerName, r.HdrName) - } - if headerMatch := "^public$"; r.HdrMatch != headerMatch { - t.Errorf("%v: HdrMatch not %s: %v", *r.Index, headerMatch, r.HdrName) - } - if headerFmt := "private"; r.HdrFormat != headerFmt { - t.Errorf("%v: HdrFmt not %s: %v", *r.Index, headerFmt, r.HdrName) - } - case 13: - if actionType := "set-status"; r.Type != actionType { - t.Errorf("%v: Type not allow: %v", *r.Index, actionType) - } - if status := int64(503); r.Status != status { - t.Errorf("%v: status not %d: %v", *r.Index, status, r.HdrName) - } - if reason := fmt.Sprintf("%q", "SlowDown"); r.StatusReason != reason { - t.Errorf("%v: reason not %s: %v", *r.Index, reason, r.HdrName) - } - case 14: - if actionType := "set-var"; r.Type != actionType { - t.Errorf("%v: Type not %s: %v", *r.Index, actionType, r.Type) - } - if varName := "last_redir"; r.VarName != varName { - t.Errorf("%v: VarName not %s: %v", *r.Index, varName, r.VarName) - } - if scope := "sess"; r.VarScope != scope { - t.Errorf("%v: VarName not %s: %v", *r.Index, scope, r.VarScope) - } - if expr := "res.hdr(location)"; r.VarExpr != expr { - t.Errorf("%v: VarExpr not %s: %v", *r.Index, expr, r.VarExpr) - } - case 15: - if actionType := "unset-var"; r.Type != actionType { - t.Errorf("%v: Type not %s: %v", *r.Index, actionType, r.Type) - } - if varName := "last_redir"; r.VarName != varName { - t.Errorf("%v: VarName not %s: %v", *r.Index, varName, r.VarName) - } - if scope := "sess"; r.VarScope != scope { - t.Errorf("%v: VarName not %s: %v", *r.Index, scope, r.VarScope) - } - } - } - - _, hRules, err = clientTest.GetHTTPAfterResponseRules("backend", "test_2", "") - if err != nil { - t.Error(err.Error()) - } - if len(hRules) > 0 { - t.Errorf("%v HTTP After Response Rules returned, expected 0", len(hRules)) - } -} - -func TestCreateHTTPAfterResponseRule(t *testing.T) { - v, err := clientTest.GetVersion("") - if err != nil { - t.Error(err.Error()) - } - - tx, err := clientTest.StartTransaction(v) - if err != nil { - t.Error(err.Error()) - } - - har := &models.HTTPAfterResponseRule{ - Index: misc.Int64P(0), - StrictMode: "on", - Type: "strict-mode", - } - if err = clientTest.CreateHTTPAfterResponseRule("backend", "test", har, tx.ID, 0); err != nil { - t.Error(err.Error()) - } - - _, found, err := clientTest.GetHTTPAfterResponseRule(0, "backend", "test", tx.ID) - if err != nil { - t.Error(err.Error()) - } - - if expected, got := har.Type, found.Type; expected != got { - t.Error(fmt.Errorf("expected type %s, got %s", expected, got)) - } - - if expected, got := har.StrictMode, found.StrictMode; expected != got { - t.Error(fmt.Errorf("expected strict-mode %s, got %s", expected, got)) - } -} - -func TestDeleteHTTPAfterResponseRule(t *testing.T) { - v, err := clientTest.GetVersion("") - if err != nil { - t.Error(err.Error()) - } - - tx, err := clientTest.StartTransaction(v) - if err != nil { - t.Error(err.Error()) - } - - _, hRules, err := clientTest.GetHTTPAfterResponseRules("frontend", "test", tx.ID) - if err != nil { - t.Error(err.Error()) - } - - for range hRules { - if err = clientTest.DeleteHTTPAfterResponseRule(int64(0), "frontend", "test", tx.ID, 0); err != nil { - t.Error(err.Error()) - } - } -} diff --git a/configuration/http_check.go b/configuration/http_check.go index b178d399..decba2a1 100644 --- a/configuration/http_check.go +++ b/configuration/http_check.go @@ -75,9 +75,9 @@ func (c *client) GetHTTPCheck(id int64, parentType string, parentName string, tr } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "defaults" { + } else if parentType == DefaultsParentName { section = parser.Defaults if parentName == "" { parentName = parser.DefaultSectionName @@ -106,9 +106,9 @@ func (c *client) DeleteHTTPCheck(id int64, parentType string, parentName string, } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "defaults" { + } else if parentType == DefaultsParentName { section = parser.Defaults if parentName == "" { parentName = parser.DefaultSectionName @@ -138,9 +138,9 @@ func (c *client) CreateHTTPCheck(parentType string, parentName string, data *mod } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "defaults" { + } else if parentType == DefaultsParentName { section = parser.Defaults if parentName == "" { parentName = parser.DefaultSectionName @@ -172,9 +172,9 @@ func (c *client) EditHTTPCheck(id int64, parentType string, parentName string, d return err } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "defaults" { + } else if parentType == DefaultsParentName { section = parser.Defaults if parentName == "" { parentName = parser.DefaultSectionName @@ -199,12 +199,12 @@ func (c *client) EditHTTPCheck(id int64, parentType string, parentName string, d func ParseHTTPChecks(t, pName string, p parser.Parser) (models.HTTPChecks, error) { var section parser.Section switch t { - case "defaults": + case DefaultsParentName: section = parser.Defaults if pName == "" { pName = parser.DefaultSectionName } - case "backend": + case BackendParentName: section = parser.Backends default: return nil, NewConfError(ErrValidationError, fmt.Sprintf("unsupported section in http_check: %s", t)) diff --git a/configuration/http_check_test.go b/configuration/http_check_test.go deleted file mode 100644 index cbbd87ca..00000000 --- a/configuration/http_check_test.go +++ /dev/null @@ -1,381 +0,0 @@ -// Copyright 2022 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 configuration - -import ( - "fmt" - "testing" - - "github.com/haproxytech/client-native/v5/misc" - "github.com/haproxytech/client-native/v5/models" -) - -func TestGetHTTPChecks(t *testing.T) { //nolint:gocognit,gocyclo - v, checks, err := clientTest.GetHTTPChecks("backend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if len(checks) != 14 { - t.Errorf("%v http checks returned, expected 14", len(checks)) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - for _, r := range checks { - switch *r.Index { - case 0: - if r.Type != "connect" { - t.Errorf("%v: Action not allow: %v", *r.Index, r.Type) - } - case 1: - if r.Type != "send" { - t.Errorf("%v: Action not send: %v", *r.Index, r.Type) - } - if r.Method != "GET" { - t.Errorf("%v: Method not GET: %v", *r.Index, r.Method) - } - if r.URI != "/" { - t.Errorf("%v: URI not /: %v", *r.Index, r.URI) - } - if r.Version != "HTTP/1.1" { - t.Errorf("%v: Version not HTTP/1.1: %v", *r.Index, r.Version) - } - if len(r.CheckHeaders) < 1 { - t.Errorf("%v: Not enough headers", *r.Index) - } else { - if *r.CheckHeaders[0].Name != "host" { - t.Errorf("%v: Header Name not host: %v", *r.Index, r.CheckHeaders[0].Name) - } - if *r.CheckHeaders[0].Fmt != "haproxy.1wt.eu" { - t.Errorf("%v: Header Fmt not haproxy.1wt.eu: %v", *r.Index, r.CheckHeaders[0].Fmt) - } - } - case 2: - if r.Type != "expect" { - t.Errorf("%v: Action not expect: %v", *r.Index, r.Type) - } - if r.Match != "status" { - t.Errorf("%v: Match not status: %v", *r.Index, r.Match) - } - if r.Pattern != "200-399" { - t.Errorf("%v: Pattern not 200-399: %v", *r.Index, r.Pattern) - } - case 3: - if r.Type != "connect" { - t.Errorf("%v: Action not connect: %v", *r.Index, r.Type) - } - if *r.Port != 443 { - t.Errorf("%v: Port not 443: %v", *r.Index, *r.Port) - } - if !r.Ssl { - t.Errorf("%v: Ssl not enabled", *r.Index) - } - if r.Sni != "haproxy.1wt.eu" { - t.Errorf("%v: Sni not haproxy.1wt.eu: %v", *r.Index, r.Sni) - } - case 4: - if r.Type != "expect" { - t.Errorf("%v: Action not expect: %v", *r.Index, r.Type) - } - if r.Match != "status" { - t.Errorf("%v: Match not status: %v", *r.Index, r.Match) - } - if r.Pattern != "200,201,300-310" { - t.Errorf("%v: Pattern not 200,201,300-310: %v", *r.Index, r.Pattern) - } - case 5: - if r.Type != "expect" { - t.Errorf("%v: Action not expect: %v", *r.Index, r.Type) - } - if r.Match != "header" { - t.Errorf("%v: Match not header: %v", *r.Index, r.Match) - } - if r.Pattern != "name \"set-cookie\" value -m beg \"sessid=\"" { - t.Errorf("%v: Pattern not name \"set-cookie\" value -m beg \"sessid=\": %v", *r.Index, r.Pattern) - } - case 6: - if r.Type != "expect" { - t.Errorf("%v: Action not expect: %v", *r.Index, r.Type) - } - if !r.ExclamationMark { - t.Errorf("%v: ExclamationMark not set", *r.Index) - } - if r.Match != "string" { - t.Errorf("%v: Match not string: %v", *r.Index, r.Match) - } - if r.Pattern != "SQL\\ Error" { - t.Errorf("%v: Pattern not SQL\\ Error: %v", *r.Index, r.Pattern) - } - case 7: - if r.Type != "expect" { - t.Errorf("%v: Action not expect: %v", *r.Index, r.Type) - } - if !r.ExclamationMark { - t.Errorf("%v: ExclamationMark not set", *r.Index) - } - if r.Match != "rstatus" { - t.Errorf("%v: Match not string: %v", *r.Index, r.Match) - } - if r.Pattern != "^5" { - t.Errorf("%v: Pattern not ^5: %v", *r.Index, r.Pattern) - } - case 8: - if r.Type != "expect" { - t.Errorf("%v: Action not expect: %v", *r.Index, r.Type) - } - if r.Match != "rstring" { - t.Errorf("%v: Match not rstring: %v", *r.Index, r.Match) - } - if r.Pattern != "" { - t.Errorf("%v: Pattern not : %v", *r.Index, r.Pattern) - } - case 9: - if r.Type != "unset-var" { - t.Errorf("%v: Type not unset-var: %v", *r.Index, r.Type) - } - if r.VarScope != "check" { - t.Errorf("%v: VarScope not check: %v", *r.Index, r.VarScope) - } - if r.VarName != "port" { - t.Errorf("%v: VarName not port: %v", *r.Index, r.VarName) - } - case 10: - if r.Type != "set-var" { - t.Errorf("%v: Type not set-var: %v", *r.Index, r.Type) - } - if r.VarScope != "check" { - t.Errorf("%v: VarScope not check: %v", *r.Index, r.VarScope) - } - if r.VarName != "port" { - t.Errorf("%v: VarName not port: %v", *r.Index, r.VarName) - } - if r.VarExpr != "int(1234)" { - t.Errorf("%v: VarExpr not int(1234): %v", *r.Index, r.VarExpr) - } - case 11: - if r.Type != "set-var-fmt" { - t.Errorf("%v: Type not set-var-fmt: %v", *r.Index, r.Type) - } - if r.VarScope != "check" { - t.Errorf("%v: VarScope not check: %v", *r.Index, r.VarScope) - } - if r.VarName != "port" { - t.Errorf("%v: VarName not port: %v", *r.Index, r.VarName) - } - if r.VarExpr != "int(1234)" { - t.Errorf("%v: VarExpr not int(1234): %v", *r.Index, r.VarExpr) - } - case 12: - if r.Type != "send-state" { - t.Errorf("%v: Action not send-state: %v", *r.Index, r.Type) - } - case 13: - if r.Type != "disable-on-404" { - t.Errorf("%v: Action not disable-on-404: %v", *r.Index, r.Type) - } - default: - t.Errorf("Expect only http checks 0 to 31, %v found", *r.Index) - } - } - - _, checks, err = clientTest.GetHTTPChecks("defaults", "", "") - if err != nil { - t.Error(err.Error()) - } - if len(checks) > 2 { - t.Errorf("%v HTTP Checks returned, expected 2", len(checks)) - } - - for _, r := range checks { - switch *r.Index { - case 0: - if r.Type != "send-state" { - t.Errorf("%v: Action not send-state: %v", *r.Index, r.Type) - } - case 1: - if r.Type != "disable-on-404" { - t.Errorf("%v: Action not disable-on-404: %v", *r.Index, r.Type) - } - default: - t.Errorf("Expect only http-check 0 to %v, %v found", *r.Index, len(checks)-1) - } - } - - _, checks, err = clientTest.GetHTTPChecks("backend", "test_2", "") - if err != nil { - t.Error(err.Error()) - } - if len(checks) != 1 { - t.Errorf("%v HTTP Checks returned, expected 1", len(checks)) - } -} - -func TestGetHTTPCheck(t *testing.T) { - v, check, err := clientTest.GetHTTPCheck(0, "backend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - if *check.Index != 0 { - t.Errorf("HTTP Request Rule Index not 0, %v found", *check.Index) - } - if check.Type != "connect" { - t.Errorf("%v: Action not allow: %v", *check.Index, check.Type) - } - - _, err = check.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - _, _, err = clientTest.GetHTTPCheck(3, "backend", "test_2", "") - if err == nil { - t.Error("Should throw error, non existent HTTP Request Rule") - } - - _, check, err = clientTest.GetHTTPCheck(0, "defaults", "", "") - if err != nil { - t.Error(err.Error()) - } - if check.Type != "send-state" { - t.Errorf("%v: Action not send-state: %v", *check.Index, check.Type) - } -} - -func TestCreateEditDeleteHTTPCheck(t *testing.T) { - id := int64(1) - - // TestCreateHTTPCheck - r := &models.HTTPCheck{ - Index: &id, - Type: "send", - Method: "GET", - Version: "HTTP/1.1", - URI: "/", - CheckHeaders: []*models.ReturnHeader{}, - } - - err := clientTest.CreateHTTPCheck("backend", "test", r, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, ondiskR, err := clientTest.GetHTTPCheck(1, "backend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - var givenJSONB []byte - givenJSONB, err = r.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - var ondiskJSONB []byte - ondiskJSONB, err = ondiskR.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - if string(givenJSONB) != string(ondiskJSONB) { - fmt.Printf("Created HTTP check: %v\n", string(ondiskJSONB)) - fmt.Printf("Given HTTP check: %v\n", string(givenJSONB)) - t.Error("Created HTTP check not equal to given HTTP check") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestEditHTTPRequestRule - r = &models.HTTPCheck{ - Index: &id, - Type: "send", - Method: "GET", - Version: "HTTP/1.1", - URI: "/", - CheckHeaders: []*models.ReturnHeader{ - { - Name: misc.StringP("Host"), - Fmt: misc.StringP("google.com"), - }, - }, - } - - err = clientTest.EditHTTPCheck(1, "backend", "test", r, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, ondiskR, err = clientTest.GetHTTPCheck(1, "backend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - givenJSONB, err = r.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - ondiskJSONB, err = ondiskR.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - if string(givenJSONB) != string(ondiskJSONB) { - fmt.Printf("Created HTTP check: %v\n", string(ondiskJSONB)) - fmt.Printf("Given HTTP check: %v\n", string(givenJSONB)) - t.Error("Created HTTP check not equal to given HTTP check") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestDeleteHTTPRequest - err = clientTest.DeleteHTTPCheck(14, "backend", "test", "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - if v, _ := clientTest.GetVersion(""); v != version { - t.Error("Version not incremented") - } - - _, _, err = clientTest.GetHTTPCheck(14, "backend", "test", "") - if err == nil { - t.Error("DeleteHTTPCheck failed, HTTP check 13 still exists") - } - - err = clientTest.DeleteHTTPCheck(5, "backend", "test_2", "", version) - if err == nil { - t.Error("Should throw error, non existent HTTP Check") - version++ - } -} diff --git a/configuration/http_error_rule.go b/configuration/http_error_rule.go index 777a7397..c14b25cb 100644 --- a/configuration/http_error_rule.go +++ b/configuration/http_error_rule.go @@ -74,14 +74,14 @@ func (c *client) GetHTTPErrorRule(id int64, parentType, parentName string, trans var section parser.Section switch parentType { - case "defaults": + case DefaultsParentName: section = parser.Defaults if parentName == "" { parentName = parser.DefaultSectionName } - case "frontend": + case FrontendParentName: section = parser.Frontends - case "backend": + case BackendParentName: section = parser.Backends } @@ -106,14 +106,14 @@ func (c *client) DeleteHTTPErrorRule(id int64, parentType string, parentName str var section parser.Section switch parentType { - case "defaults": + case DefaultsParentName: section = parser.Defaults if parentName == "" { parentName = parser.DefaultSectionName } - case "frontend": + case FrontendParentName: section = parser.Frontends - case "backend": + case BackendParentName: section = parser.Backends } @@ -140,14 +140,14 @@ func (c *client) CreateHTTPErrorRule(parentType string, parentName string, data var section parser.Section switch parentType { - case "defaults": + case DefaultsParentName: section = parser.Defaults if parentName == "" { parentName = parser.DefaultSectionName } - case "frontend": + case FrontendParentName: section = parser.Frontends - case "backend": + case BackendParentName: section = parser.Backends } @@ -179,14 +179,14 @@ func (c *client) EditHTTPErrorRule(id int64, parentType string, parentName strin var section parser.Section switch parentType { - case "defaults": + case DefaultsParentName: section = parser.Defaults if parentName == "" { parentName = parser.DefaultSectionName } - case "frontend": + case FrontendParentName: section = parser.Frontends - case "backend": + case BackendParentName: section = parser.Backends } @@ -208,14 +208,14 @@ func (c *client) EditHTTPErrorRule(id int64, parentType string, parentName strin func ParseHTTPErrorRules(t, pName string, p parser.Parser) (models.HTTPErrorRules, error) { var section parser.Section switch t { - case "defaults": + case DefaultsParentName: section = parser.Defaults if pName == "" { pName = parser.DefaultSectionName } - case "frontend": + case FrontendParentName: section = parser.Frontends - case "backend": + case BackendParentName: section = parser.Backends default: return nil, NewConfError(ErrValidationError, fmt.Sprintf("unsupported section in http_error: %s", t)) diff --git a/configuration/http_error_rule_test.go b/configuration/http_error_rule_test.go deleted file mode 100644 index eba772e9..00000000 --- a/configuration/http_error_rule_test.go +++ /dev/null @@ -1,345 +0,0 @@ -// Copyright 2022 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 configuration - -import ( - "fmt" - "testing" - - "github.com/haproxytech/client-native/v5/misc" - "github.com/haproxytech/client-native/v5/models" -) - -func TestGetHTTPErrorRules(t *testing.T) { //nolint:gocognit,gocyclo - v, checks, err := clientTest.GetHTTPErrorRules("frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - if len(checks) != 1 { - t.Errorf("%v http-error rules returned, expected 1", len(checks)) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - for _, r := range checks { - switch *r.Index { - case 0: - if r.Type != "status" { - t.Errorf("%v: Action not status: %v", *r.Index, r.Type) - } - if r.Status != 400 { - t.Errorf("%v: Status not 400: %v", *r.Index, r.Type) - } - if *r.ReturnContentType != "application/json" { - t.Errorf("%v: ReturnContentType not application/json: %v", *r.Index, *r.ReturnContentType) - } - if r.ReturnContentFormat != "lf-file" { - t.Errorf("%v: ReturnContentFormat not lf-file: %v", *r.Index, r.ReturnContentFormat) - } - if r.ReturnContent != "/var/errors.file" { - t.Errorf(`%v: ReturnContent not "/var/errors.file": %v`, *r.Index, r.ReturnContent) - } - if len(r.ReturnHeaders) != 0 { - t.Errorf(`%v: len(ReturnHeaders) not 0: %v`, *r.Index, len(r.ReturnHeaders)) - } - } - } - - _, checks, err = clientTest.GetHTTPErrorRules("defaults", "", "") - if err != nil { - t.Error(err.Error()) - } - if len(checks) != 2 { - t.Errorf("%v http-error rules returned, expected 2", len(checks)) - } - - for _, r := range checks { - switch *r.Index { - case 0: - if r.Type != "status" { - t.Errorf("%v: Action not status: %v", *r.Index, r.Type) - } - if r.Status != 503 { - t.Errorf("%v: Status not 503: %v", *r.Index, r.Type) - } - if *r.ReturnContentType != "\"application/json\"" { - t.Errorf(`%v: ReturnContentType not \"application/json\": %v`, *r.Index, *r.ReturnContentType) - } - if r.ReturnContentFormat != "file" { - t.Errorf("%v: ReturnContentFormat not file: %v", *r.Index, r.ReturnContentFormat) - } - if r.ReturnContent != "/test/503" { - t.Errorf("%v: ReturnContent not /test/503: %v", *r.Index, r.ReturnContent) - } - if len(r.ReturnHeaders) != 0 { - t.Errorf("%v: len(ReturnHeaders) not 0: %v", *r.Index, len(r.ReturnHeaders)) - } - case 1: - if r.Type != "status" { - t.Errorf("%v: Action not status: %v", *r.Index, r.Type) - } - if r.Status != 429 { - t.Errorf("%v: Status not 429: %v", *r.Index, r.Type) - } - if *r.ReturnContentType != "application/json" { - t.Errorf("%v: ReturnContentType not application/json: %v", *r.Index, *r.ReturnContentType) - } - if r.ReturnContentFormat != "file" { - t.Errorf("%v: ReturnContentFormat not file: %v", *r.Index, r.ReturnContentFormat) - } - if r.ReturnContent != "/test/429" { - t.Errorf("%v: ReturnContent not /test/429: %v", *r.Index, r.ReturnContent) - } - if len(r.ReturnHeaders) != 0 { - t.Errorf("%v: len(ReturnHeaders) not 0: %v", *r.Index, len(r.ReturnHeaders)) - } - } - } - - _, checks, err = clientTest.GetHTTPErrorRules("backend", "test_2", "") - if err != nil { - t.Error(err.Error()) - } - if len(checks) != 2 { - t.Errorf("%v http-error rules returned, expected 2", len(checks)) - } - - for _, r := range checks { - switch *r.Index { - case 0: - if r.Type != "status" { - t.Errorf("%v: Action not status: %v", *r.Index, r.Type) - } - if r.Status != 200 { - t.Errorf("%v: Status not 200: %v", *r.Index, r.Type) - } - if *r.ReturnContentType != "\"text/plain\"" { - t.Errorf(`%v: ReturnContentType not \"text/plain\": %v`, *r.Index, *r.ReturnContentType) - } - if r.ReturnContentFormat != "string" { - t.Errorf("%v: ReturnContentFormat not string: %v", *r.Index, r.ReturnContentFormat) - } - if r.ReturnContent != "\"My content\"" { - t.Errorf(`%v: ReturnContent not "\"My content\" %v`, *r.Index, r.ReturnContent) - } - if len(r.ReturnHeaders) != 1 { - t.Errorf("%v: len(ReturnHeaders) not 1: %v", *r.Index, len(r.ReturnHeaders)) - } else if *r.ReturnHeaders[0].Name != "Some-Header" { - t.Errorf("%v: ReturnHeaders[0] name not Some-Header: %v", *r.Index, len(r.ReturnHeaders)) - } else if *r.ReturnHeaders[0].Fmt != "value" { - t.Errorf("%v: ReturnHeaders[0] fmt not value: %v", *r.Index, len(r.ReturnHeaders)) - } - case 1: - if r.Type != "status" { - t.Errorf("%v: Action not status: %v", *r.Index, r.Type) - } - if r.Status != 503 { - t.Errorf("%v: Status not 503: %v", *r.Index, r.Type) - } - if *r.ReturnContentType != "application/json" { - t.Errorf("%v: ReturnContentType not application/json: %v", *r.Index, *r.ReturnContentType) - } - if r.ReturnContentFormat != "string" { - t.Errorf("%v: ReturnContentFormat not string: %v", *r.Index, r.ReturnContentFormat) - } - if r.ReturnContent != "\"My content\"" { - t.Errorf(`%v: ReturnContent not "\"My content\" %v`, *r.Index, r.ReturnContent) - } - if len(r.ReturnHeaders) != 2 { - t.Errorf("%v: len(ReturnHeaders) not 2: %v", *r.Index, len(r.ReturnHeaders)) - } else if *r.ReturnHeaders[0].Name != "Additional-Header" { - t.Errorf("%v: ReturnHeaders[0] name not Additional-Header: %v", *r.Index, len(r.ReturnHeaders)) - } else if *r.ReturnHeaders[0].Fmt != "value1" { - t.Errorf("%v: ReturnHeaders[0] fmt not value1: %v", *r.Index, len(r.ReturnHeaders)) - } else if *r.ReturnHeaders[1].Name != "Some-Header" { - t.Errorf("%v: ReturnHeaders[1] name not Some-Header: %v", *r.Index, len(r.ReturnHeaders)) - } else if *r.ReturnHeaders[1].Fmt != "value" { - t.Errorf("%v: ReturnHeaders[1] fmt not value: %v", *r.Index, len(r.ReturnHeaders)) - } - } - } -} - -func TestGetHTTPErrorRule(t *testing.T) { - v, check, err := clientTest.GetHTTPErrorRule(0, "backend", "test_2", "") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - if *check.Index != 0 { - t.Errorf("http-error rule index not 0: %v", *check.Index) - } - if check.Type != "status" { - t.Errorf("%v: Action not status: %v", *check.Index, check.Type) - } - if check.Status != 200 { - t.Errorf("%v: Status not 200: %v", *check.Index, check.Type) - } - _, err = check.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - _, _, err = clientTest.GetHTTPErrorRule(3, "backend", "test", "") - if err == nil { - t.Error("no http-error rules in backend section named test - expected an error") - } - - _, check, err = clientTest.GetHTTPErrorRule(1, "defaults", "", "") - if err != nil { - t.Error(err.Error()) - } - if *check.Index != 1 { - t.Errorf("http-error rule index not 1: %v", *check.Index) - } - if check.Type != "status" { - t.Errorf("%v: Action not status: %v", *check.Index, check.Type) - } - if check.Status != 429 { - t.Errorf("%v: Status not 429: %v", *check.Index, check.Type) - } -} - -func TestCreateEditDeleteHTTPErrorRule(t *testing.T) { - id := int64(1) - r := &models.HTTPErrorRule{ - Index: &id, - Type: "status", - Status: 429, - ReturnContentType: misc.StringP("application/json"), - ReturnContentFormat: "file", - ReturnContent: "/test/429", - ReturnHeaders: []*models.ReturnHeader{ - { - Name: misc.StringP("Some-Header"), - Fmt: misc.StringP("value"), - }, - }, - } - - // TestCreateHTTPErrorRule - err := clientTest.CreateHTTPErrorRule("backend", "test_2", r, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, ondiskR, err := clientTest.GetHTTPErrorRule(1, "backend", "test_2", "") - if err != nil { - t.Error(err.Error()) - } - - var givenJSONB []byte - givenJSONB, err = r.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - var ondiskJSONB []byte - ondiskJSONB, err = ondiskR.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - if string(givenJSONB) != string(ondiskJSONB) { - fmt.Printf("Created HTTP error rule: %v\n", string(ondiskJSONB)) - fmt.Printf("Given HTTP error rule: %v\n", string(givenJSONB)) - t.Error("Created HTTP error rule not equal to given HTTP error rule") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestEditHTTPErrorRule - err = clientTest.EditHTTPErrorRule(1, "backend", "test_2", r, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, ondiskR, err = clientTest.GetHTTPErrorRule(1, "backend", "test_2", "") - if err != nil { - t.Error(err.Error()) - } - - givenJSONB, err = r.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - ondiskJSONB, err = ondiskR.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - if string(givenJSONB) != string(ondiskJSONB) { - fmt.Printf("Created HTTP error rule: %v\n", string(ondiskJSONB)) - fmt.Printf("Given HTTP error rule: %v\n", string(givenJSONB)) - t.Error("Created HTTP error rule not equal to given HTTP error rule") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestDeleteHTTPErrorRule - err = clientTest.DeleteHTTPErrorRule(0, "frontend", "test", "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - if v, _ := clientTest.GetVersion(""); v != version { - t.Error("Version not incremented") - } - - _, _, err = clientTest.GetHTTPErrorRule(0, "frontend", "test", "") - if err == nil { - t.Error("deleting http-error rule failed - http-error rule 0 still exists") - } - - err = clientTest.DeleteHTTPErrorRule(1, "defaults", "", "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - if v, _ := clientTest.GetVersion(""); v != version { - t.Error("Version not incremented") - } - - _, _, err = clientTest.GetHTTPErrorRule(1, "defaults", "", "") - if err == nil { - t.Error("deleting http-error rule failed - http-error rule 1 still exists") - } - - err = clientTest.DeleteHTTPErrorRule(3, "backend", "test_2", "", version) - if err == nil { - t.Error("deleting http-error rule that does not exist - expected an error") - version++ - } -} diff --git a/configuration/http_request_rule.go b/configuration/http_request_rule.go index a7370b04..eb349969 100644 --- a/configuration/http_request_rule.go +++ b/configuration/http_request_rule.go @@ -76,9 +76,9 @@ func (c *client) GetHTTPRequestRule(id int64, parentType, parentName string, tra } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -105,9 +105,9 @@ func (c *client) DeleteHTTPRequestRule(id int64, parentType string, parentName s } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -134,9 +134,9 @@ func (c *client) CreateHTTPRequestRule(parentType string, parentName string, dat } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -169,9 +169,9 @@ func (c *client) EditHTTPRequestRule(id int64, parentType string, parentName str } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -193,9 +193,9 @@ func (c *client) EditHTTPRequestRule(id int64, parentType string, parentName str func ParseHTTPRequestRules(t, pName string, p parser.Parser) (models.HTTPRequestRules, error) { section := parser.Global - if t == "frontend" { + if t == FrontendParentName { section = parser.Frontends - } else if t == "backend" { + } else if t == BackendParentName { section = parser.Backends } diff --git a/configuration/http_request_rule_test.go b/configuration/http_request_rule_test.go deleted file mode 100644 index 831c87be..00000000 --- a/configuration/http_request_rule_test.go +++ /dev/null @@ -1,985 +0,0 @@ -// 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. -// - -package configuration - -import ( - "fmt" - "reflect" - "testing" - - "github.com/haproxytech/client-native/v5/misc" - "github.com/haproxytech/client-native/v5/models" -) - -func TestGetHTTPRequestRules(t *testing.T) { //nolint:gocognit,gocyclo - v, hRules, err := clientTest.GetHTTPRequestRules("frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if len(hRules) != 47 { - t.Errorf("%v http request rules returned, expected 47", len(hRules)) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - for _, r := range hRules { - switch *r.Index { - case 0: - if r.Type != "allow" { - t.Errorf("%v: Type not allow: %v", *r.Index, r.Type) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "src 192.168.0.0/16" { - t.Errorf("%v: CondTest not src 192.168.0.0/16: %v", *r.Index, r.CondTest) - } - case 1: - if r.Type != "set-header" { - t.Errorf("%v: Type not set-header: %v", *r.Index, r.Type) - } - if r.HdrName != "X-SSL" { - t.Errorf("%v: HdrName not X-SSL: %v", *r.Index, r.HdrName) - } - if r.HdrFormat != "%[ssl_fc]" { - t.Errorf("%v: HdrFormat not [ssl_fc]: %v", *r.Index, r.HdrFormat) - } - case 2: - if r.Type != "set-var" { - t.Errorf("%v: Type not set-var: %v", *r.Index, r.Type) - } - if r.VarName != "my_var" { - t.Errorf("%v: VarName not my_var: %v", *r.Index, r.VarName) - } - if r.VarScope != "req" { - t.Errorf("%v: VarName not req: %v", *r.Index, r.VarScope) - } - if r.VarExpr != "req.fhdr(user-agent),lower" { - t.Errorf("%v: VarPattern not req.fhdr(user-agent),lower: %v", *r.Index, r.VarExpr) - } - case 3: - if r.Type != "set-map" { - t.Errorf("%v: Type not set-map: %v", *r.Index, r.Type) - } - if r.MapFile != "map.lst" { - t.Errorf("%v: MapFile not map.lst: %v", *r.Index, r.MapFile) - } - if r.MapKeyfmt != "%[src]" { - t.Errorf("%v: MapKeyfmt not %%[src]: %v", *r.Index, r.MapKeyfmt) - } - if r.MapValuefmt != "%[req.hdr(X-Value)]" { - t.Errorf("%v: MapValuefmt not %%[req.hdr(X-Value)]: %v", *r.Index, r.MapValuefmt) - } - case 4: - if r.Type != "del-map" { - t.Errorf("%v: Type not del-map: %v", *r.Index, r.Type) - } - if r.MapFile != "map.lst" { - t.Errorf("%v: MapFile not map.lst: %v", *r.Index, r.MapFile) - } - if r.MapKeyfmt != "%[src]" { - t.Errorf("%v: MapKeyfmt not %%[src]: %v", *r.Index, r.MapKeyfmt) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 5: - if r.Type != "del-acl" { - t.Errorf("%v: Type not del-acl: %v", *r.Index, r.Type) - } - if r.ACLFile != "map.lst" { - t.Errorf("%v: ACLFile not map.lst: %v", *r.Index, r.ACLFile) - } - if r.ACLKeyfmt != "%[src]" { - t.Errorf("%v: ACLKeyfmt not %%[src]: %v", *r.Index, r.ACLKeyfmt) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 6: - if r.Type != "cache-use" { - t.Errorf("%v: Type not cache-use: %v", *r.Index, r.Type) - } - if r.CacheName != "cache-name" { - t.Errorf("%v: CacheName not cache-name: %v", *r.Index, r.MapFile) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 7: - if r.Type != "disable-l7-retry" { - t.Errorf("%v: Type not disable-l7-retry: %v", *r.Index, r.Type) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 8: - if r.Type != "early-hint" { - t.Errorf("%v: Type not early-hint: %v", *r.Index, r.Type) - } - if r.HintName != "hint-name" { - t.Errorf("%v: HintName not hint-name: %v", *r.Index, r.MapFile) - } - if r.HintFormat != "%[src]" { - t.Errorf("%v: HintFormat not %%[src]: %v", *r.Index, r.MapFile) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 9: - if r.Type != "replace-uri" { - t.Errorf("%v: Type not replace-uri: %v", *r.Index, r.Type) - } - if r.URIMatch != "^http://(.*)" { - t.Errorf("%v: URIMatch not ^http://(.*): %v", *r.Index, r.MapFile) - } - if r.URIFmt != "https://1" { - t.Errorf("%v: URIFmt not https://1: %v", *r.Index, r.MapKeyfmt) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 10: - if r.Type != "sc-add-gpc" { - t.Errorf("%v: Type not sc-add-gpc: %v", *r.Index, r.Type) - } - if r.ScIdx != 0 { - t.Errorf("%v: ScIdx not 0: %v", *r.Index, r.ScID) - } - if r.ScID != 1 { - t.Errorf("%v: ScID not 1: %v", *r.Index, r.ScID) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 11: - if r.Type != "sc-inc-gpc" { - t.Errorf("%v: Type not sc-inc-gpc: %v", *r.Index, r.Type) - } - if r.ScIdx != 0 { - t.Errorf("%v: ScIdx not 0: %v", *r.Index, r.ScID) - } - if r.ScID != 1 { - t.Errorf("%v: ScID not 1: %v", *r.Index, r.ScID) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 12: - if r.Type != "sc-inc-gpc0" { - t.Errorf("%v: Type not sc-inc-gpc0: %v", *r.Index, r.Type) - } - if r.ScID != 0 { - t.Errorf("%v: ScID not 0: %v", *r.Index, r.ScID) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 13: - if r.Type != "sc-inc-gpc1" { - t.Errorf("%v: Type not sc-inc-gpc1: %v", *r.Index, r.Type) - } - if r.ScID != 0 { - t.Errorf("%v: ScID not 0: %v", *r.Index, r.ScID) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 14: - if r.Type != "do-resolve" { - t.Errorf("%v: Type not do-resolve: %v", *r.Index, r.Type) - } - if r.VarName != "txn.myip" { - t.Errorf("%v: VarName not txn.myip: %v", *r.Index, r.VarName) - } - if r.Resolvers != "mydns" { - t.Errorf("%v: Resolvers not mydns: %v", *r.Index, r.Resolvers) - } - if r.Protocol != "ipv4" { - t.Errorf("%v: Protocol not ipv4: %v", *r.Index, r.Protocol) - } - if r.Expr != "hdr(Host),lower" { - t.Errorf("%v: Expr not hdr(Host),lower: %v", *r.Index, r.Expr) - } - case 15: - if r.Type != "sc-set-gpt0" { - t.Errorf("%v: Type not sc-set-gpt0: %v", *r.Index, r.Type) - } - if r.ScID != 1 { - t.Errorf("%v: ScID not 1: %v", *r.Index, r.ScID) - } - if r.ScInt != nil { - t.Errorf("%v: ScInt not nil: %v", *r.Index, *r.ScInt) - } - if r.ScExpr != "hdr(Host),lower" { - t.Errorf("%v: ScExpr not hdr(Host),lower: %v", *r.Index, r.ScExpr) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 16: - if r.Type != "sc-set-gpt0" { - t.Errorf("%v: Type not sc-set-gpt0: %v", *r.Index, r.Type) - } - if r.ScID != 1 { - t.Errorf("%v: ScID not 1: %v", *r.Index, r.ScID) - } - if r.ScInt == nil || *r.ScInt != 20 { - if r.ScInt == nil { - t.Errorf("%v: ScInt is nil", *r.Index) - } else { - t.Errorf("%v: ScInt not 20: %v", *r.Index, *r.ScInt) - } - } - if r.ScExpr != "" { - t.Errorf("%v: ScExpr not empty string: %v", *r.Index, r.ScExpr) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 17: - if r.Type != "set-mark" { - t.Errorf("%v: Type not set-mark: %v", *r.Index, r.Type) - } - if r.MarkValue != "20" { - t.Errorf("%v: MarkValue not 20: %v", *r.Index, r.MarkValue) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 18: - if r.Type != "set-nice" { - t.Errorf("%v: Type not set-nice: %v", *r.Index, r.Type) - } - if r.NiceValue != 20 { - t.Errorf("%v: NiceValue not 20: %v", *r.Index, r.NiceValue) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 19: - if r.Type != "set-method" { - t.Errorf("%v: Type not set-method: %v", *r.Index, r.Type) - } - if r.MethodFmt != "POST" { - t.Errorf("%v: MethodFmt not 0: %v", *r.Index, r.MethodFmt) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 20: - if r.Type != "set-priority-class" { - t.Errorf("%v: Type not set-priority-class: %v", *r.Index, r.Type) - } - if r.Expr != "req.hdr(class)" { - t.Errorf("%v: Expr not req.hdr(class): %v", *r.Index, r.Expr) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 21: - if r.Type != "set-priority-offset" { - t.Errorf("%v: Type not set-priority-offset: %v", *r.Index, r.Type) - } - if r.Expr != "req.hdr(offset)" { - t.Errorf("%v: Expr not req.hdr(offset): %v", *r.Index, r.Expr) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 22: - if r.Type != "set-src" { - t.Errorf("%v: Type not set-src: %v", *r.Index, r.Type) - } - if r.Expr != "req.hdr(src)" { - t.Errorf("%v: Expr not 0: %v", *r.Index, r.Expr) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 23: - if r.Type != "set-src-port" { - t.Errorf("%v: Type not set-src-port: %v", *r.Index, r.Type) - } - if r.Expr != "req.hdr(port)" { - t.Errorf("%v: Expr not req.hdr(port): %v", *r.Index, r.Expr) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 24: - if r.Type != "wait-for-handshake" { - t.Errorf("%v: Type not wait-for-handshake: %v", *r.Index, r.Type) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 25: - if r.Type != "set-tos" { - t.Errorf("%v: Type not set-tos: %v", *r.Index, r.Type) - } - if r.TosValue != "0" { - t.Errorf("%v: TosValue not 0: %v", *r.Index, r.TosValue) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 26: - if r.Type != "silent-drop" { - t.Errorf("%v: Type not silent-drop: %v", *r.Index, r.Type) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 27: - if r.Type != "unset-var" { - t.Errorf("%v: Type not unset-var: %v", *r.Index, r.Type) - } - if r.VarName != "my_var" { - t.Errorf("%v: VarName not my_var: %v", *r.Index, r.VarName) - } - if r.VarScope != "req" { - t.Errorf("%v: VarScope not req: %v", *r.Index, r.VarScope) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 28: - if r.Type != "strict-mode" { - t.Errorf("%v: Type not strict-mode: %v", *r.Index, r.Type) - } - if r.StrictMode != "on" { - t.Errorf("%v: StrictMode not on: %v", *r.Index, r.StrictMode) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 29: - if r.Type != "lua" { - t.Errorf("%v: Type not lua: %v", *r.Index, r.Type) - } - if r.LuaAction != "foo" { - t.Errorf("%v: LuaAction not foo: %v", *r.Index, r.LuaAction) - } - if r.LuaParams != "param1 param2" { - t.Errorf("%v: LuaParams not 'param1 param2': %v", *r.Index, r.LuaParams) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 30: - if r.Type != "use-service" { - t.Errorf("%v: Type not use-service: %v", *r.Index, r.Type) - } - if r.ServiceName != "svrs" { - t.Errorf("%v: ServiceName not svrs: %v", *r.Index, r.ServiceName) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 31: - if r.Type != "return" { - t.Errorf("%v: Type not return: %v", *r.Index, r.Type) - } - if *r.ReturnStatusCode != 200 { - t.Errorf("%v: ReturnStatusCode not 200: %v", *r.Index, *r.ReturnStatusCode) - } - if *r.ReturnContentType != `"text/plain"` { - t.Errorf("%v: ReturnContentType not text/plain: %v", *r.Index, *r.ReturnContentType) - } - if r.ReturnContentFormat != "string" { - t.Errorf("%v: ReturnContentFormat not string: %v", *r.Index, r.ReturnContentFormat) - } - if r.ReturnContent != `"My content"` { - t.Errorf(`%v: ReturnContent not "My content": %v`, *r.Index, r.ReturnContent) - } - if len(r.ReturnHeaders) != 1 { - t.Errorf("%v: ReturnHeaders not length 1: %v", *r.Index, len(r.ReturnHeaders)) - } - if *r.ReturnHeaders[0].Name != "Some-Header" { - t.Errorf("%v: ReturnHeaders[0].Name not Some-Header: %v", *r.Index, *r.ReturnHeaders[0].Name) - } - if *r.ReturnHeaders[0].Fmt != "value" { - t.Errorf("%v: ReturnHeaders[0].Fmt not value: %v", *r.Index, *r.ReturnHeaders[0].Fmt) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 32: - if r.Type != "redirect" { - t.Errorf("%v: Type not redirect: %v", *r.Index, r.Type) - } - if r.RedirType != "scheme" { - t.Errorf("%v: RedirType not scheme: %v", *r.Index, r.RedirType) - } - if r.RedirValue != "https" { - t.Errorf("%v: RedirValue not https: %v", *r.Index, r.RedirValue) - } - if r.RedirCode != nil { - t.Errorf("%v: RedirCode not empty: %v", *r.Index, *r.RedirCode) - } - if r.RedirOption != "" { - t.Errorf("%v: RedirOption not empty: %v", *r.Index, r.RedirOption) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "!{ ssl_fc }" { - t.Errorf("%v: CondTest not !{ ssl_fc }: %v", *r.Index, r.CondTest) - } - case 33: - if r.Type != "redirect" { - t.Errorf("%v: Type not redirect: %v", *r.Index, r.Type) - } - if r.RedirType != "location" { - t.Errorf("%v: RedirType not location: %v", *r.Index, r.RedirType) - } - if r.RedirValue != "https://%[hdr(host),field(1,:)]:443%[capture.req.uri]" { - t.Errorf("%v: RedirValue not match: %v", *r.Index, r.RedirValue) - } - if r.RedirCode == nil { - t.Errorf("%v: RedirCode not 302: %v", *r.Index, r.RedirCode) - } else if *r.RedirCode != 302 { - t.Errorf("%v: RedirCode not 302: %v", *r.Index, *r.RedirCode) - } - if r.RedirOption != "" { - t.Errorf("%v: RedirOption not empty: %v", *r.Index, r.RedirOption) - } - if r.Cond != "" { - t.Errorf("%v: Cond not empty: %v", *r.Index, r.Cond) - } - if r.CondTest != "" { - t.Errorf("%v: CondTest not empty: %v", *r.Index, r.CondTest) - } - case 34: - if r.Type != "deny" { - t.Errorf("%v: Type not deny: %v", *r.Index, r.Type) - } - if r.Cond != "unless" { - t.Errorf("%v: Cond not unless: %v", *r.Index, r.Cond) - } - if r.CondTest != "src 192.168.0.0/16" { - t.Errorf("%v: CondTest not src 192.168.0.0/16: %v", *r.Index, r.CondTest) - } - case 35: - if r.Type != "deny" { - t.Errorf("%v: Type not deny: %v", *r.Index, r.Type) - } - if *r.DenyStatus != 400 { - t.Errorf("%v: DenyStatus not 400: %v", *r.Index, *r.DenyStatus) - } - if *r.ReturnContentType != "application/json" { - t.Errorf("%v: ReturnContentType not application/json: %v", *r.Index, *r.ReturnContentType) - } - if r.ReturnContentFormat != "lf-file" { - t.Errorf("%v: ReturnContentFormat not lf-file: %v", *r.Index, r.ReturnContentFormat) - } - if r.ReturnContent != "/var/errors.file" { - t.Errorf(`%v: ReturnContent not "/var/errors.file": %v`, *r.Index, r.ReturnContent) - } - case 36: - if r.Type != "wait-for-body" { - t.Errorf("%v: Type not wait-for-body: %v", *r.Index, r.Type) - } - if *r.WaitTime != 20000 { - t.Errorf("%v: WaitTime not 20000: %v", *r.Index, *r.WaitTime) - } - if *r.WaitAtLeast != 102400 { - t.Errorf("%v: AtLeast not 102400: %v", *r.Index, *r.WaitAtLeast) - } - case 37: - if r.Type != "set-timeout" { - t.Errorf("%v: Type not set-timeout: %v", *r.Index, r.Type) - } - if r.TimeoutType != "server" { - t.Errorf("%v: TimeoutType not server: %v", *r.Index, r.TimeoutType) - } - if r.Timeout != "20" { - t.Errorf("%v: Timeout not 20: %v", *r.Index, r.Timeout) - } - case 38: - if r.Type != "set-timeout" { - t.Errorf("%v: Type not set-timeout: %v", *r.Index, r.Type) - } - if r.TimeoutType != "tunnel" { - t.Errorf("%v: TimeoutType not tunnel: %v", *r.Index, r.TimeoutType) - } - if r.Timeout != "20" { - t.Errorf("%v: Timeout not 20: %v", *r.Index, r.Timeout) - } - case 39: - if r.Type != "set-timeout" { - t.Errorf("%v: Type not set-timeout: %v", *r.Index, r.Type) - } - if r.TimeoutType != "client" { - t.Errorf("%v: TimeoutType not client: %v", *r.Index, r.TimeoutType) - } - if r.Timeout != "20" { - t.Errorf("%v: Timeout not 20: %v", *r.Index, r.Timeout) - } - case 40: - if r.Type != "set-bandwidth-limit" { - t.Errorf("%v: Type not set-bandwidth-limit: %v", *r.Index, r.Type) - } - if r.BandwidthLimitName != "my-limit" { - t.Errorf("%v: BandwidthLimitName not my-limit: %v", *r.Index, r.BandwidthLimitName) - } - if r.BandwidthLimitLimit != "1m" { - t.Errorf("%v: BandwidthLimitLimit not 1m: %v", *r.Index, r.BandwidthLimitLimit) - } - if r.BandwidthLimitPeriod != "10s" { - t.Errorf("%v: BandwidthLimitPeriod not 10s: %v", *r.Index, r.BandwidthLimitPeriod) - } - case 41: - if r.Type != "set-bandwidth-limit" { - t.Errorf("%v: Type not set-bandwidth-limit: %v", *r.Index, r.Type) - } - if r.BandwidthLimitName != "my-limit-reverse" { - t.Errorf("%v: BandwidthLimitName not my-limit-reverse: %v", *r.Index, r.BandwidthLimitName) - } - if r.BandwidthLimitLimit != "2m" { - t.Errorf("%v: BandwidthLimitLimit not 2m: %v", *r.Index, r.BandwidthLimitLimit) - } - if r.BandwidthLimitPeriod != "20s" { - t.Errorf("%v: BandwidthLimitPeriod no 20s: %v", *r.Index, r.BandwidthLimitPeriod) - } - case 42: - if r.Type != "set-bandwidth-limit" { - t.Errorf("%v: Type not set-bandwidth-limit: %v", *r.Index, r.Type) - } - if r.BandwidthLimitName != "my-limit-cond" { - t.Errorf("%v: BandwidthLimitName not my-limit-cond: %v", *r.Index, r.BandwidthLimitName) - } - if r.BandwidthLimitLimit != "3m" { - t.Errorf("%v: BandwidthLimitLimit not 3m: %v", *r.Index, r.BandwidthLimitLimit) - } - if r.BandwidthLimitPeriod != "" { - t.Errorf("%v: BandwidthLimitPeriod not empty", *r.Index) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 43: - if r.Type != "track-sc" { - t.Errorf("%v: Type not track-sc: %v", *r.Index, r.Type) - } - if *r.TrackScStickCounter != 0 { - t.Errorf("%v: TrackScStickCounter not 0: %v", *r.Index, r.TrackScStickCounter) - } - if r.TrackScKey != "src" { - t.Errorf("%v: TrackScKey not src: %v", *r.Index, r.TrackScKey) - } - if r.TrackScTable != "tr0" { - t.Errorf("%v: TrackScTable not tr0: %v", *r.Index, r.TrackScTable) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not TRUE: %v", *r.Index, r.CondTest) - } - case 44: - if r.Type != "track-sc" { - t.Errorf("%v: Type not track-sc: %v", *r.Index, r.Type) - } - if *r.TrackScStickCounter != 1 { - t.Errorf("%v: TrackScStickCounter not 1: %v", *r.Index, r.TrackScStickCounter) - } - if r.TrackScKey != "src" { - t.Errorf("%v: TrackScKey not src: %v", *r.Index, r.TrackScKey) - } - if r.TrackScTable != "tr1" { - t.Errorf("%v: TrackScTable not tr1: %v", *r.Index, r.TrackScTable) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not TRUE: %v", *r.Index, r.CondTest) - } - case 45: - if r.Type != "track-sc" { - t.Errorf("%v: Type not track-sc: %v", *r.Index, r.Type) - } - if *r.TrackScStickCounter != 2 { - t.Errorf("%v: TrackScStickCounter not 2: %v", *r.Index, r.TrackScStickCounter) - } - if r.TrackScKey != "src" { - t.Errorf("%v: TrackScKey not src: %v", *r.Index, r.TrackScKey) - } - if r.TrackScTable != "tr2" { - t.Errorf("%v: TrackScTable not tr2: %v", *r.Index, r.TrackScTable) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not TRUE: %v", *r.Index, r.CondTest) - } - case 46: - if r.Type != "track-sc" { - t.Errorf("%v: Type not track-sc: %v", *r.Index, r.Type) - } - if *r.TrackScStickCounter != 5 { - t.Errorf("%v: TrackScStickCounter not 5: %v", *r.Index, r.TrackScStickCounter) - } - if r.TrackScKey != "src" { - t.Errorf("%v: TrackScKey not src: %v", *r.Index, r.TrackScKey) - } - if r.TrackScTable != "test" { - t.Errorf("%v: TrackScTable not test: %v", *r.Index, r.TrackScTable) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not TRUE: %v", *r.Index, r.CondTest) - } - default: - t.Errorf("Expect only http-request 0 to 46, %v found", *r.Index) - } - } - - _, hRules, err = clientTest.GetHTTPRequestRules("backend", "test", "") - if err != nil { - t.Error(err.Error()) - } - if len(hRules) > 2 { - t.Errorf("%v HTTP Request Rules returned, expected 2", len(hRules)) - } - - for _, r := range hRules { - switch *r.Index { - case 0: - if r.Type != "set-dst" { - t.Errorf("%v: Type not set-dst: %v", *r.Index, r.Type) - } - if r.Expr != "hdr(x-dst)" { - t.Errorf("%v: Expr not hdr(x-dst): %v", *r.Index, r.VarExpr) - } - case 1: - if r.Type != "set-dst-port" { - t.Errorf("%v: Type not set-dst-port: %v", *r.Index, r.Type) - } - if r.Expr != "int(4000)" { - t.Errorf("%v: Expr not v: %v", *r.Index, r.Expr) - } - default: - t.Errorf("Expect only http-request 0 to %v, %v found", *r.Index, len(hRules)-1) - } - } - - _, hRules, err = clientTest.GetHTTPRequestRules("backend", "test_2", "") - if err != nil { - t.Error(err.Error()) - } - if len(hRules) > 0 { - t.Errorf("%v HTTP Request Rules returned, expected 0", len(hRules)) - } -} - -func TestGetHTTPRequestRule(t *testing.T) { - v, r, err := clientTest.GetHTTPRequestRule(0, "frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - if *r.Index != 0 { - t.Errorf("HTTP Request Rule Index not 0, %v found", *r.Index) - } - if r.Type != "allow" { - t.Errorf("%v: Type not allow: %v", *r.Index, r.Type) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "src 192.168.0.0/16" { - t.Errorf("%v: CondTest not src 192.168.0.0/16: %v", *r.Index, r.CondTest) - } - - _, err = r.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - _, _, err = clientTest.GetHTTPRequestRule(3, "backend", "test_2", "") - if err == nil { - t.Error("Should throw error, non existent HTTP Request Rule") - } - - _, r, err = clientTest.GetHTTPRequestRule(0, "frontend", "test_2", "") - if err != nil { - t.Error("Should throw error, non existent HTTP Request Rule") - } - if r.Type != "capture" { - t.Errorf("%v: Type not allow: %v", *r.Index, r.Type) - } - if r.CaptureLen != 10 { - t.Errorf("%v: Wrong len parameter for capture: %v", *r.Index, r.CaptureLen) - } - - _, r, err = clientTest.GetHTTPRequestRule(1, "frontend", "test_2", "") - if err != nil { - t.Error("Should throw error, non existent HTTP Request Rule") - } - if *r.CaptureID != 0 { - t.Errorf("%v: Wrong slotIndex: %v", *r.Index, *r.CaptureID) - } -} - -func TestCreateEditDeleteHTTPRequestRule(t *testing.T) { - id := int64(1) - - // TestCreateHTTPRequestRule - var redirCode int64 = 301 - r := &models.HTTPRequestRule{ - Index: &id, - Type: "redirect", - RedirCode: &redirCode, - RedirValue: "http://www.%[hdr(host)]%[capture.req.uri]", - RedirType: "location", - } - - err := clientTest.CreateHTTPRequestRule("frontend", "test", r, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, ondiskR, err := clientTest.GetHTTPRequestRule(1, "frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if !reflect.DeepEqual(ondiskR, r) { - fmt.Printf("Created HTTP request rule: %v\n", ondiskR) - fmt.Printf("Given HTTP request rule: %v\n", r) - t.Error("Created HTTP request rule not equal to given HTTP request rule") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestEditHTTPRequestRule - r = &models.HTTPRequestRule{ - Index: &id, - Type: "redirect", - RedirCode: &redirCode, - RedirValue: "http://www1.%[hdr(host)]%[capture.req.uri]", - RedirType: "scheme", - } - - err = clientTest.EditHTTPRequestRule(1, "frontend", "test", r, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, ondiskR, err = clientTest.GetHTTPRequestRule(1, "frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if !reflect.DeepEqual(ondiskR, r) { - fmt.Printf("Edited HTTP request rule: %v\n", ondiskR) - fmt.Printf("Given HTTP request rule: %v\n", r) - t.Error("Edited HTTP request rule not equal to given HTTP request rule") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestDeleteHTTPRequest - err = clientTest.DeleteHTTPRequestRule(47, "frontend", "test", "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - if v, _ := clientTest.GetVersion(""); v != version { - t.Error("Version not incremented") - } - - _, _, err = clientTest.GetHTTPRequestRule(47, "frontend", "test", "") - if err == nil { - t.Error("DeleteHTTPRequestRule failed, HTTP Request Rule 47 still exists") - } - - err = clientTest.DeleteHTTPRequestRule(2, "backend", "test_2", "", version) - if err == nil { - t.Error("Should throw error, non existent HTTP Request Rule") - version++ - } -} - -func TestSerializeHTTPRequestRule(t *testing.T) { - testCases := []struct { - input models.HTTPRequestRule - expectedResult string - }{ - { - input: models.HTTPRequestRule{ - Type: models.HTTPRequestRuleTypeTrackDashSc, - Cond: "if", - CondTest: "TRUE", - TrackScKey: "src", - TrackScTable: "tr0", - TrackScStickCounter: misc.Int64P(3), - }, - expectedResult: "track-sc3 src table tr0 if TRUE", - }, - { - input: models.HTTPRequestRule{ - Type: models.HTTPRequestRuleTypeTrackDashSc0, - Cond: "if", - CondTest: "TRUE", - TrackSc0Key: "src", - TrackSc0Table: "tr0", - }, - expectedResult: "track-sc0 src table tr0 if TRUE", - }, - { - input: models.HTTPRequestRule{ - Type: models.HTTPRequestRuleTypeTrackDashSc1, - Cond: "if", - CondTest: "TRUE", - TrackSc1Key: "src", - TrackSc1Table: "tr1", - }, - expectedResult: "track-sc1 src table tr1 if TRUE", - }, - { - input: models.HTTPRequestRule{ - Type: models.HTTPRequestRuleTypeTrackDashSc2, - Cond: "if", - CondTest: "TRUE", - TrackSc2Key: "src", - TrackSc2Table: "tr2", - }, - expectedResult: "track-sc2 src table tr2 if TRUE", - }, - } - - for _, testCase := range testCases { - t.Run(testCase.expectedResult, func(t *testing.T) { - tcpType, err := SerializeHTTPRequestRule(testCase.input) - if err != nil { - t.Error(err.Error()) - } - - actual := tcpType.String() - if actual != testCase.expectedResult { - t.Errorf("Expected %q, got: %q", testCase.expectedResult, actual) - } - }) - } -} diff --git a/configuration/http_response_rule.go b/configuration/http_response_rule.go index f0595331..500d03f1 100644 --- a/configuration/http_response_rule.go +++ b/configuration/http_response_rule.go @@ -76,9 +76,9 @@ func (c *client) GetHTTPResponseRule(id int64, parentType, parentName string, tr } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -102,9 +102,9 @@ func (c *client) DeleteHTTPResponseRule(id int64, parentType string, parentName } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -130,9 +130,9 @@ func (c *client) CreateHTTPResponseRule(parentType string, parentName string, da } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -165,9 +165,9 @@ func (c *client) EditHTTPResponseRule(id int64, parentType string, parentName st } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -188,9 +188,9 @@ func (c *client) EditHTTPResponseRule(id int64, parentType string, parentName st func ParseHTTPResponseRules(t, pName string, p parser.Parser) (models.HTTPResponseRules, error) { section := parser.Global - if t == "frontend" { + if t == FrontendParentName { section = parser.Frontends - } else if t == "backend" { + } else if t == BackendParentName { section = parser.Backends } diff --git a/configuration/http_response_rule_test.go b/configuration/http_response_rule_test.go deleted file mode 100644 index 73341d56..00000000 --- a/configuration/http_response_rule_test.go +++ /dev/null @@ -1,766 +0,0 @@ -// 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. -// - -package configuration - -import ( - "fmt" - "reflect" - "testing" - - "github.com/haproxytech/client-native/v5/misc" - "github.com/haproxytech/client-native/v5/models" -) - -func TestGetHTTPResponseRules(t *testing.T) { //nolint:gocognit,gocyclo - v, hRules, err := clientTest.GetHTTPResponseRules("frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if len(hRules) != 35 { - t.Errorf("%v http response rules returned, expected 35", len(hRules)) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - for _, r := range hRules { - switch *r.Index { - case 0: - if r.Type != "allow" { - t.Errorf("%v: Type not allow: %v", *r.Index, r.Type) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "src 192.168.0.0/16" { - t.Errorf("%v: CondTest not src 192.168.0.0/16: %v", *r.Index, r.CondTest) - } - case 1: - if r.Type != "set-header" { - t.Errorf("%v: Type not set-header: %v", *r.Index, r.Type) - } - if r.HdrName != "X-SSL" { - t.Errorf("%v: HdrName not X-SSL: %v", *r.Index, r.HdrName) - } - if r.HdrFormat != "%[ssl_fc]" { - t.Errorf("%v: HdrValue not [ssl_fc]: %v", *r.Index, r.HdrFormat) - } - case 2: - if r.Type != "set-var" { - t.Errorf("%v: Type not set-var: %v", *r.Index, r.Type) - } - if r.VarName != "my_var" { - t.Errorf("%v: VarName not my_var: %v", *r.Index, r.VarName) - } - if r.VarScope != "req" { - t.Errorf("%v: VarName not req: %v", *r.Index, r.VarScope) - } - if r.VarExpr != "req.fhdr(user-agent),lower" { - t.Errorf("%v: VarExpr not req.fhdr(user-agent),lower: %v", *r.Index, r.VarExpr) - } - case 3: - if r.Type != "set-map" { - t.Errorf("%v: Type not set-map: %v", *r.Index, r.Type) - } - if r.MapFile != "map.lst" { - t.Errorf("%v: MapFile not map.lst: %v", *r.Index, r.MapFile) - } - if r.MapKeyfmt != "%[src]" { - t.Errorf("%v: MapKeyfmt not %%[src]: %v", *r.Index, r.MapKeyfmt) - } - if r.MapValuefmt != "%[res.hdr(X-Value)]" { - t.Errorf("%v: MapValuefmt not %%[res.hdr(X-Value)]: %v", *r.Index, r.MapValuefmt) - } - case 4: - if r.Type != "del-map" { - t.Errorf("%v: Type not del-map: %v", *r.Index, r.Type) - } - if r.MapFile != "map.lst" { - t.Errorf("%v: MapFile not map.lst: %v", *r.Index, r.MapFile) - } - if r.MapKeyfmt != "%[src]" { - t.Errorf("%v: MapKeyfmt not %%[src]: %v", *r.Index, r.MapKeyfmt) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 5: - if r.Type != "del-acl" { - t.Errorf("%v: Type not del-acl: %v", *r.Index, r.Type) - } - if r.ACLFile != "map.lst" { - t.Errorf("%v: ACLFile not map.lst: %v", *r.Index, r.ACLFile) - } - if r.ACLKeyfmt != "%[src]" { - t.Errorf("%v: ACLKeyfmt not %%[src]: %v", *r.Index, r.ACLKeyfmt) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 6: - if r.Type != "cache-store" { - t.Errorf("%v: Type not cache-store: %v", *r.Index, r.Type) - } - if r.CacheName != "cache-name" { - t.Errorf("%v: CacheName not cache-name: %v", *r.Index, r.MapFile) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 7: - if r.Type != "sc-add-gpc" { - t.Errorf("%v: Type not sc-add-gpc: %v", *r.Index, r.Type) - } - if r.ScIdx != 0 { - t.Errorf("%v: ScIdx not 0: %v", *r.Index, r.ScID) - } - if r.ScID != 1 { - t.Errorf("%v: ScID not 1: %v", *r.Index, r.ScID) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 8: - if r.Type != "sc-inc-gpc" { - t.Errorf("%v: Type not sc-inc-gpc: %v", *r.Index, r.Type) - } - if r.ScIdx != 0 { - t.Errorf("%v: ScIdx not 0: %v", *r.Index, r.ScID) - } - if r.ScID != 1 { - t.Errorf("%v: ScID not 1: %v", *r.Index, r.ScID) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 9: - if r.Type != "sc-inc-gpc0" { - t.Errorf("%v: Type not sc-inc-gpc0: %v", *r.Index, r.Type) - } - if r.ScID != 0 { - t.Errorf("%v: ScID not 0: %v", *r.Index, r.ScID) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 10: - if r.Type != "sc-inc-gpc1" { - t.Errorf("%v: Type not sc-inc-gpc1: %v", *r.Index, r.Type) - } - if r.ScID != 0 { - t.Errorf("%v: ScID not 0: %v", *r.Index, r.ScID) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 11: - if r.Type != "sc-set-gpt0" { - t.Errorf("%v: Type not sc-set-gpt0: %v", *r.Index, r.Type) - } - if r.ScID != 1 { - t.Errorf("%v: ScID not 1: %v", *r.Index, r.ScID) - } - if r.ScInt != nil { - t.Errorf("%v: ScInt not nil: %v", *r.Index, *r.ScInt) - } - if r.ScExpr != "hdr(Host),lower" { - t.Errorf("%v: ScExpr not hdr(Host),lower: %v", *r.Index, r.ScExpr) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 12: - if r.Type != "sc-set-gpt0" { - t.Errorf("%v: Type not sc-set-gpt0: %v", *r.Index, r.Type) - } - if r.ScID != 1 { - t.Errorf("%v: ScID not 1: %v", *r.Index, r.ScID) - } - if r.ScInt == nil || *r.ScInt != 20 { - if r.ScInt == nil { - t.Errorf("%v: ScInt is nil", *r.Index) - } else { - t.Errorf("%v: ScInt not 20: %v", *r.Index, *r.ScInt) - } - } - if r.ScExpr != "" { - t.Errorf("%v: ScExpr not empty string: %v", *r.Index, r.ScExpr) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 13: - if r.Type != "set-mark" { - t.Errorf("%v: Type not set-mark: %v", *r.Index, r.Type) - } - if r.MarkValue != "20" { - t.Errorf("%v: MarkValue not 20: %v", *r.Index, r.MarkValue) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 14: - if r.Type != "set-nice" { - t.Errorf("%v: Type not set-nice: %v", *r.Index, r.Type) - } - if r.NiceValue != 20 { - t.Errorf("%v: NiceValue not 20: %v", *r.Index, r.NiceValue) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 15: - if r.Type != "set-tos" { - t.Errorf("%v: Type not set-tos: %v", *r.Index, r.Type) - } - if r.TosValue != "0" { - t.Errorf("%v: TosValue not 0: %v", *r.Index, r.TosValue) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 16: - if r.Type != "silent-drop" { - t.Errorf("%v: Type not silent-drop: %v", *r.Index, r.Type) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 17: - if r.Type != "unset-var" { - t.Errorf("%v: Type not unset-var: %v", *r.Index, r.Type) - } - if r.VarName != "my_var" { - t.Errorf("%v: VarName not my_var: %v", *r.Index, r.VarName) - } - if r.VarScope != "req" { - t.Errorf("%v: VarScope not req: %v", *r.Index, r.VarScope) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 18: - if r.Type != "track-sc" { - t.Errorf("%v: Type not track-sc %v", *r.Index, r.Type) - } - if *r.TrackScStickCounter != 0 { - t.Errorf("%v: TrackScStickCounter not 0: %v", *r.Index, r.TrackScStickCounter) - } - if r.TrackScKey != "src" { - t.Errorf("%v: TrackScKey not src: %v", *r.Index, r.TrackSc0Key) - } - if r.TrackScTable != "tr0" { - t.Errorf("%v: TrackScTable not tr0: %v", *r.Index, r.TrackSc0Table) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 19: - if r.Type != "track-sc" { - t.Errorf("%v: Type not track-sc: %v", *r.Index, r.Type) - } - if *r.TrackScStickCounter != 1 { - t.Errorf("%v: TrackScStickCounter not 1: %v", *r.Index, r.TrackScStickCounter) - } - if r.TrackScKey != "src" { - t.Errorf("%v: TrackScKey not src: %v", *r.Index, r.TrackSc1Key) - } - if r.TrackScTable != "tr1" { - t.Errorf("%v: TrackScTable not tr1: %v", *r.Index, r.TrackSc1Table) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 20: - if r.Type != "track-sc" { - t.Errorf("%v: Type not track-sc: %v", *r.Index, r.Type) - } - if *r.TrackScStickCounter != 2 { - t.Errorf("%v: TrackScStickCounter not 2: %v", *r.Index, r.TrackScStickCounter) - } - if r.TrackScKey != "src" { - t.Errorf("%v: TrackScKey not src: %v", *r.Index, r.TrackSc2Key) - } - if r.TrackScTable != "tr2" { - t.Errorf("%v: TrackScTable not tr2: %v", *r.Index, r.TrackSc2Table) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 21: - if r.Type != "strict-mode" { - t.Errorf("%v: Type not strict-mode: %v", *r.Index, r.Type) - } - if r.StrictMode != "on" { - t.Errorf("%v: StrictMode not on: %v", *r.Index, r.StrictMode) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 22: - if r.Type != "lua" { - t.Errorf("%v: Type not lua: %v", *r.Index, r.Type) - } - if r.LuaAction != "foo" { - t.Errorf("%v: LuaAction not foo: %v", *r.Index, r.LuaAction) - } - if r.LuaParams != "param1 param2" { - t.Errorf("%v: LuaParams not 'param1 param2': %v", *r.Index, r.LuaParams) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 23: - if r.Type != "deny" { - t.Errorf("%v: Type not deny: %v", *r.Index, r.Type) - } - if *r.DenyStatus != 400 { - t.Errorf("%v: DenyStatus not 400: %v", *r.Index, *r.DenyStatus) - } - if *r.ReturnContentType != "application/json" { - t.Errorf("%v: ReturnContentType not application/json: %v", *r.Index, *r.ReturnContentType) - } - if r.ReturnContentFormat != "lf-file" { - t.Errorf("%v: ReturnContentFormat not lf-file: %v", *r.Index, r.ReturnContentFormat) - } - if r.ReturnContent != "/var/errors.file" { - t.Errorf(`%v: ReturnContent not "/var/errors.file": %v`, *r.Index, r.ReturnContent) - } - case 24: - if r.Type != "wait-for-body" { - t.Errorf("%v: Type not wait-for-body: %v", *r.Index, r.Type) - } - if *r.WaitTime != 20000 { - t.Errorf("%v: WaitTime not 20000: %v", *r.Index, *r.WaitTime) - } - if *r.WaitAtLeast != 102400 { - t.Errorf("%v: AtLeast not 102400: %v", *r.Index, *r.WaitAtLeast) - } - case 25: - if r.Type != "set-bandwidth-limit" { - t.Errorf("%v: Type not set-bandwidth-limit: %v", *r.Index, r.Type) - } - if r.BandwidthLimitName != "my-limit" { - t.Errorf("%v: BandwidthLimitName not my-limit: %v", *r.Index, r.BandwidthLimitName) - } - if r.BandwidthLimitLimit != "1m" { - t.Errorf("%v: BandwidthLimitLimit not 1m: %v", *r.Index, r.BandwidthLimitLimit) - } - if r.BandwidthLimitPeriod != "10s" { - t.Errorf("%v: BandwidthLimitPeriod not 10s: %v", *r.Index, r.BandwidthLimitPeriod) - } - case 26: - if r.Type != "set-bandwidth-limit" { - t.Errorf("%v: Type not set-bandwidth-limit: %v", *r.Index, r.Type) - } - if r.BandwidthLimitName != "my-limit-reverse" { - t.Errorf("%v: BandwidthLimitName not my-limit-reverse: %v", *r.Index, r.BandwidthLimitName) - } - if r.BandwidthLimitLimit != "2m" { - t.Errorf("%v: BandwidthLimitLimit not 2m: %v", *r.Index, r.BandwidthLimitLimit) - } - if r.BandwidthLimitPeriod != "20s" { - t.Errorf("%v: BandwidthLimitPeriod no 20s: %v", *r.Index, r.BandwidthLimitPeriod) - } - case 27: - if r.Type != "set-bandwidth-limit" { - t.Errorf("%v: Type not set-bandwidth-limit: %v", *r.Index, r.Type) - } - if r.BandwidthLimitName != "my-limit-cond" { - t.Errorf("%v: BandwidthLimitName not my-limit-cond: %v", *r.Index, r.BandwidthLimitName) - } - if r.BandwidthLimitLimit != "3m" { - t.Errorf("%v: BandwidthLimitLimit not 3m: %v", *r.Index, r.BandwidthLimitLimit) - } - if r.BandwidthLimitPeriod != "" { - t.Errorf("%v: BandwidthLimitPeriod not empty", *r.Index) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 28: - if r.Type != "track-sc" { - t.Errorf("%v: Type not track-sc: %v", *r.Index, r.Type) - } - if *r.TrackScStickCounter != 0 { - t.Errorf("%v: TrackScStickCounter not 0: %v", *r.Index, r.TrackScStickCounter) - } - if r.TrackScKey != "src" { - t.Errorf("%v: TrackScKey not src: %v", *r.Index, r.TrackScKey) - } - if r.TrackScTable != "tr0" { - t.Errorf("%v: TrackScTable not tr0: %v", *r.Index, r.TrackScTable) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not TRUE: %v", *r.Index, r.CondTest) - } - case 29: - if r.Type != "track-sc" { - t.Errorf("%v: Type not track-sc: %v", *r.Index, r.Type) - } - if *r.TrackScStickCounter != 1 { - t.Errorf("%v: TrackScStickCounter not 1: %v", *r.Index, r.TrackScStickCounter) - } - if r.TrackScKey != "src" { - t.Errorf("%v: TrackScKey not src: %v", *r.Index, r.TrackScKey) - } - if r.TrackScTable != "tr1" { - t.Errorf("%v: TrackScTable not tr1: %v", *r.Index, r.TrackScTable) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not TRUE: %v", *r.Index, r.CondTest) - } - case 30: - if r.Type != "track-sc" { - t.Errorf("%v: Type not track-sc: %v", *r.Index, r.Type) - } - if *r.TrackScStickCounter != 2 { - t.Errorf("%v: TrackScStickCounter not 2: %v", *r.Index, r.TrackScStickCounter) - } - if r.TrackScKey != "src" { - t.Errorf("%v: TrackScKey not src: %v", *r.Index, r.TrackScKey) - } - if r.TrackScTable != "tr2" { - t.Errorf("%v: TrackScTable not tr2: %v", *r.Index, r.TrackScTable) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not TRUE: %v", *r.Index, r.CondTest) - } - case 31: - if r.Type != "track-sc" { - t.Errorf("%v: Type not track-sc: %v", *r.Index, r.Type) - } - if *r.TrackScStickCounter != 5 { - t.Errorf("%v: TrackScStickCounter not 5: %v", *r.Index, r.TrackScStickCounter) - } - if r.TrackScKey != "src" { - t.Errorf("%v: TrackScKey not src: %v", *r.Index, r.TrackScKey) - } - if r.TrackScTable != "test" { - t.Errorf("%v: TrackScTable not test: %v", *r.Index, r.TrackScTable) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not TRUE: %v", *r.Index, r.CondTest) - } - case 32: - if r.Type != "set-timeout" { - t.Errorf("%v: Type not set-timeout: %v", *r.Index, r.Type) - } - if r.TimeoutType != "server" { - t.Errorf("%v: TimeoutType not server: %v", *r.Index, r.TimeoutType) - } - if r.Timeout != "20" { - t.Errorf("%v: Timeout not 20: %v", *r.Index, r.Timeout) - } - case 33: - if r.Type != "set-timeout" { - t.Errorf("%v: Type not set-timeout: %v", *r.Index, r.Type) - } - if r.TimeoutType != "tunnel" { - t.Errorf("%v: TimeoutType not tunnel: %v", *r.Index, r.TimeoutType) - } - if r.Timeout != "20" { - t.Errorf("%v: Timeout not 20: %v", *r.Index, r.Timeout) - } - case 34: - if r.Type != "set-timeout" { - t.Errorf("%v: Type not set-timeout: %v", *r.Index, r.Type) - } - if r.TimeoutType != "client" { - t.Errorf("%v: TimeoutType not client: %v", *r.Index, r.TimeoutType) - } - if r.Timeout != "20" { - t.Errorf("%v: Timeout not 20: %v", *r.Index, r.Timeout) - } - default: - t.Errorf("Expect only http-response 0 to 34, %v found", *r.Index) - } - } - - _, hRules, err = clientTest.GetHTTPResponseRules("backend", "test_2", "") - if err != nil { - t.Error(err.Error()) - } - if len(hRules) > 0 { - t.Errorf("%v HTTP Response Rules returned, expected 0", len(hRules)) - } -} - -func TestGetHTTPResponseRule(t *testing.T) { - v, r, err := clientTest.GetHTTPResponseRule(0, "frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - if *r.Index != 0 { - t.Errorf("HTTPResponse Rule ID not 0, %v found", *r.Index) - } - if r.Type != "allow" { - t.Errorf("%v: Type not allow: %v", *r.Index, r.Type) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "src 192.168.0.0/16" { - t.Errorf("%v: CondTest not src 192.168.0.0/16: %v", *r.Index, r.CondTest) - } - - _, err = r.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - _, _, err = clientTest.GetHTTPResponseRule(3, "backend", "test2", "") - if err == nil { - t.Error("Should throw error, non existent HTTPResponse Rule") - } - - _, r, err = clientTest.GetHTTPResponseRule(0, "frontend", "test_2", "") - if err != nil { - t.Error(err.Error()) - } - if r.Type != "capture" { - t.Errorf("%v: Type not 'capture': %v", *r.Index, r.Type) - } - if *r.CaptureID != 0 { - t.Errorf("%v: Wrong slotID: %v", *r.Index, r.CaptureID) - } -} - -func TestCreateEditDeleteHTTPResponseRule(t *testing.T) { - id := int64(1) - // TestCreateHTTPResponseRule - r := &models.HTTPResponseRule{ - Index: &id, - Type: "set-log-level", - LogLevel: "alert", - } - - err := clientTest.CreateHTTPResponseRule("frontend", "test", r, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, ondiskR, err := clientTest.GetHTTPResponseRule(1, "frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if !reflect.DeepEqual(ondiskR, r) { - fmt.Printf("Created HTTP response rule: %v\n", ondiskR) - fmt.Printf("Given HTTP response rule: %v\n", r) - t.Error("Created HTTP response rule not equal to given HTTP response rule") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestEditHTTPResponseRule - r = &models.HTTPResponseRule{ - Index: &id, - Type: "set-log-level", - LogLevel: "warning", - } - - err = clientTest.EditHTTPResponseRule(1, "frontend", "test", r, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, ondiskR, err = clientTest.GetHTTPResponseRule(1, "frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if !reflect.DeepEqual(ondiskR, r) { - fmt.Printf("Edited HTTP response rule: %v\n", ondiskR) - fmt.Printf("Given HTTP response rule: %v\n", r) - t.Error("Edited HTTP response rule not equal to given HTTP response rule") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestDeleteHTTPResponse - err = clientTest.DeleteHTTPResponseRule(35, "frontend", "test", "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - if v, _ := clientTest.GetVersion(""); v != version { - t.Error("Version not incremented") - } - - _, _, err = clientTest.GetHTTPResponseRule(35, "frontend", "test", "") - if err == nil { - t.Error("DeleteHTTPResponseRule failed, HTTPResponse Rule 35 still exists") - } - - err = clientTest.DeleteHTTPResponseRule(2, "backend", "test_2", "", version) - if err == nil { - t.Error("Should throw error, non existent HTTPResponse Rule") - version++ - } -} - -func TestSerializeHTTPResponseRule(t *testing.T) { - testCases := []struct { - input models.HTTPResponseRule - expectedResult string - }{ - { - input: models.HTTPResponseRule{ - Type: models.HTTPResponseRuleTypeTrackDashSc, - Cond: "if", - CondTest: "TRUE", - TrackScKey: "src", - TrackScTable: "tr0", - TrackScStickCounter: misc.Int64P(3), - }, - expectedResult: "track-sc3 src table tr0 if TRUE", - }, - { - input: models.HTTPResponseRule{ - Type: models.HTTPResponseRuleTypeTrackDashSc0, - Cond: "if", - CondTest: "TRUE", - TrackSc0Key: "src", - TrackSc0Table: "tr0", - }, - expectedResult: "track-sc0 src table tr0 if TRUE", - }, - { - input: models.HTTPResponseRule{ - Type: models.HTTPResponseRuleTypeTrackDashSc1, - Cond: "if", - CondTest: "TRUE", - TrackSc1Key: "src", - TrackSc1Table: "tr1", - }, - expectedResult: "track-sc1 src table tr1 if TRUE", - }, - { - input: models.HTTPResponseRule{ - Type: models.HTTPResponseRuleTypeTrackDashSc2, - Cond: "if", - CondTest: "TRUE", - TrackSc2Key: "src", - TrackSc2Table: "tr2", - }, - expectedResult: "track-sc2 src table tr2 if TRUE", - }, - } - - for _, testCase := range testCases { - t.Run(testCase.expectedResult, func(t *testing.T) { - tcpType, err := SerializeHTTPResponseRule(testCase.input) - if err != nil { - t.Error(err.Error()) - } - - actual := tcpType.String() - if actual != testCase.expectedResult { - t.Errorf("Expected %q, got: %q", testCase.expectedResult, actual) - } - }) - } -} diff --git a/configuration/log_target.go b/configuration/log_target.go index 44c6e3c8..a4b0130c 100644 --- a/configuration/log_target.go +++ b/configuration/log_target.go @@ -232,21 +232,21 @@ func SerializeLogTarget(l models.LogTarget) types.Log { func logTargetSectionType(parentType string, parentName string) (parser.Section, string) { var section parser.Section switch parentType { - case "global": + case GlobalParentName: section = parser.Global parentName = parser.GlobalSectionName - case "defaults": + case DefaultsParentName: section = parser.Defaults if parentName == "" { parentName = parser.DefaultSectionName } - case "backend": + case BackendParentName: section = parser.Backends - case "frontend": + case FrontendParentName: section = parser.Frontends - case "log_forward": + case LogForwardParentName: section = parser.LogForward - case "peers": + case PeersParentName: section = parser.Peers } return section, parentName diff --git a/configuration/nameserver.go b/configuration/nameserver.go index b0c46d0b..dfb27154 100644 --- a/configuration/nameserver.go +++ b/configuration/nameserver.go @@ -53,7 +53,7 @@ func (c *client) GetNameservers(resolverSection string, transactionID string) (i nameservers, err := ParseNameservers(resolverSection, p) if err != nil { - return v, nil, c.HandleError("", "resolvers", resolverSection, "", false, err) + return v, nil, c.HandleError("", ResolverParentName, resolverSection, "", false, err) } return v, nameservers, nil @@ -91,11 +91,11 @@ func (c *client) DeleteNameserver(name string, resolverSection string, transacti nameserver, i := GetNameserverByName(name, resolverSection, p) if nameserver == nil { e := NewConfError(ErrObjectDoesNotExist, fmt.Sprintf("Nameserver %s does not exist in resolvers section %s", name, resolverSection)) - return c.HandleError(name, "resolvers", resolverSection, t, transactionID == "", e) + return c.HandleError(name, ResolverParentName, resolverSection, t, transactionID == "", e) } if err := p.Delete(parser.Resolvers, resolverSection, "nameserver", i); err != nil { - return c.HandleError(name, "resolvers", resolverSection, t, transactionID == "", err) + return c.HandleError(name, ResolverParentName, resolverSection, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -118,11 +118,11 @@ func (c *client) CreateNameserver(resolverSection string, data *models.Nameserve nameserver, _ := GetNameserverByName(data.Name, resolverSection, p) if nameserver != nil { e := NewConfError(ErrObjectAlreadyExists, fmt.Sprintf("Nameserver %s already exists in resolvers section %s", data.Name, resolverSection)) - return c.HandleError(data.Name, "resolvers", resolverSection, t, transactionID == "", e) + return c.HandleError(data.Name, ResolverParentName, resolverSection, t, transactionID == "", e) } if err := p.Insert(parser.Resolvers, resolverSection, "nameserver", SerializeNameserver(*data), -1); err != nil { - return c.HandleError(data.Name, "resolvers", resolverSection, t, transactionID == "", err) + return c.HandleError(data.Name, ResolverParentName, resolverSection, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -145,11 +145,11 @@ func (c *client) EditNameserver(name string, resolverSection string, data *model nameserver, i := GetNameserverByName(name, resolverSection, p) if nameserver == nil { e := NewConfError(ErrObjectDoesNotExist, fmt.Sprintf("Nameserver %v does not exist in resolvers section %s", name, resolverSection)) - return c.HandleError(data.Name, "resolvers", resolverSection, t, transactionID == "", e) + return c.HandleError(data.Name, ResolverParentName, resolverSection, t, transactionID == "", e) } if err := p.Set(parser.Resolvers, resolverSection, "nameserver", SerializeNameserver(*data), i); err != nil { - return c.HandleError(data.Name, "resolvers", resolverSection, t, transactionID == "", err) + return c.HandleError(data.Name, ResolverParentName, resolverSection, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") diff --git a/configuration/peer_entry.go b/configuration/peer_entry.go index a283378a..07ebd1d5 100644 --- a/configuration/peer_entry.go +++ b/configuration/peer_entry.go @@ -52,7 +52,7 @@ func (c *client) GetPeerEntries(peerSection string, transactionID string) (int64 peerEntries, err := ParsePeerEntries(peerSection, p) if err != nil { - return v, nil, c.HandleError("", "peers", peerSection, "", false, err) + return v, nil, c.HandleError("", PeersParentName, peerSection, "", false, err) } return v, peerEntries, nil @@ -90,11 +90,11 @@ func (c *client) DeletePeerEntry(name string, peerSection string, transactionID peerEntry, i := GetPeerEntryByName(name, peerSection, p) if peerEntry == nil { e := NewConfError(ErrObjectDoesNotExist, fmt.Sprintf("PeerEntry %s does not exist in peer section %s", name, peerSection)) - return c.HandleError(name, "peers", peerSection, t, transactionID == "", e) + return c.HandleError(name, PeersParentName, peerSection, t, transactionID == "", e) } if err := p.Delete(parser.Peers, peerSection, "peer", i); err != nil { - return c.HandleError(name, "peers", peerSection, t, transactionID == "", err) + return c.HandleError(name, PeersParentName, peerSection, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -117,11 +117,11 @@ func (c *client) CreatePeerEntry(peerSection string, data *models.PeerEntry, tra peerEntry, _ := GetPeerEntryByName(data.Name, peerSection, p) if peerEntry != nil { e := NewConfError(ErrObjectAlreadyExists, fmt.Sprintf("PeerEntry %s already exists in peer section %s", data.Name, peerSection)) - return c.HandleError(data.Name, "peers", peerSection, t, transactionID == "", e) + return c.HandleError(data.Name, PeersParentName, peerSection, t, transactionID == "", e) } if err := p.Insert(parser.Peers, peerSection, "peer", SerializePeerEntry(*data), -1); err != nil { - return c.HandleError(data.Name, "peers", peerSection, t, transactionID == "", err) + return c.HandleError(data.Name, PeersParentName, peerSection, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -144,11 +144,11 @@ func (c *client) EditPeerEntry(name string, peerSection string, data *models.Pee peerEntry, i := GetPeerEntryByName(name, peerSection, p) if peerEntry == nil { e := NewConfError(ErrObjectDoesNotExist, fmt.Sprintf("PeerEntry %v does not exist in peer section %s", name, peerSection)) - return c.HandleError(data.Name, "peers", peerSection, t, transactionID == "", e) + return c.HandleError(data.Name, PeersParentName, peerSection, t, transactionID == "", e) } if err := p.Set(parser.Peers, peerSection, "peer", SerializePeerEntry(*data), i); err != nil { - return c.HandleError(data.Name, "peers", peerSection, t, transactionID == "", err) + return c.HandleError(data.Name, PeersParentName, peerSection, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") diff --git a/configuration/server.go b/configuration/server.go index 1d698deb..bb6ca499 100644 --- a/configuration/server.go +++ b/configuration/server.go @@ -185,7 +185,7 @@ func ParseServers(parentType string, parentName string, p parser.Parser) (models return servers, nil } -func parseAddress(address string) (ipOrAddress string, port *int64) { +func ParseAddress(address string) (ipOrAddress string, port *int64) { if strings.HasPrefix(address, "[") && strings.ContainsRune(address, ']') { // IPv6 with port [2001:0DB8:0000:0000:0000:0000:1428:57ab]:80 split := strings.Split(address, "]") split[0] = strings.TrimPrefix(split[0], "[") @@ -497,7 +497,7 @@ func ParseServer(ondiskServer types.Server) *models.Server { s := &models.Server{ Name: ondiskServer.Name, } - address, port := parseAddress(ondiskServer.Address) + address, port := ParseAddress(ondiskServer.Address) if address == "" { return nil } @@ -868,11 +868,11 @@ func GetServerByName(name string, parentType string, parentName string, p parser func sectionType(parentType string) parser.Section { var sectionType parser.Section switch parentType { - case "backend": + case BackendParentName: sectionType = parser.Backends - case "ring": + case RingParentName: sectionType = parser.Ring - case "peers": + case PeersParentName: sectionType = parser.Peers } return sectionType diff --git a/configuration/server_switching_rule.go b/configuration/server_switching_rule.go index 957333c0..8c709e64 100644 --- a/configuration/server_switching_rule.go +++ b/configuration/server_switching_rule.go @@ -43,7 +43,7 @@ func (c *client) GetServerSwitchingRules(backend string, transactionID string) ( srvRules, err := ParseServerSwitchingRules(backend, p) if err != nil { - return v, nil, c.HandleError("", "backend", backend, "", false, err) + return v, nil, c.HandleError("", BackendParentName, backend, "", false, err) } return v, srvRules, nil @@ -64,7 +64,7 @@ func (c *client) GetServerSwitchingRule(id int64, backend string, transactionID data, err := p.GetOne(parser.Backends, backend, "use-server", int(id)) if err != nil { - return v, nil, c.HandleError(strconv.FormatInt(id, 10), "backend", backend, "", false, err) + return v, nil, c.HandleError(strconv.FormatInt(id, 10), BackendParentName, backend, "", false, err) } srvRule := ParseServerSwitchingRule(data.(types.UseServer)) @@ -82,7 +82,7 @@ func (c *client) DeleteServerSwitchingRule(id int64, backend string, transaction } if err := p.Delete(parser.Backends, backend, "use-server", int(id)); err != nil { - return c.HandleError(strconv.FormatInt(id, 10), "backend", backend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(id, 10), BackendParentName, backend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -103,7 +103,7 @@ func (c *client) CreateServerSwitchingRule(backend string, data *models.ServerSw } if err := p.Insert(parser.Backends, backend, "use-server", SerializeServerSwitchingRule(*data), int(*data.Index)); err != nil { - return c.HandleError(strconv.FormatInt(*data.Index, 10), "backend", backend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(*data.Index, 10), BackendParentName, backend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -124,11 +124,11 @@ func (c *client) EditServerSwitchingRule(id int64, backend string, data *models. } if _, err := p.GetOne(parser.Backends, backend, "use-server", int(id)); err != nil { - return c.HandleError(strconv.FormatInt(*data.Index, 10), "backend", backend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(*data.Index, 10), BackendParentName, backend, t, transactionID == "", err) } if err := p.Set(parser.Backends, backend, "use-server", SerializeServerSwitchingRule(*data), int(id)); err != nil { - return c.HandleError(strconv.FormatInt(*data.Index, 10), "backend", backend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(*data.Index, 10), BackendParentName, backend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") diff --git a/configuration/server_template.go b/configuration/server_template.go index c7ed3043..036926e9 100644 --- a/configuration/server_template.go +++ b/configuration/server_template.go @@ -52,7 +52,7 @@ func (c *client) GetServerTemplates(backend string, transactionID string) (int64 templates, err := ParseServerTemplates(backend, p) if err != nil { - return v, nil, c.HandleError("", "backend", backend, "", false, err) + return v, nil, c.HandleError("", BackendParentName, backend, "", false, err) } return v, templates, nil @@ -90,11 +90,11 @@ func (c *client) DeleteServerTemplate(prefix string, backend string, transaction template, i := GetServerTemplateByPrefix(prefix, backend, p) if template == nil { e := NewConfError(ErrObjectDoesNotExist, fmt.Sprintf("Server template %s does not exist in backend %s", prefix, backend)) - return c.HandleError(prefix, "backend", backend, t, transactionID == "", e) + return c.HandleError(prefix, BackendParentName, backend, t, transactionID == "", e) } if err := p.Delete(parser.Backends, backend, "server-template", i); err != nil { - return c.HandleError(prefix, "backend", backend, t, transactionID == "", err) + return c.HandleError(prefix, BackendParentName, backend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -117,11 +117,11 @@ func (c *client) CreateServerTemplate(backend string, data *models.ServerTemplat template, _ := GetServerTemplateByPrefix(data.Prefix, backend, p) if template != nil { e := NewConfError(ErrObjectAlreadyExists, fmt.Sprintf("Server template %s already exists in backend %s", data.Prefix, backend)) - return c.HandleError(data.Prefix, "backend", backend, t, transactionID == "", e) + return c.HandleError(data.Prefix, BackendParentName, backend, t, transactionID == "", e) } if err := p.Insert(parser.Backends, backend, "server-template", SerializeServerTemplate(*data), -1); err != nil { - return c.HandleError(data.Prefix, "backend", backend, t, transactionID == "", err) + return c.HandleError(data.Prefix, BackendParentName, backend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -144,11 +144,11 @@ func (c *client) EditServerTemplate(prefix string, backend string, data *models. template, i := GetServerTemplateByPrefix(prefix, backend, p) if template == nil { e := NewConfError(ErrObjectDoesNotExist, fmt.Sprintf("Server template %v does not exist in backend %s", prefix, backend)) - return c.HandleError(data.Prefix, "backend", backend, t, transactionID == "", e) + return c.HandleError(data.Prefix, BackendParentName, backend, t, transactionID == "", e) } if err := p.Set(parser.Backends, backend, "server-template", SerializeServerTemplate(*data), i); err != nil { - return c.HandleError(data.Prefix, "backend", backend, t, transactionID == "", err) + return c.HandleError(data.Prefix, BackendParentName, backend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") diff --git a/configuration/server_test.go b/configuration/server_test.go deleted file mode 100644 index 6e695155..00000000 --- a/configuration/server_test.go +++ /dev/null @@ -1,468 +0,0 @@ -// 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. -// - -package configuration - -import ( - "fmt" - "reflect" - "testing" - - "github.com/haproxytech/client-native/v5/misc" - "github.com/haproxytech/client-native/v5/models" -) - -func TestGetServers(t *testing.T) { //nolint:gocognit,gocyclo - v, servers, err := clientTest.GetServers("backend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if len(servers) != 2 { - t.Errorf("%v servers returned, expected 2", len(servers)) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - for _, s := range servers { - if s.Name != "webserv" && s.Name != "webserv2" { - t.Errorf("Expected only webserv or webserv2 servers, %v found", s.Name) - } - if s.Address != "192.168.1.1" { - t.Errorf("%v: Address not 192.168.1.1: %v", s.Name, s.Address) - } - if *s.Port != 9300 && *s.Port != 9200 { - t.Errorf("%v: Port not 9300 or 9200: %v", s.Name, *s.Port) - } - if s.Ssl != "enabled" { - t.Errorf("%v: Ssl not enabled: %v", s.Name, s.Ssl) - } - if s.Cookie != "BLAH" { - t.Errorf("%v: Cookie not BLAH: %v", s.Name, s.Cookie) - } - if *s.Maxconn != 1000 { - t.Errorf("%v: Maxconn not 1000: %v", s.Name, *s.Maxconn) - } - if *s.Weight != 10 { - t.Errorf("%v: Weight not 10: %v", s.Name, *s.Weight) - } - if *s.Inter != 2000 { - t.Errorf("%v: Inter not 2000: %v", s.Name, *s.Inter) - } - if s.Ws != "h1" { - t.Errorf("%v: Ws not h1: %v", s.Name, s.Ws) - } - if *s.PoolLowConn != 128 { - t.Errorf("%v: PoolLowConn not 128: %v", s.Name, *s.PoolLowConn) - } - if len(s.ProxyV2Options) != 2 { - t.Errorf("%v: ProxyV2Options < 2: %d", s.Name, len(s.ProxyV2Options)) - } else { - if s.ProxyV2Options[0] != "authority" { - t.Errorf("%v: ProxyV2Options[0] not authority: %s", s.Name, s.ProxyV2Options[0]) - } - if s.ProxyV2Options[1] != "crc32c" { - t.Errorf("%v: ProxyV2Options[0] not crc32c: %s", s.Name, s.ProxyV2Options[1]) - } - } - - if s.Name == "webserv" && (s.LogBufsize == nil || *s.LogBufsize != 10) { - t.Errorf("%v: LogBufsize should be 10: %v", s.Name, s.LogBufsize) - } - if s.Name == "webserv2" && s.LogBufsize != nil { - t.Errorf("%v: LogBufsize should be nil: %v", s.Name, s.LogBufsize) - } - if s.Name == "webserv" { - if s.SetProxyV2TlvFmt != nil { - if s.SetProxyV2TlvFmt.ID != nil { - if *s.SetProxyV2TlvFmt.ID != "0x20" { - t.Errorf("%v: SetProxyV2TlvFmt ID should be 0x20: %s", s.Name, *s.SetProxyV2TlvFmt.ID) - } - } else { - t.Errorf("%v: SetProxyV2TlvFmt ID should be set", s.Name) - } - if s.SetProxyV2TlvFmt.Value != nil { - if *s.SetProxyV2TlvFmt.Value != "%[fc_pp_tlv(0x20)]" { - t.Errorf("%v: SetProxyV2TlvFmt Value should be %%[fc_pp_tlv(0x20)]: %s", s.Name, *s.SetProxyV2TlvFmt.Value) - } - } else { - t.Errorf("%v: SetProxyV2TlvFmt Value should be set", s.Name) - } - } else { - t.Errorf("%v: SetProxyV2TlvFmt should be set", s.Name) - } - } - } - - _, servers, err = clientTest.GetServers("backend", "test_2", "") - if err != nil { - t.Error(err.Error()) - } - if len(servers) > 0 { - t.Errorf("%v servers returned, expected 0", len(servers)) - } -} - -func TestGetServer(t *testing.T) { - v, s, err := clientTest.GetServer("webserv", "backend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - if s.Name != "webserv" { - t.Errorf("Expected only webserv, %v found", s.Name) - } - if s.Address != "192.168.1.1" { - t.Errorf("%v: Address not 192.168.1.1: %v", s.Name, s.Address) - } - if *s.Port != 9200 { - t.Errorf("%v: Port not 9200: %v", s.Name, *s.Port) - } - if s.Ssl != "enabled" { - t.Errorf("%v: Ssl not enabled: %v", s.Name, s.Ssl) - } - if s.ClientSigalgs != "ECDSA+SHA256:RSA+SHA256" { - t.Errorf("%v: ClientSigalgs not ECDSA+SHA256:RSA+SHA256: %v", s.Name, s.ClientSigalgs) - } - if s.Cookie != "BLAH" { - t.Errorf("%v: HTTPCookieID not BLAH: %v", s.Name, s.Cookie) - } - if *s.Maxconn != 1000 { - t.Errorf("%v: MaxConnections not 1000: %v", s.Name, *s.Maxconn) - } - if *s.Weight != 10 { - t.Errorf("%v: Weight not 10: %v", s.Name, *s.Weight) - } - if *s.Inter != 2000 { - t.Errorf("%v: Inter not 2000: %v", s.Name, *s.Inter) - } - if s.Ws != "h1" { - t.Errorf("%v: Ws not h1: %v", s.Name, s.Ws) - } - if *s.PoolLowConn != 128 { - t.Errorf("%v: PoolLowConn not 128: %v", s.Name, *s.PoolLowConn) - } - if *s.ID != 1234 { - t.Errorf("%v: ID not 1234: %v", s.Name, *s.ID) - } - if len(s.ProxyV2Options) != 2 { - t.Errorf("%v: ProxyV2Options < 2: %d", s.Name, len(s.ProxyV2Options)) - } else { - if s.ProxyV2Options[0] != "authority" { - t.Errorf("%v: ProxyV2Options[0] not authority: %s", s.Name, s.ProxyV2Options[0]) - } - if s.ProxyV2Options[1] != "crc32c" { - t.Errorf("%v: ProxyV2Options[0] not crc32c: %s", s.Name, s.ProxyV2Options[1]) - } - } - if *s.PoolPurgeDelay != 10000 { - t.Errorf("%v: PoolPurgeDelay not 10000: %v", s.Name, *s.PoolPurgeDelay) - } - if *s.TCPUt != 2000 { - t.Errorf("%v: TCPUt not 2000: %v", s.Name, *s.TCPUt) - } - if s.Curves != "secp384r1" { - t.Errorf("%v: Curves not secp384r1: %v", s.Name, s.Curves) - } - if s.Sigalgs != "ECDSA+SHA256" { - t.Errorf("%v: Sigalgs not ECDSA+SHA256: %v", s.Name, s.Sigalgs) - } - if s.LogBufsize == nil || *s.LogBufsize != 10 { - t.Errorf("%v: LogBufsize should be 10: %v", s.Name, s.LogBufsize) - } - if s.SetProxyV2TlvFmt != nil { - if s.SetProxyV2TlvFmt.ID != nil { - if *s.SetProxyV2TlvFmt.ID != "0x20" { - t.Errorf("%v: SetProxyV2TlvFmt ID should be 0x20: %s", s.Name, *s.SetProxyV2TlvFmt.ID) - } - } else { - t.Errorf("%v: SetProxyV2TlvFmt ID should be set", s.Name) - } - if s.SetProxyV2TlvFmt.Value != nil { - if *s.SetProxyV2TlvFmt.Value != "%[fc_pp_tlv(0x20)]" { - t.Errorf("%v: SetProxyV2TlvFmt Value should be %%[fc_pp_tlv(0x20)]: %s", s.Name, *s.SetProxyV2TlvFmt.Value) - } - } else { - t.Errorf("%v: SetProxyV2TlvFmt Value should be set", s.Name) - } - } else { - t.Errorf("%v: SetProxyV2TlvFmt should be set", s.Name) - } - - _, err = s.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - _, _, err = clientTest.GetServer("webserv", "backend", "test_2", "") - if err == nil { - t.Error("Should throw error, non existent server") - } -} - -func TestGetRingServer(t *testing.T) { - v, s, err := clientTest.GetServer("mysyslogsrv", "ring", "myring", "") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - if s.Name != "mysyslogsrv" { - t.Errorf("Expected only mysyslogsrv, %v found", s.Name) - } - if s.Address != "127.0.0.1" { - t.Errorf("%v: Address not 127.0.0.1: %v", s.Name, s.Address) - } - if *s.Port != 6514 { - t.Errorf("%v: Port not 6514: %v", s.Name, *s.Port) - } - - if s.LogProto != "octet-count" { - t.Errorf("%v: log-proto not octet-count: %v", s.Name, s.LogProto) - } - - v, s, err = clientTest.GetServer("s1", "ring", "myring", "") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - if s.Name != "s1" { - t.Errorf("Expected only s1, %v found", s.Name) - } - if s.Address != "192.168.1.1" { - t.Errorf("%v: Address not 192.168.1.1: %v", s.Name, s.Address) - } - if *s.Port != 80 { - t.Errorf("%v: Port not 6514: %v", s.Name, *s.Port) - } - - if s.ResolveOpts != "allow-dup-ip,ignore-weight" { - t.Errorf("%v: resolve_opts not allow-dup-ip,ignore-weight: %v", s.Name, s.ResolveOpts) - } - - if s.ResolveNet != "10.0.0.0/8,10.200.200.0/12" { - t.Errorf("%v: resolve-net not 10.0.0.0/8,10.200.200.0/12: %v", s.Name, s.ResolveNet) - } - - _, err = s.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - _, _, err = clientTest.GetServer("non-existent", "ring", "myring", "") - if err == nil { - t.Error("Should throw error, non existent server") - } -} - -func TestCreateEditDeleteServer(t *testing.T) { - // TestCreateServer - port := int64(4300) - inter := int64(5000) - slowStart := int64(6000) - s := &models.Server{ - Name: "created", - Address: "192.168.2.1", - Port: &port, - ServerParams: models.ServerParams{ - Backup: "enabled", - Check: "enabled", - Maintenance: "enabled", - Ssl: "enabled", - AgentCheck: "enabled", - SslCertificate: "dummy.crt", - TLSTickets: "enabled", - Verify: "none", - Inter: &inter, - OnMarkedDown: "shutdown-sessions", - OnError: "mark-down", - OnMarkedUp: "shutdown-backup-sessions", - Slowstart: &slowStart, - ProxyV2Options: []string{"ssl", "unique-id"}, - Curves: "brainpoolP384r1", - Sigalgs: "RSA+SHA256", - ClientSigalgs: "ECDSA+SHA256", - LogBufsize: misc.Int64P(11), - SetProxyV2TlvFmt: &models.ServerParamsSetProxyV2TlvFmt{ - ID: misc.StringP("0x50"), - Value: misc.StringP("%[fc_pp_tlv(0x20)]"), - }, - }, - } - - err := clientTest.CreateServer("backend", "test", s, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, server, err := clientTest.GetServer("created", "backend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if !reflect.DeepEqual(server, s) { - fmt.Printf("Created server: %v\n", server) - fmt.Printf("Given server: %v\n", s) - t.Error("Created server not equal to given server") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - err = clientTest.CreateServer("backend", "test", s, "", version) - if err == nil { - t.Error("Should throw error server already exists") - version++ - } - - // TestEditServer - port = int64(5300) - slowStart = int64(3000) - s = &models.Server{ - Name: "created", - Address: "192.168.3.1", - Port: &port, - ServerParams: models.ServerParams{ - AgentCheck: "disabled", - Ssl: "enabled", - SslCertificate: "dummy.crt", - SslCafile: "dummy.ca", - TLSTickets: "disabled", - Verify: "required", - Slowstart: &slowStart, - }, - } - - err = clientTest.EditServer("created", "backend", "test", s, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, server, err = clientTest.GetServer("created", "backend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if !reflect.DeepEqual(server, s) { - fmt.Printf("Edited server: %v\n", server) - fmt.Printf("Given server: %v\n", s) - t.Error("Edited server not equal to given server") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestDeleteServer - err = clientTest.DeleteServer("created", "backend", "test", "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - if v, _ := clientTest.GetVersion(""); v != version { - t.Error("Version not incremented") - } - - _, _, err = clientTest.GetServer("created", "backend", "test", "") - if err == nil { - t.Error("DeleteServer failed, server test still exists") - } - - err = clientTest.DeleteServer("created", "backend", "test_2", "", version) - if err == nil { - t.Error("Should throw error, non existent server") - version++ - } -} - -func Test_parseAddress(t *testing.T) { - type args struct { - address string - } - tests := []struct { - name string - args args - wantIpOrAddress string - wantPort *int64 - }{ - { - name: "IPv6 with brackets", - args: args{address: "[fd00:6:48:c85:deb:f:62:4]:80"}, - wantIpOrAddress: "fd00:6:48:c85:deb:f:62:4", - wantPort: misc.Int64P(80), - }, - { - name: "IPv6 without brackets", - args: args{address: "fd00:6:48:c85:deb:f:62:4:443"}, - wantIpOrAddress: "fd00:6:48:c85:deb:f:62:4", - wantPort: misc.Int64P(443), - }, - { - name: "IPv6 without brackets, without port", - args: args{address: "fd00:6:48:c85:deb:f:62:a123"}, - wantIpOrAddress: "fd00:6:48:c85:deb:f:62:a123", - wantPort: nil, - }, - { - name: "IPv4 with port", - args: args{address: "10.1.1.2:8080"}, - wantIpOrAddress: "10.1.1.2", - wantPort: misc.Int64P(8080), - }, - { - name: "IPv4 without port", - args: args{address: "10.1.1.2"}, - wantIpOrAddress: "10.1.1.2", - wantPort: nil, - }, - { - name: "Socket address", - args: args{address: "/var/run/test_socket"}, - wantIpOrAddress: "/var/run/test_socket", - wantPort: nil, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - gotIpOrAddress, gotPort := parseAddress(tt.args.address) - if gotIpOrAddress != tt.wantIpOrAddress { - t.Errorf("parseAddress() gotIpOrAddress = %v, want %v", gotIpOrAddress, tt.wantIpOrAddress) - } - if gotPort != nil && tt.wantPort != nil && *gotPort != *tt.wantPort { - t.Errorf("parseAddress() gotPort = %v, want %v", gotPort, tt.wantPort) - } - }) - } -} diff --git a/configuration/service.go b/configuration/service.go index e824915b..45db0fca 100644 --- a/configuration/service.go +++ b/configuration/service.go @@ -34,7 +34,7 @@ type ServiceServer struct { Port int } -type serviceNode struct { +type ServiceNode struct { address string port int64 name string @@ -46,7 +46,7 @@ type serviceNode struct { type Service struct { client Configuration name string - nodes []*serviceNode + nodes []*ServiceNode usedNames map[string]struct{} transactionID string scaling ScalingParams @@ -75,7 +75,7 @@ func (c *client) NewService(name string, scaling ScalingParams) (*Service, error service := &Service{ client: c, name: name, - nodes: make([]*serviceNode, 0), + nodes: make([]*ServiceNode, 0), usedNames: make(map[string]struct{}), scaling: scaling, } @@ -158,7 +158,7 @@ func (s *Service) Update(servers []ServiceServer) (bool, error) { // GetServers returns the list of servers as they are currently configured in the services backend func (s *Service) GetServers() (models.Servers, error) { - _, servers, err := s.client.GetServers("backend", s.name, s.transactionID) + _, servers, err := s.client.GetServers(BackendParentName, s.name, s.transactionID) return servers, err } @@ -265,7 +265,7 @@ func (s *Service) getLastNodeIndex(nodeCount int) (int, bool) { func (s *Service) removeNodesAfterIndex(lastIndex int) error { for i := lastIndex; i < len(s.nodes); i++ { - err := s.client.DeleteServer(s.nodes[i].name, "backend", s.name, s.transactionID, 0) + err := s.client.DeleteServer(s.nodes[i].name, BackendParentName, s.name, s.transactionID, 0) if err != nil { return err } @@ -290,12 +290,12 @@ func (s *Service) createBackend(from string) (bool, error) { } func (s *Service) loadNodes() (bool, error) { - _, servers, err := s.client.GetServers("backend", s.name, s.transactionID) + _, servers, err := s.client.GetServers(BackendParentName, s.name, s.transactionID) if err != nil { return false, err } for _, server := range servers { - sNode := &serviceNode{ + sNode := &ServiceNode{ name: server.Name, address: server.Address, port: *server.Port, @@ -328,7 +328,7 @@ func (s *Service) updateConfig() (bool, error) { if node.disabled { server.Maintenance = "enabled" } - err := s.client.EditServer(node.name, "backend", s.name, server, s.transactionID, 0) + err := s.client.EditServer(node.name, BackendParentName, s.name, server, s.transactionID, 0) if err != nil { return false, err } @@ -339,7 +339,7 @@ func (s *Service) updateConfig() (bool, error) { return reload, nil } -func (s *Service) nodeRemoved(node *serviceNode, servers []ServiceServer) bool { +func (s *Service) nodeRemoved(node *ServiceNode, servers []ServiceServer) bool { for _, server := range servers { if s.nodesMatch(node, server) { return false @@ -348,7 +348,7 @@ func (s *Service) nodeRemoved(node *serviceNode, servers []ServiceServer) bool { return true } -func (s *Service) nodesMatch(sNode *serviceNode, servers ServiceServer) bool { +func (s *Service) nodesMatch(sNode *ServiceNode, servers ServiceServer) bool { return !sNode.disabled && sNode.address == servers.Address && sNode.port == int64(servers.Port) } @@ -385,11 +385,11 @@ func (s *Service) addNode() error { Maintenance: "enabled", }, } - err := s.client.CreateServer("backend", s.name, server, s.transactionID, 0) + err := s.client.CreateServer(BackendParentName, s.name, server, s.transactionID, 0) if err != nil { return err } - s.nodes = append(s.nodes, &serviceNode{ + s.nodes = append(s.nodes, &ServiceNode{ name: name, address: "127.0.0.1", port: 80, @@ -431,3 +431,7 @@ func (s *Service) swapDisabledNode(index int) { } } } + +func (s *Service) GetNodes() []*ServiceNode { + return s.nodes +} diff --git a/configuration/site.go b/configuration/site.go index b072adc9..1bd70737 100644 --- a/configuration/site.go +++ b/configuration/site.go @@ -116,7 +116,7 @@ func (c *client) CreateSite(data *models.Site, transactionID string, version int if l.Name == "" { l.Name = l.Address + ":" + strconv.FormatInt(*l.Port, 10) } - err = c.CreateBind("frontend", data.Name, l, t, 0) + err = c.CreateBind(FrontendParentName, data.Name, l, t, 0) if err != nil { res = append(res, err) } @@ -139,7 +139,7 @@ func (c *client) CreateSite(data *models.Site, transactionID string, version int if s.Name == "" { s.Name = s.Address + ":" + strconv.FormatInt(*s.Port, 10) } - err = c.CreateServer("backend", b.Name, s, t, 0) + err = c.CreateServer(BackendParentName, b.Name, s, t, 0) if err != nil { res = append(res, err) } @@ -194,7 +194,7 @@ func (c *client) EditSite(name string, data *models.Site, transactionID string, for _, confL := range confS.Service.Listeners { if l.Name == confL.Name { if !reflect.DeepEqual(l, confL) { - errB := c.EditBind(l.Name, "frontend", data.Name, l, t, 0) + errB := c.EditBind(l.Name, FrontendParentName, data.Name, l, t, 0) if errB != nil { res = append(res, errB) } @@ -208,7 +208,7 @@ func (c *client) EditSite(name string, data *models.Site, transactionID string, if l.Name == "" { l.Name = l.Address + ":" + strconv.FormatInt(*l.Port, 10) } - err = c.CreateBind("frontend", data.Name, l, t, 0) + err = c.CreateBind(FrontendParentName, data.Name, l, t, 0) if err != nil { res = append(res, err) } @@ -224,7 +224,7 @@ func (c *client) EditSite(name string, data *models.Site, transactionID string, } } if !found { - err = c.DeleteBind(confL.Name, "frontend", data.Name, t, 0) + err = c.DeleteBind(confL.Name, FrontendParentName, data.Name, t, 0) if err != nil { res = append(res, err) } @@ -250,7 +250,7 @@ func (c *client) EditSite(name string, data *models.Site, transactionID string, res = append(res, err) } for _, s := range b.Servers { - errC := c.CreateServer("backend", b.Name, s, t, 0) + errC := c.CreateServer(BackendParentName, b.Name, s, t, 0) if errC != nil { res = append(res, errC) } @@ -293,7 +293,7 @@ func (c *client) EditSite(name string, data *models.Site, transactionID string, for _, confSrv := range confB.Servers { if srv.Name == confSrv.Name { if !reflect.DeepEqual(srv, confSrv) { - errS := c.EditServer(srv.Name, "backend", b.Name, srv, t, 0) + errS := c.EditServer(srv.Name, BackendParentName, b.Name, srv, t, 0) if errS != nil { res = append(res, errS) } @@ -303,7 +303,7 @@ func (c *client) EditSite(name string, data *models.Site, transactionID string, } } if !found { - err = c.CreateServer("backend", b.Name, srv, t, 0) + err = c.CreateServer(BackendParentName, b.Name, srv, t, 0) if err != nil { res = append(res, err) } @@ -319,7 +319,7 @@ func (c *client) EditSite(name string, data *models.Site, transactionID string, } } if !found { - err = c.DeleteServer(confSrv.Name, "backend", b.Name, t, 0) + err = c.DeleteServer(confSrv.Name, BackendParentName, b.Name, t, 0) if err != nil { res = append(res, err) } @@ -471,7 +471,7 @@ func (c *client) parseSite(s string, p parser.Parser) *models.Site { return nil } - ls, _ := ParseBinds("frontend", s, p) + ls, _ := ParseBinds(FrontendParentName, s, p) site := &models.Site{ Name: s, Service: &models.SiteService{ @@ -507,7 +507,7 @@ func (c *client) parseFarm(name string, useAs string, cond string, condTest stri backend := &models.Backend{Name: name} if c.checkSectionExists(parser.Backends, name, p) { if err := ParseSection(backend, parser.Backends, name, p); err == nil { - srvs, err := ParseServers("backend", name, p) + srvs, err := ParseServers(BackendParentName, name, p) if err != nil { srvs = models.Servers{} } diff --git a/configuration/stick_rule.go b/configuration/stick_rule.go index 723af428..bd1e6a76 100644 --- a/configuration/stick_rule.go +++ b/configuration/stick_rule.go @@ -51,7 +51,7 @@ func (c *client) GetStickRules(backend string, transactionID string) (int64, mod sRules, err := ParseStickRules(backend, p) if err != nil { - return v, nil, c.HandleError("", "backend", backend, "", false, err) + return v, nil, c.HandleError("", BackendParentName, backend, "", false, err) } return v, sRules, nil @@ -72,7 +72,7 @@ func (c *client) GetStickRule(id int64, backend string, transactionID string) (i data, err := p.GetOne(parser.Backends, backend, "stick", int(id)) if err != nil { - return v, nil, c.HandleError(strconv.FormatInt(id, 10), "backend", backend, "", false, err) + return v, nil, c.HandleError(strconv.FormatInt(id, 10), BackendParentName, backend, "", false, err) } sRule := ParseStickRule(data.(types.Stick)) @@ -90,7 +90,7 @@ func (c *client) DeleteStickRule(id int64, backend string, transactionID string, } if err := p.Delete(parser.Backends, backend, "stick", int(id)); err != nil { - return c.HandleError(strconv.FormatInt(id, 10), "backend", backend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(id, 10), BackendParentName, backend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -111,7 +111,7 @@ func (c *client) CreateStickRule(backend string, data *models.StickRule, transac } if err := p.Insert(parser.Backends, backend, "stick", SerializeStickRule(*data), int(*data.Index)); err != nil { - return c.HandleError(strconv.FormatInt(*data.Index, 10), "backend", backend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(*data.Index, 10), BackendParentName, backend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -132,11 +132,11 @@ func (c *client) EditStickRule(id int64, backend string, data *models.StickRule, } if _, err := p.GetOne(parser.Backends, backend, "stick", int(id)); err != nil { - return c.HandleError(strconv.FormatInt(*data.Index, 10), "backend", backend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(*data.Index, 10), BackendParentName, backend, t, transactionID == "", err) } if err := p.Set(parser.Backends, backend, "stick", SerializeStickRule(*data), int(id)); err != nil { - return c.HandleError(strconv.FormatInt(*data.Index, 10), "backend", backend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(*data.Index, 10), BackendParentName, backend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") diff --git a/configuration/table.go b/configuration/table.go index f3eb8eaa..80129c70 100644 --- a/configuration/table.go +++ b/configuration/table.go @@ -51,7 +51,7 @@ func (c *client) GetTables(peerSection string, transactionID string) (int64, mod Tables, err := ParseTables(peerSection, p) if err != nil { - return v, nil, c.HandleError("", "peers", peerSection, "", false, err) + return v, nil, c.HandleError("", PeersParentName, peerSection, "", false, err) } return v, Tables, nil @@ -89,11 +89,11 @@ func (c *client) DeleteTable(name string, peerSection string, transactionID stri Table, i := GetTableByName(name, peerSection, p) if Table == nil { e := NewConfError(ErrObjectDoesNotExist, fmt.Sprintf("Table %s does not exist in peer section %s", name, peerSection)) - return c.HandleError(name, "peers", peerSection, t, transactionID == "", e) + return c.HandleError(name, PeersParentName, peerSection, t, transactionID == "", e) } if err := p.Delete(parser.Peers, peerSection, "table", i); err != nil { - return c.HandleError(name, "peers", peerSection, t, transactionID == "", err) + return c.HandleError(name, PeersParentName, peerSection, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -143,11 +143,11 @@ func (c *client) EditTable(name string, peerSection string, data *models.Table, Table, i := GetTableByName(name, peerSection, p) if Table == nil { e := NewConfError(ErrObjectDoesNotExist, fmt.Sprintf("Table %v does not exist in peer section %s", name, peerSection)) - return c.HandleError(data.Name, "peers", peerSection, t, transactionID == "", e) + return c.HandleError(data.Name, PeersParentName, peerSection, t, transactionID == "", e) } if err := p.Set(parser.Peers, peerSection, "table", SerializeTable(*data), i); err != nil { - return c.HandleError(data.Name, "peers", peerSection, t, transactionID == "", err) + return c.HandleError(data.Name, PeersParentName, peerSection, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") diff --git a/configuration/tcp_check.go b/configuration/tcp_check.go index adf4af24..5605f659 100644 --- a/configuration/tcp_check.go +++ b/configuration/tcp_check.go @@ -75,9 +75,9 @@ func (c *client) GetTCPCheck(id int64, parentType string, parentName string, tra } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "defaults" { + } else if parentType == DefaultsParentName { section = parser.Defaults if parentName == "" { parentName = parser.DefaultSectionName @@ -106,9 +106,9 @@ func (c *client) DeleteTCPCheck(id int64, parentType string, parentName string, } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "defaults" { + } else if parentType == DefaultsParentName { section = parser.Defaults if parentName == "" { parentName = parser.DefaultSectionName @@ -138,9 +138,9 @@ func (c *client) CreateTCPCheck(parentType string, parentName string, data *mode } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "defaults" { + } else if parentType == DefaultsParentName { section = parser.Defaults if parentName == "" { parentName = parser.DefaultSectionName @@ -172,9 +172,9 @@ func (c *client) EditTCPCheck(id int64, parentType string, parentName string, da return err } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "defaults" { + } else if parentType == DefaultsParentName { section = parser.Defaults if parentName == "" { parentName = parser.DefaultSectionName @@ -199,12 +199,12 @@ func (c *client) EditTCPCheck(id int64, parentType string, parentName string, da func ParseTCPChecks(t, pName string, p parser.Parser) (models.TCPChecks, error) { var section parser.Section switch t { - case "defaults": + case DefaultsParentName: section = parser.Defaults if pName == "" { pName = parser.DefaultSectionName } - case "backend": + case BackendParentName: section = parser.Backends default: return nil, NewConfError(ErrValidationError, fmt.Sprintf("unsupported section in tcp_check: %s", t)) diff --git a/configuration/tcp_request_rule.go b/configuration/tcp_request_rule.go index 8edd407a..7b72d779 100644 --- a/configuration/tcp_request_rule.go +++ b/configuration/tcp_request_rule.go @@ -77,9 +77,9 @@ func (c *client) GetTCPRequestRule(id int64, parentType, parentName string, tran } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -105,9 +105,9 @@ func (c *client) DeleteTCPRequestRule(id int64, parentType string, parentName st return err } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -134,9 +134,9 @@ func (c *client) CreateTCPRequestRule(parentType string, parentName string, data } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -169,9 +169,9 @@ func (c *client) EditTCPRequestRule(id int64, parentType string, parentName stri } var section parser.Section - if parentType == "backend" { + if parentType == BackendParentName { section = parser.Backends - } else if parentType == "frontend" { + } else if parentType == FrontendParentName { section = parser.Frontends } @@ -193,9 +193,9 @@ func (c *client) EditTCPRequestRule(id int64, parentType string, parentName stri func ParseTCPRequestRules(t, pName string, p parser.Parser) (models.TCPRequestRules, error) { section := parser.Global - if t == "frontend" { + if t == FrontendParentName { section = parser.Frontends - } else if t == "backend" { + } else if t == BackendParentName { section = parser.Backends } diff --git a/configuration/tcp_request_rule_test.go b/configuration/tcp_request_rule_test.go deleted file mode 100644 index 0227bda0..00000000 --- a/configuration/tcp_request_rule_test.go +++ /dev/null @@ -1,961 +0,0 @@ -// 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. -// - -package configuration - -import ( - "fmt" - "reflect" - "testing" - - "github.com/haproxytech/client-native/v5/misc" - "github.com/haproxytech/client-native/v5/models" -) - -func TestGetTCPRequestRules(t *testing.T) { //nolint:gocognit,gocyclo - v, tRules, err := clientTest.GetTCPRequestRules("frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if len(tRules) != 33 { - t.Errorf("%v tcp request rules returned, expected 33", len(tRules)) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - for _, r := range tRules { - switch *r.Index { - case 0: - if r.Type != "connection" { - t.Errorf("%v: Type not connection: %v", *r.Index, r.Type) - } - if r.Action != "accept" { - t.Errorf("%v: Action not accept: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not src TRUE: %v", *r.Index, r.CondTest) - } - case 1: - if r.Type != "connection" { - t.Errorf("%v: Type not connection: %v", *r.Index, r.Type) - } - if r.Action != "reject" { - t.Errorf("%v: Action not reject: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not src FALSE: %v", *r.Index, r.CondTest) - } - case 2: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "accept" { - t.Errorf("%v: Action not accept: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not src TRUE: %v", *r.Index, r.CondTest) - } - case 3: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "reject" { - t.Errorf("%v: Action not reject: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not src FALSE: %v", *r.Index, r.CondTest) - } - case 4: - if r.Type != "connection" { - t.Errorf("%v: Type not connection: %v", *r.Index, r.Type) - } - if r.Action != "silent-drop" { - t.Errorf("%v: Action not silent-drop: %v", *r.Index, r.Action) - } - if r.Cond != "" { - t.Errorf("%v: Cond not blank: %v", *r.Index, r.Cond) - } - if r.CondTest != "" { - t.Errorf("%v: CondTest not blank: %v", *r.Index, r.CondTest) - } - case 5: - if r.Type != "connection" { - t.Errorf("%v: Type not connection: %v", *r.Index, r.Type) - } - if r.Action != "silent-drop" { - t.Errorf("%v: Action not silent-drop: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not src TRUE: %v", *r.Index, r.CondTest) - } - case 6: - if r.Type != "connection" { - t.Errorf("%v: Type not connection: %v", *r.Index, r.Type) - } - if r.Action != "lua" { - t.Errorf("%v: Action not lua: %v", *r.Index, r.Action) - } - if r.LuaAction != "foo" { - t.Errorf("%v: LuaAction not foo: %v", *r.Index, r.LuaAction) - } - if r.LuaParams != "param1 param2" { - t.Errorf("%v: LuaParams not param1 param2: %v", *r.Index, r.LuaParams) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not src FALSE: %v", *r.Index, r.CondTest) - } - case 7: - if r.Type != "connection" { - t.Errorf("%v: Type not connection: %v", *r.Index, r.Type) - } - if r.Action != "sc-add-gpc" { - t.Errorf("%v: Type not sc-add-gpc: %v", *r.Index, r.Type) - } - if r.ScIdx != "0" { - t.Errorf("%v: ScIdx not 0: %v", *r.Index, r.ScIdx) - } - if r.ScIncID != "1" { - t.Errorf("%v: ScID not 1: %v", *r.Index, r.ScIncID) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 8: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "lua" { - t.Errorf("%v: Action not lua: %v", *r.Index, r.Action) - } - if r.LuaAction != "foo" { - t.Errorf("%v: LuaAction not foo: %v", *r.Index, r.LuaAction) - } - if r.LuaParams != "param1 param2" { - t.Errorf("%v: LuaParams not param1 param2: %v", *r.Index, r.LuaParams) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not src FALSE: %v", *r.Index, r.CondTest) - } - case 9: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "sc-add-gpc" { - t.Errorf("%v: Type not sc-add-gpc: %v", *r.Index, r.Type) - } - if r.ScIdx != "0" { - t.Errorf("%v: ScIdx not 0: %v", *r.Index, r.ScIdx) - } - if r.ScIncID != "1" { - t.Errorf("%v: ScID not 1: %v", *r.Index, r.ScIncID) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 10: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-bandwidth-limit" { - t.Errorf("%v: Action not set-bandwidth-limit: %v", *r.Index, r.Action) - } - if r.BandwidthLimitName != "my-limit" { - t.Errorf("%v: BandwidthLimitName not my-limit: %v", *r.Index, r.BandwidthLimitName) - } - if r.BandwidthLimitLimit != "1m" { - t.Errorf("%v: BandwidthLimitLimit not 1m: %v", *r.Index, r.BandwidthLimitLimit) - } - if r.BandwidthLimitPeriod != "10s" { - t.Errorf("%v: BandwidthLimitPeriod not 10s: %v", *r.Index, r.BandwidthLimitPeriod) - } - case 11: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-bandwidth-limit" { - t.Errorf("%v: Action not set-bandwidth-limit: %v", *r.Index, r.Action) - } - if r.BandwidthLimitName != "my-limit-reverse" { - t.Errorf("%v: BandwidthLimitName not my-limit-reverse: %v", *r.Index, r.BandwidthLimitName) - } - if r.BandwidthLimitLimit != "2m" { - t.Errorf("%v: BandwidthLimitLimit not 2m: %v", *r.Index, r.BandwidthLimitLimit) - } - if r.BandwidthLimitPeriod != "20s" { - t.Errorf("%v: BandwidthLimitPeriod no 20s: %v", *r.Index, r.BandwidthLimitPeriod) - } - case 12: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-bandwidth-limit" { - t.Errorf("%v: Action not set-bandwidth-limit: %v", *r.Index, r.Action) - } - if r.BandwidthLimitName != "my-limit-cond" { - t.Errorf("%v: BandwidthLimitName not my-limit-cond: %v", *r.Index, r.BandwidthLimitName) - } - if r.BandwidthLimitLimit != "3m" { - t.Errorf("%v: BandwidthLimitLimit not 3m: %v", *r.Index, r.BandwidthLimitLimit) - } - if r.BandwidthLimitPeriod != "" { - t.Errorf("%v: BandwidthLimitPeriod not empty", *r.Index) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 13: - if r.Type != "connection" { - t.Errorf("%v: Type not connection: %v", *r.Index, r.Type) - } - if r.Action != "set-mark" { - t.Errorf("%v: Action not set-mark: %v", *r.Index, r.Action) - } - if r.MarkValue != "0x1Ab" { - t.Errorf("%v: MarkValue not 0x1Ab: %v", *r.Index, r.MarkValue) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 14: - if r.Type != "connection" { - t.Errorf("%v: Type not connection: %v", *r.Index, r.Type) - } - if r.Action != "set-src-port" { - t.Errorf("%v: Action not set-src-port: %v", *r.Index, r.Action) - } - if r.Expr != "hdr(port)" { - t.Errorf("%v: Expr not hdr(port): %v", *r.Index, r.Expr) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 15: - if r.Type != "connection" { - t.Errorf("%v: Type not connection: %v", *r.Index, r.Type) - } - if r.Action != "set-tos" { - t.Errorf("%v: Action not set-tos: %v", *r.Index, r.Action) - } - if r.TosValue != "1" { - t.Errorf("%v: TosValue not 1: %v", *r.Index, r.TosValue) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 16: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-log-level" { - t.Errorf("%v: Action not set-log-level: %v", *r.Index, r.Action) - } - if r.LogLevel != "silent" { - t.Errorf("%v: LogLevel not silent %v", *r.Index, r.LogLevel) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 17: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-mark" { - t.Errorf("%v: Action not set-mark: %v", *r.Index, r.Action) - } - if r.MarkValue != "0x1Ac" { - t.Errorf("%v: MarkValue not 0x1Ac: %v", *r.Index, r.MarkValue) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 18: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-nice" { - t.Errorf("%v: Action not set-nice: %v", *r.Index, r.Action) - } - if r.NiceValue != 2 { - t.Errorf("%v: NiceValue not 2 %v", *r.Index, r.NiceValue) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 19: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-src-port" { - t.Errorf("%v: Action not set-src-port: %v", *r.Index, r.Action) - } - if r.Expr != "hdr(port)" { - t.Errorf("%v: Expr not hdr(port): %v", *r.Index, r.Expr) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 20: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-tos" { - t.Errorf("%v: Action not set-tos: %v", *r.Index, r.Action) - } - if r.TosValue != "3" { - t.Errorf("%v: TosValue not 3: %v", *r.Index, r.TosValue) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 21: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-var-fmt" { - t.Errorf("%v: Action not set-var-fmt: %v", *r.Index, r.Action) - } - if r.VarName != "tn" { - t.Errorf("%v: VarName not tn: %v", *r.Index, r.VarName) - } - if r.VarScope != "req" { - t.Errorf("%v: VarScope not req: %v", *r.Index, r.VarScope) - } - if r.VarFormat != "ssl_c_s_tn" { - t.Errorf("%v: VarFormat not ssl_c_s_tn: %v", *r.Index, r.VarFormat) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 22: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "switch-mode" { - t.Errorf("%v: Action not switch-mode: %v", *r.Index, r.Action) - } - if r.SwitchModeProto != "my-proto" { - t.Errorf("%v: SwitchModeProto not my-proto: %v", *r.Index, r.SwitchModeProto) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 23: - if r.Type != "session" { - t.Errorf("%v: Type not session: %v", *r.Index, r.Type) - } - if r.Action != "sc-add-gpc" { - t.Errorf("%v: Type not sc-add-gpc: %v", *r.Index, r.Type) - } - if r.ScIdx != "0" { - t.Errorf("%v: ScIdx not 0: %v", *r.Index, r.ScIdx) - } - if r.ScIncID != "1" { - t.Errorf("%v: ScID not 1: %v", *r.Index, r.ScIncID) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 24: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "track-sc" { - t.Errorf("%v: Action not track-sc: %v", *r.Index, r.Action) - } - if *r.TrackStickCounter != 0 { - t.Errorf("%v: TrackStickCounter not 0: %v", *r.Index, r.Action) - } - if r.TrackKey != "src" { - t.Errorf("%v: TrackKey not src: %v", *r.Index, r.Action) - } - if r.TrackTable != "tr0" { - t.Errorf("%v: TrackKey not tr0: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - - case 25: - if r.Type != "connection" { - t.Errorf("%v: Type not connection: %v", *r.Index, r.Type) - } - if r.Action != "track-sc" { - t.Errorf("%v: Action not track-sc: %v", *r.Index, r.Action) - } - if *r.TrackStickCounter != 0 { - t.Errorf("%v: TrackStickCounter not 0: %v", *r.Index, r.Action) - } - if r.TrackKey != "src" { - t.Errorf("%v: TrackKey not src: %v", *r.Index, r.Action) - } - if r.TrackTable != "tr0" { - t.Errorf("%v: TrackKey not tr0: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 26: - if r.Type != "session" { - t.Errorf("%v: Type not session: %v", *r.Index, r.Type) - } - if r.Action != "track-sc" { - t.Errorf("%v: Action not track-sc: %v", *r.Index, r.Action) - } - if *r.TrackStickCounter != 0 { - t.Errorf("%v: TrackStickCounter not 0: %v", *r.Index, r.Action) - } - if r.TrackKey != "src" { - t.Errorf("%v: TrackKey not src: %v", *r.Index, r.Action) - } - if r.TrackTable != "tr0" { - t.Errorf("%v: TrackKey not tr0: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 27: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "track-sc" { - t.Errorf("%v: Action not track-sc: %v", *r.Index, r.Action) - } - if *r.TrackStickCounter != 5 { - t.Errorf("%v: TrackStickCounter not 5: %v", *r.Index, r.Action) - } - if r.TrackKey != "src" { - t.Errorf("%v: TrackKey not src: %v", *r.Index, r.Action) - } - if r.TrackTable != "test" { - t.Errorf("%v: TrackKey not test: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 28: - if r.Type != "connection" { - t.Errorf("%v: Type not connection: %v", *r.Index, r.Type) - } - if r.Action != "track-sc" { - t.Errorf("%v: Action not track-sc: %v", *r.Index, r.Action) - } - if *r.TrackStickCounter != 5 { - t.Errorf("%v: TrackStickCounter not 5: %v", *r.Index, r.Action) - } - if r.TrackKey != "src" { - t.Errorf("%v: TrackKey not src: %v", *r.Index, r.Action) - } - if r.TrackTable != "test" { - t.Errorf("%v: TrackKey not test: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 29: - if r.Type != "session" { - t.Errorf("%v: Type not session: %v", *r.Index, r.Type) - } - if r.Action != "track-sc" { - t.Errorf("%v: Action not track-sc: %v", *r.Index, r.Action) - } - if *r.TrackStickCounter != 5 { - t.Errorf("%v: TrackStickCounter not 5: %v", *r.Index, r.Action) - } - if r.TrackKey != "src" { - t.Errorf("%v: TrackKey not src: %v", *r.Index, r.Action) - } - if r.TrackTable != "test" { - t.Errorf("%v: TrackKey not test: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 30: - if r.Type != "session" { - t.Errorf("%v: Type not session: %v", *r.Index, r.Type) - } - if r.Action != "attach-srv" { - t.Errorf("%v: Action not attach-srv: %v", *r.Index, r.Action) - } - if r.ServerName != "srv1" { - t.Errorf("%v: ServerName not srv1: %v", *r.Index, r.ServerName) - } - case 31: - if r.Type != "session" { - t.Errorf("%v: Type not session: %v", *r.Index, r.Type) - } - if r.Action != "attach-srv" { - t.Errorf("%v: Action not attach-srv: %v", *r.Index, r.Action) - } - if r.ServerName != "srv2" { - t.Errorf("%v: ServerName not srv2: %v", *r.Index, r.ServerName) - } - if r.Expr != "example.com" { - t.Errorf("%v: Expr not example.com: %v", *r.Index, r.Expr) - } - case 32: - if r.Type != "session" { - t.Errorf("%v: Type not session: %v", *r.Index, r.Type) - } - if r.Action != "attach-srv" { - t.Errorf("%v: Action not attach-srv: %v", *r.Index, r.Action) - } - if r.ServerName != "srv3" { - t.Errorf("%v: ServerName not srv1: %v", *r.Index, r.ServerName) - } - if r.Cond != "if" { - t.Errorf("%v: Cond is not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "is_cached" { - t.Errorf("%v: CondTest not is_cached: %v", *r.Index, r.CondTest) - } - default: - t.Errorf("Expect tcp-request 0-26, %v found", *r.Index) - } - } - - _, tRules, err = clientTest.GetTCPRequestRules("backend", "test_2", "") - if err != nil { - t.Error(err.Error()) - } - if len(tRules) > 0 { - t.Errorf("%v TCP Request Rules returned, expected 0", len(tRules)) - } -} - -func TestGetTCPRequestRule(t *testing.T) { - v, r, err := clientTest.GetTCPRequestRule(0, "frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - if r.Type != "connection" { - t.Errorf("%v: Type not connection: %v", *r.Index, r.Type) - } - if r.Action != "accept" { - t.Errorf("%v: Action not accept: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not src TRUE: %v", *r.Index, r.CondTest) - } - - _, err = r.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - _, _, err = clientTest.GetTCPRequestRule(3, "backend", "test_2", "") - if err == nil { - t.Error("Should throw error, non existent TCP Request Rule") - } -} - -func TestCreateEditDeleteTCPRequestRule(t *testing.T) { - id := int64(4) - tOut := int64(1000) - // TestCreateTCPRequestRule - r := &models.TCPRequestRule{ - Index: &id, - Type: "inspect-delay", - Timeout: &tOut, - } - - err := clientTest.CreateTCPRequestRule("frontend", "test", r, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, ondiskR, err := clientTest.GetTCPRequestRule(4, "frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if !reflect.DeepEqual(ondiskR, r) { - fmt.Printf("Created TCP request rule: %v\n", ondiskR) - fmt.Printf("Given TCP request rule: %v\n", r) - t.Error("Created TCP request rule not equal to given TCP request rule") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestEditTCPRequestRule - r = &models.TCPRequestRule{ - Index: &id, - Type: "connection", - Action: "accept", - Cond: "if", - CondTest: "FALSE", - } - - err = clientTest.EditTCPRequestRule(4, "frontend", "test", r, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, ondiskR, err = clientTest.GetTCPRequestRule(4, "frontend", "test", "") - if err != nil { - t.Error(err.Error()) - } - - if !reflect.DeepEqual(ondiskR, r) { - fmt.Printf("Edited TCP request rule: %v\n", ondiskR) - fmt.Printf("Given TCP request rule: %v\n", r) - t.Error("Edited TCP request rule not equal to given TCP request rule") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestDeleteTCPRequest - err = clientTest.DeleteTCPRequestRule(33, "frontend", "test", "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - if v, _ := clientTest.GetVersion(""); v != version { - t.Error("Version not incremented") - } - - _, _, err = clientTest.GetTCPRequestRule(33, "frontend", "test", "") - if err == nil { - t.Error("DeleteTCPRequestRule failed, TCP Request Rule 33 still exists") - } - - err = clientTest.DeleteTCPRequestRule(27, "backend", "test_2", "", version) - if err == nil { - t.Error("Should throw error, non existent TCP Request Rule") - version++ - } -} - -func TestSerializeTCPRequestRule(t *testing.T) { - testCases := []struct { - input models.TCPRequestRule - expectedResult string - }{ - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeConnection, - Action: models.TCPRequestRuleActionSilentDashDrop, - Cond: "if", - CondTest: "FALSE", - }, - expectedResult: "connection silent-drop if FALSE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeContent, - Action: models.TCPRequestRuleActionSilentDashDrop, - Cond: "if", - CondTest: "FALSE", - }, - expectedResult: "content silent-drop if FALSE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeSession, - Action: models.TCPRequestRuleActionSilentDashDrop, - Cond: "if", - CondTest: "FALSE", - }, - expectedResult: "session silent-drop if FALSE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeConnection, - Action: models.TCPRequestRuleActionExpectDashProxy, - Cond: "if", - CondTest: "{ src 1.2.3.4 5.6.7.8 }", - }, - expectedResult: "connection expect-proxy layer4 if { src 1.2.3.4 5.6.7.8 }", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeConnection, - Action: models.TCPRequestRuleActionTrackDashSc, - Cond: "if", - CondTest: "TRUE", - TrackKey: "src", - TrackTable: "tr0", - TrackStickCounter: misc.Int64P(3), - }, - expectedResult: "connection track-sc3 src table tr0 if TRUE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeConnection, - Action: models.TCPRequestRuleActionTrackDashSc0, - Cond: "if", - CondTest: "TRUE", - TrackKey: "src", - TrackTable: "tr0", - }, - expectedResult: "connection track-sc0 src table tr0 if TRUE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeConnection, - Action: models.TCPRequestRuleActionTrackDashSc1, - Cond: "if", - CondTest: "TRUE", - TrackKey: "src", - TrackTable: "tr1", - }, - expectedResult: "connection track-sc1 src table tr1 if TRUE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeConnection, - Action: models.TCPRequestRuleActionTrackDashSc2, - Cond: "if", - CondTest: "TRUE", - TrackKey: "src", - TrackTable: "tr2", - }, - expectedResult: "connection track-sc2 src table tr2 if TRUE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeContent, - Action: models.TCPRequestRuleActionTrackDashSc, - Cond: "if", - CondTest: "TRUE", - TrackKey: "src", - TrackTable: "tr0", - TrackStickCounter: misc.Int64P(3), - }, - expectedResult: "content track-sc3 src table tr0 if TRUE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeContent, - Action: models.TCPRequestRuleActionTrackDashSc0, - Cond: "if", - CondTest: "TRUE", - TrackKey: "src", - TrackTable: "tr0", - }, - expectedResult: "content track-sc0 src table tr0 if TRUE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeContent, - Action: models.TCPRequestRuleActionTrackDashSc1, - Cond: "if", - CondTest: "TRUE", - TrackKey: "src", - TrackTable: "tr1", - }, - expectedResult: "content track-sc1 src table tr1 if TRUE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeContent, - Action: models.TCPRequestRuleActionTrackDashSc2, - Cond: "if", - CondTest: "TRUE", - TrackKey: "src", - TrackTable: "tr2", - }, - expectedResult: "content track-sc2 src table tr2 if TRUE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeSession, - Action: models.TCPRequestRuleActionTrackDashSc, - Cond: "if", - CondTest: "TRUE", - TrackKey: "src", - TrackTable: "tr0", - TrackStickCounter: misc.Int64P(3), - }, - expectedResult: "session track-sc3 src table tr0 if TRUE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeSession, - Action: models.TCPRequestRuleActionTrackDashSc0, - Cond: "if", - CondTest: "TRUE", - TrackKey: "src", - TrackTable: "tr0", - }, - expectedResult: "session track-sc0 src table tr0 if TRUE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeSession, - Action: models.TCPRequestRuleActionTrackDashSc1, - Cond: "if", - CondTest: "TRUE", - TrackKey: "src", - TrackTable: "tr1", - }, - expectedResult: "session track-sc1 src table tr1 if TRUE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeSession, - Action: models.TCPRequestRuleActionTrackDashSc2, - Cond: "if", - CondTest: "TRUE", - TrackKey: "src", - TrackTable: "tr2", - }, - expectedResult: "session track-sc2 src table tr2 if TRUE", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeSession, - Action: models.TCPRequestRuleActionAttachDashSrv, - ServerName: "srv8", - Expr: "haproxy.org", - }, - expectedResult: "session attach-srv srv8 name haproxy.org", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeSession, - Action: models.TCPRequestRuleActionAttachDashSrv, - ServerName: "srv8", - }, - expectedResult: "session attach-srv srv8", - }, - { - input: models.TCPRequestRule{ - Type: models.TCPRequestRuleTypeSession, - Action: models.TCPRequestRuleActionAttachDashSrv, - ServerName: "srv8", - Cond: "unless", - CondTest: "limit_exceeded", - }, - expectedResult: "session attach-srv srv8 unless limit_exceeded", - }, - } - - for _, testCase := range testCases { - t.Run(testCase.expectedResult, func(t *testing.T) { - tcpType, err := SerializeTCPRequestRule(testCase.input) - if err != nil { - t.Error(err.Error()) - } - - actual := tcpType.String() - if actual != testCase.expectedResult { - t.Errorf("Expected %q, got: %q", testCase.expectedResult, actual) - } - }) - } -} diff --git a/configuration/tcp_response_rule.go b/configuration/tcp_response_rule.go index f977e2f5..a2ea7023 100644 --- a/configuration/tcp_response_rule.go +++ b/configuration/tcp_response_rule.go @@ -56,7 +56,7 @@ func (c *client) GetTCPResponseRules(backend string, transactionID string) (int6 tcpRules, err := ParseTCPResponseRules(backend, p) if err != nil { - return v, nil, c.HandleError("", "backend", backend, "", false, err) + return v, nil, c.HandleError("", BackendParentName, backend, "", false, err) } return v, tcpRules, nil @@ -77,7 +77,7 @@ func (c *client) GetTCPResponseRule(id int64, backend string, transactionID stri data, err := p.GetOne(parser.Backends, backend, "tcp-response", int(id)) if err != nil { - return v, nil, c.HandleError(strconv.FormatInt(id, 10), "backend", backend, "", false, err) + return v, nil, c.HandleError(strconv.FormatInt(id, 10), BackendParentName, backend, "", false, err) } tcpRule, parseErr := ParseTCPResponseRule(data.(types.TCPType)) @@ -98,7 +98,7 @@ func (c *client) DeleteTCPResponseRule(id int64, backend string, transactionID s } if err := p.Delete(parser.Backends, backend, "tcp-response", int(id)); err != nil { - return c.HandleError(strconv.FormatInt(id, 10), "backend", backend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(id, 10), BackendParentName, backend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -123,7 +123,7 @@ func (c *client) CreateTCPResponseRule(backend string, data *models.TCPResponseR return serializeErr } if err := p.Insert(parser.Backends, backend, "tcp-response", tcpRule, int(*data.Index)); err != nil { - return c.HandleError(strconv.FormatInt(*data.Index, 10), "backend", backend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(*data.Index, 10), BackendParentName, backend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") @@ -144,7 +144,7 @@ func (c *client) EditTCPResponseRule(id int64, backend string, data *models.TCPR } if _, err := p.GetOne(parser.Backends, backend, "tcp-response", int(id)); err != nil { - return c.HandleError(strconv.FormatInt(*data.Index, 10), "backend", backend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(*data.Index, 10), BackendParentName, backend, t, transactionID == "", err) } tcpRule, serializeErr := SerializeTCPResponseRule(*data) @@ -152,7 +152,7 @@ func (c *client) EditTCPResponseRule(id int64, backend string, data *models.TCPR return serializeErr } if err := p.Set(parser.Backends, backend, "tcp-response", tcpRule, int(id)); err != nil { - return c.HandleError(strconv.FormatInt(*data.Index, 10), "backend", backend, t, transactionID == "", err) + return c.HandleError(strconv.FormatInt(*data.Index, 10), BackendParentName, backend, t, transactionID == "", err) } return c.SaveData(p, t, transactionID == "") diff --git a/configuration/tcp_response_rule_test.go b/configuration/tcp_response_rule_test.go deleted file mode 100644 index c0850701..00000000 --- a/configuration/tcp_response_rule_test.go +++ /dev/null @@ -1,472 +0,0 @@ -// 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. -// - -package configuration - -import ( - "fmt" - "reflect" - "testing" - - "github.com/haproxytech/client-native/v5/models" -) - -func TestGetTCPResponseRules(t *testing.T) { //nolint:gocognit - v, tRules, err := clientTest.GetTCPResponseRules("test", "") - if err != nil { - t.Error(err.Error()) - } - - if len(tRules) != 18 { - t.Errorf("%v tcp response rules returned, expected 17", len(tRules)) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - for _, r := range tRules { - switch *r.Index { - case 0: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "accept" { - t.Errorf("%v: Action not accept: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not src TRUE: %v", *r.Index, r.CondTest) - } - case 1: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "reject" { - t.Errorf("%v: Action not reject: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not src FALSE: %v", *r.Index, r.CondTest) - } - case 2: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "lua" { - t.Errorf("%v: Action not lua: %v", *r.Index, r.Action) - } - if r.LuaAction != "foo" { - t.Errorf("%v: LuaAction not foo: %v", *r.Index, r.LuaAction) - } - if r.LuaParams != "param1 param2" { - t.Errorf("%v: LuaParams not param1 param2: %v", *r.Index, r.LuaParams) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not src FALSE: %v", *r.Index, r.CondTest) - } - case 3: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-bandwidth-limit" { - t.Errorf("%v: Action not set-bandwidth-limit: %v", *r.Index, r.Action) - } - if r.BandwidthLimitName != "my-limit" { - t.Errorf("%v: BandwidthLimitName not my-limit: %v", *r.Index, r.BandwidthLimitName) - } - if r.BandwidthLimitLimit != "1m" { - t.Errorf("%v: BandwidthLimitLimit not 1m: %v", *r.Index, r.BandwidthLimitLimit) - } - if r.BandwidthLimitPeriod != "10s" { - t.Errorf("%v: BandwidthLimitPeriod not 10s: %v", *r.Index, r.BandwidthLimitPeriod) - } - case 4: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-bandwidth-limit" { - t.Errorf("%v: Action not set-bandwidth-limit: %v", *r.Index, r.Action) - } - if r.BandwidthLimitName != "my-limit-reverse" { - t.Errorf("%v: BandwidthLimitName not my-limit-reverse: %v", *r.Index, r.BandwidthLimitName) - } - if r.BandwidthLimitLimit != "2m" { - t.Errorf("%v: BandwidthLimitLimit not 2m: %v", *r.Index, r.BandwidthLimitLimit) - } - if r.BandwidthLimitPeriod != "20s" { - t.Errorf("%v: BandwidthLimitPeriod no 20s: %v", *r.Index, r.BandwidthLimitPeriod) - } - case 5: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-bandwidth-limit" { - t.Errorf("%v: Action not set-bandwidth-limit: %v", *r.Index, r.Action) - } - if r.BandwidthLimitName != "my-limit-cond" { - t.Errorf("%v: BandwidthLimitName not my-limit-cond: %v", *r.Index, r.BandwidthLimitName) - } - if r.BandwidthLimitLimit != "3m" { - t.Errorf("%v: BandwidthLimitLimit not 3m: %v", *r.Index, r.BandwidthLimitLimit) - } - if r.BandwidthLimitPeriod != "" { - t.Errorf("%v: BandwidthLimitPeriod not empty", *r.Index) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 6: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "close" { - t.Errorf("%v: Action not close: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 7: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "sc-add-gpc" { - t.Errorf("%v: Type not sc-add-gpc: %v", *r.Index, r.Type) - } - if r.ScIdx != 0 { - t.Errorf("%v: ScIdx not 0: %v", *r.Index, r.ScIdx) - } - if r.ScID != 1 { - t.Errorf("%v: ScID not 1: %v", *r.Index, r.ScID) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 8: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "sc-inc-gpc0" { - t.Errorf("%v: Action not sc-inc-gpc0: %v", *r.Index, r.Action) - } - if r.ScID != 1 { - t.Errorf("%v: ScID not 1 %v", *r.Index, r.ScID) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 9: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "sc-inc-gpc1" { - t.Errorf("%v: Action not sc-inc-gpc1: %v", *r.Index, r.Action) - } - if r.ScID != 2 { - t.Errorf("%v: ScID not 2 %v", *r.Index, r.ScID) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 10: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "sc-set-gpt0" { - t.Errorf("%v: Action not sc-set-gpt0: %v", *r.Index, r.Action) - } - if r.ScID != 3 { - t.Errorf("%v: ScID not 3 %v", *r.Index, r.ScID) - } - if r.Expr != "hdr(Host),lower" { - t.Errorf("%v: Expr not hdr(Host),lower: %v", *r.Index, r.Expr) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 11: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "send-spoe-group" { - t.Errorf("%v: Action not send-spoe-group: %v", *r.Index, r.Action) - } - if r.SpoeEngine != "engine" { - t.Errorf("%v: SpoeEngine not engine %v", *r.Index, r.SpoeEngine) - } - if r.SpoeGroup != "group" { - t.Errorf("%v: SpoeGroup not group %v", *r.Index, r.SpoeGroup) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 12: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-log-level" { - t.Errorf("%v: Action not set-log-level: %v", *r.Index, r.Action) - } - if r.LogLevel != "silent" { - t.Errorf("%v: LogLevel not silent %v", *r.Index, r.LogLevel) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 13: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-mark" { - t.Errorf("%v: Action not set-mark: %v", *r.Index, r.Action) - } - if r.MarkValue != "0x1Ab" { - t.Errorf("%v: MarkValue not 0x1Ab %v", *r.Index, r.MarkValue) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 14: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-nice" { - t.Errorf("%v: Action not set-nice: %v", *r.Index, r.Action) - } - if r.NiceValue != 1 { - t.Errorf("%v: NiceValue not 1 %v", *r.Index, r.NiceValue) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 15: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "set-tos" { - t.Errorf("%v: Action not set-tos: %v", *r.Index, r.Action) - } - if r.TosValue != "2" { - t.Errorf("%v: TosValue not 2 %v", *r.Index, r.TosValue) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 16: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "silent-drop" { - t.Errorf("%v: Action not silent-drop: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - case 17: - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "unset-var" { - t.Errorf("%v: Action not unset-var: %v", *r.Index, r.Action) - } - if r.VarName != "my_var" { - t.Errorf("%v: VarName not my_var: %v", *r.Index, r.VarName) - } - if r.VarScope != "req" { - t.Errorf("%v: VarScope not req: %v", *r.Index, r.VarScope) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "FALSE" { - t.Errorf("%v: CondTest not FALSE: %v", *r.Index, r.CondTest) - } - default: - t.Errorf("Expect only tcp-response 0 to 17 %v found", *r.Index) - } - } - - _, tRules, err = clientTest.GetTCPResponseRules("test_2", "") - if err != nil { - t.Error(err.Error()) - } - if len(tRules) > 0 { - t.Errorf("%v TCP Response Rules returned, expected 0", len(tRules)) - } -} - -func TestGetTCPResponseRule(t *testing.T) { - v, r, err := clientTest.GetTCPResponseRule(0, "test", "") - if err != nil { - t.Error(err.Error()) - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - if r.Type != "content" { - t.Errorf("%v: Type not content: %v", *r.Index, r.Type) - } - if r.Action != "accept" { - t.Errorf("%v: Action not accept: %v", *r.Index, r.Action) - } - if r.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *r.Index, r.Cond) - } - if r.CondTest != "TRUE" { - t.Errorf("%v: CondTest not src TRUE: %v", *r.Index, r.CondTest) - } - - _, err = r.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - _, _, err = clientTest.GetTCPResponseRule(3, "test_2", "") - if err == nil { - t.Error("Should throw error, non existent TCP Response Rule") - } -} - -func TestCreateEditDeleteTCPResponseRule(t *testing.T) { - id := int64(2) - tOut := int64(1000) - // TestCreateTCPResponseRule - r := &models.TCPResponseRule{ - Index: &id, - Type: "inspect-delay", - Timeout: &tOut, - } - - err := clientTest.CreateTCPResponseRule("test", r, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, ondiskR, err := clientTest.GetTCPResponseRule(2, "test", "") - if err != nil { - t.Error(err.Error()) - } - - if !reflect.DeepEqual(ondiskR, r) { - fmt.Printf("Created TCP response rule: %v\n", ondiskR) - fmt.Printf("Given TCP response rule: %v\n", r) - t.Error("Created TCP response rule not equal to given TCP response rule") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestEditTCPResponseRule - r = &models.TCPResponseRule{ - Index: &id, - Type: "content", - Action: "accept", - Cond: "if", - CondTest: "FALSE", - } - - err = clientTest.EditTCPResponseRule(2, "test", r, "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - v, ondiskR, err = clientTest.GetTCPResponseRule(2, "test", "") - if err != nil { - t.Error(err.Error()) - } - - if !reflect.DeepEqual(ondiskR, r) { - fmt.Printf("Edited TCP response rule: %v\n", ondiskR) - fmt.Printf("Given TCP response rule: %v\n", r) - t.Error("Edited TCP response rule not equal to given TCP response rule") - } - - if v != version { - t.Errorf("Version %v returned, expected %v", v, version) - } - - // TestDeleteTCPResponse - err = clientTest.DeleteTCPResponseRule(18, "test", "", version) - if err != nil { - t.Error(err.Error()) - } else { - version++ - } - - if v, _ := clientTest.GetVersion(""); v != version { - t.Error("Version not incremented") - } - - _, _, err = clientTest.GetTCPResponseRule(18, "test", "") - if err == nil { - t.Error("DeleteTCPResponseRule failed, TCP Response Rule 17 still exists") - } - - err = clientTest.DeleteTCPResponseRule(18, "test_2", "", version) - if err == nil { - t.Error("Should throw error, non existent TCP Response Rule") - version++ - } -} diff --git a/configuration/acl_test.go b/test/acl_test.go similarity index 51% rename from configuration/acl_test.go rename to test/acl_test.go index 877baf04..98b39dea 100644 --- a/configuration/acl_test.go +++ b/test/acl_test.go @@ -13,20 +13,41 @@ // limitations under the License. // -package configuration +package test import ( + _ "embed" "fmt" "reflect" + "strings" "testing" + "github.com/google/go-cmp/cmp" parser "github.com/haproxytech/config-parser/v5" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" - "github.com/haproxytech/client-native/v5/misc" + "github.com/haproxytech/client-native/v5/configuration" "github.com/haproxytech/client-native/v5/models" ) +func aclExpectation() map[string]models.Acls { + initStructuredExpected() + res := StructuredToACLMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%d", k, *v.Index) + keyName := fmt.Sprintf("%s/%s", k, v.ACLName) + if _, ok := res[keyName]; !ok { + res[keyName] = models.Acls{} + } + res[keyName] = append(res[keyName], v) + res[key] = models.Acls{v} + } + } + return res +} + func TestClient_GetACLs(t *testing.T) { type args struct { parentType string @@ -38,88 +59,69 @@ func TestClient_GetACLs(t *testing.T) { name string args args want int64 - want1 models.Acls wantErr bool }{ { - name: "Should return acl list in one fcgi-app", - args: args{parentType: string(parser.FCGIApp), parentName: "test", transactionID: ""}, - want: 1, - want1: models.Acls{ - &models.ACL{ACLName: "invalid_src", Criterion: "src", Index: misc.Int64P(0), Value: "0.0.0.0/7 224.0.0.0/3"}, - &models.ACL{ACLName: "invalid_src", Criterion: "src_port", Index: misc.Int64P(1), Value: "0:1023"}, - &models.ACL{ACLName: "local_dst", Criterion: "hdr(host)", Index: misc.Int64P(2), Value: "-i localhost"}, - }, + name: "Should return acl list in one fcgi-app", + args: args{parentType: string(parser.FCGIApp), parentName: "test", transactionID: ""}, + want: 1, wantErr: false, }, { - name: "Should return acl list in one fcgi-app by acl name", - args: args{parentType: string(parser.FCGIApp), parentName: "test", transactionID: "", aclName: []string{"invalid_src"}}, - want: 1, - want1: models.Acls{ - &models.ACL{ACLName: "invalid_src", Criterion: "src", Index: misc.Int64P(0), Value: "0.0.0.0/7 224.0.0.0/3"}, - &models.ACL{ACLName: "invalid_src", Criterion: "src_port", Index: misc.Int64P(1), Value: "0:1023"}, - }, + name: "Should return acl list in one fcgi-app by acl name", + args: args{parentType: string(parser.FCGIApp), parentName: "test", transactionID: "", aclName: []string{"invalid_src"}}, + want: 1, wantErr: false, }, { name: "Should return acl list in one fcgi-app by acl name 2", args: args{parentType: string(parser.FCGIApp), parentName: "test", transactionID: "", aclName: []string{"local_dst"}}, want: 1, - want1: models.Acls{ - &models.ACL{ACLName: "local_dst", Criterion: "hdr(host)", Index: misc.Int64P(2), Value: "-i localhost"}, - }, + wantErr: false, }, { - name: "Should return acl list in one frontend", - args: args{parentType: string(parser.Frontends), parentName: "test", transactionID: ""}, - want: 1, - want1: models.Acls{ - &models.ACL{ACLName: "invalid_src", Criterion: "src", Index: misc.Int64P(0), Value: "0.0.0.0/7 224.0.0.0/3"}, - &models.ACL{ACLName: "invalid_src", Criterion: "src_port", Index: misc.Int64P(1), Value: "0:1023"}, - &models.ACL{ACLName: "local_dst", Criterion: "hdr(host)", Index: misc.Int64P(2), Value: "-i localhost"}, - &models.ACL{ACLName: "waf_wafTest_drop", Criterion: "var(txn.wafTest.drop),bool", Index: misc.Int64P(3), Value: ""}, - }, + name: "Should return acl list in one frontend", + args: args{parentType: string(parser.Frontends), parentName: "test", transactionID: ""}, + want: 1, wantErr: false, }, { - name: "Should return acl list in one frontend by acl name", - args: args{parentType: string(parser.Frontends), parentName: "test", transactionID: "", aclName: []string{"invalid_src"}}, - want: 1, - want1: models.Acls{ - &models.ACL{ACLName: "invalid_src", Criterion: "src", Index: misc.Int64P(0), Value: "0.0.0.0/7 224.0.0.0/3"}, - &models.ACL{ACLName: "invalid_src", Criterion: "src_port", Index: misc.Int64P(1), Value: "0:1023"}, - }, + name: "Should return acl list in one frontend by acl name", + args: args{parentType: string(parser.Frontends), parentName: "test", transactionID: "", aclName: []string{"invalid_src"}}, + want: 1, wantErr: false, }, { - name: "Should return acl list in one frontend by acl name 2", - args: args{parentType: string(parser.Frontends), parentName: "test", transactionID: "", aclName: []string{"local_dst"}}, - want: 1, - want1: models.Acls{ - &models.ACL{ACLName: "local_dst", Criterion: "hdr(host)", Index: misc.Int64P(2), Value: "-i localhost"}, - }, + name: "Should return acl list in one frontend by acl name 2", + args: args{parentType: string(parser.Frontends), parentName: "test", transactionID: "", aclName: []string{"local_dst"}}, + want: 1, wantErr: false, }, { name: "Should return empty slice when no acl in given section", args: args{parentType: string(parser.Backends), parentName: "test_2", transactionID: ""}, want: 1, - want1: models.Acls{}, wantErr: false, }, { name: "Should return an error when parentName doesn't exist", args: args{parentType: string(parser.Backends), parentName: "not_exists", transactionID: ""}, want: 1, - want1: nil, wantErr: true, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { + macls := make(map[string]models.Acls) got, got1, err := clientTest.GetACLs(tt.args.parentType, tt.args.parentName, tt.args.transactionID, tt.args.aclName...) + key := fmt.Sprintf("%s/%s", tt.args.parentType, tt.args.parentName) + if len(tt.args.aclName) > 0 { + key += fmt.Sprintf("/%s", strings.Join(tt.args.aclName, ",")) + } + if !tt.wantErr { + macls[key] = got1 + } if (err != nil) != tt.wantErr { t.Errorf("clientTest.GetACLs() error = %v, wantErr %v", err, tt.wantErr) return @@ -127,15 +129,15 @@ func TestClient_GetACLs(t *testing.T) { if got != tt.want { t.Errorf("clientTest.GetACLs() got = %v, want %v", got, tt.want) } - if !assert.EqualValues(t, got1, tt.want1) { - t.Errorf("clientTest.GetACLs() got1 = %v, want %v", got1, tt.want1) - } + checksACLs(t, macls) }) } } func TestGetACL(t *testing.T) { - v, acl, err := clientTest.GetACL(0, "frontend", "test", "") + macl := make(map[string]models.Acls) + + v, acl, err := clientTest.GetACL(0, configuration.FrontendParentName, "test", "") if err != nil { t.Error(err.Error()) } @@ -144,45 +146,51 @@ func TestGetACL(t *testing.T) { t.Errorf("Version %v returned, expected %v", v, version) } - if *acl.Index != 0 { - t.Errorf("ACL ID not 0, %v found", *acl.Index) - } - if acl.ACLName != "invalid_src" { - t.Errorf("%v: ACLName not invalid_src: %v", *acl.Index, acl.ACLName) - } - if acl.Value != "0.0.0.0/7 224.0.0.0/3" { - t.Errorf("%v: Value not 0.0.0.0/7 224.0.0.0/3: %v", *acl.Index, acl.Value) - } - if acl.Criterion != "src" { - t.Errorf("%v: Criterion not src: %v", *acl.Index, acl.Criterion) - } + macl["frontend/test/0"] = []*models.ACL{acl} + checksACLs(t, macl) _, err = acl.MarshalBinary() if err != nil { t.Error(err.Error()) } - _, _, err = clientTest.GetACL(3, "backend", "test_2", "") + _, _, err = clientTest.GetACL(3, configuration.BackendParentName, "test_2", "") if err == nil { t.Error("Should throw error, non existent ACL") } - - _, _, err = clientTest.GetACL(100, "frontend", "fake", "") + _, _, err = clientTest.GetACL(100, configuration.FrontendParentName, "fake", "") if err == nil { t.Error("Should throw error, non existent frontend and ACL") } - _, _, err = clientTest.GetACL(100, "backend", "fake", "") + _, _, err = clientTest.GetACL(100, configuration.BackendParentName, "fake", "") if err == nil { t.Error("Should throw error, non existent backend and ACL") } - _, _, err = clientTest.GetACL(100, "fcgi-app", "fake", "") + _, _, err = clientTest.GetACL(100, configuration.FCGIAppParentName, "fake", "") if err == nil { t.Error("Should throw error, non existent backend and ACL") } } +func checksACLs(t *testing.T, got map[string]models.Acls) { + exp := aclExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + func TestCreateEditDeleteACL(t *testing.T) { id := int64(1) @@ -194,14 +202,14 @@ func TestCreateEditDeleteACL(t *testing.T) { Value: "lt 2", } - err := clientTest.CreateACL("frontend", "test", r, "", version) + err := clientTest.CreateACL(configuration.FrontendParentName, "test", r, "", version) if err != nil { t.Error(err.Error()) } else { version++ } - v, ondiskR, err := clientTest.GetACL(1, "frontend", "test", "") + v, ondiskR, err := clientTest.GetACL(1, configuration.FrontendParentName, "test", "") if err != nil { t.Error(err.Error()) } @@ -224,14 +232,14 @@ func TestCreateEditDeleteACL(t *testing.T) { Value: "lt 4", } - err = clientTest.EditACL(1, "frontend", "test", r, "", version) + err = clientTest.EditACL(1, configuration.FrontendParentName, "test", r, "", version) if err != nil { t.Error(err.Error()) } else { version++ } - v, ondiskR, err = clientTest.GetACL(1, "frontend", "test", "") + v, ondiskR, err = clientTest.GetACL(1, configuration.FrontendParentName, "test", "") if err != nil { t.Error(err.Error()) } @@ -247,7 +255,7 @@ func TestCreateEditDeleteACL(t *testing.T) { } // TestDeleteACL - err = clientTest.DeleteACL(4, "frontend", "test", "", version) + err = clientTest.DeleteACL(4, configuration.FrontendParentName, "test", "", version) if err != nil { t.Error(err.Error()) } else { @@ -258,12 +266,12 @@ func TestCreateEditDeleteACL(t *testing.T) { t.Error("Version not incremented") } - _, _, err = clientTest.GetACL(4, "frontend", "test", "") + _, _, err = clientTest.GetACL(4, configuration.FrontendParentName, "test", "") if err == nil { t.Error("DeleteACL failed, ACL Rule 4 still exists") } - err = clientTest.DeleteACL(2, "backend", "test_2", "", version) + err = clientTest.DeleteACL(2, configuration.BackendParentName, "test_2", "", version) if err == nil { t.Error("Should throw error, non existent ACL Rule") version++ diff --git a/configuration/backend_switching_rule_test.go b/test/backend_switching_rule_test.go similarity index 75% rename from configuration/backend_switching_rule_test.go rename to test/backend_switching_rule_test.go index 343bdf9f..2019d7df 100644 --- a/configuration/backend_switching_rule_test.go +++ b/test/backend_switching_rule_test.go @@ -13,58 +13,74 @@ // limitations under the License. // -package configuration +package test import ( + _ "embed" "fmt" "reflect" "testing" + "github.com/google/go-cmp/cmp" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func bsrExpectation() map[string]models.BackendSwitchingRules { + initStructuredExpected() + res := StructuredToBackendSwitchingRuleMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%d", k, *v.Index) + res[key] = models.BackendSwitchingRules{v} + } + } + return res +} + func TestGetBackendSwitchingRules(t *testing.T) { + mbsr := make(map[string]models.BackendSwitchingRules) + v, bckRules, err := clientTest.GetBackendSwitchingRules("test", "") if err != nil { t.Error(err.Error()) } - if len(bckRules) != 2 { - t.Errorf("%v backend switching rules returned, expected 2", len(bckRules)) - } - if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - - for _, br := range bckRules { - if *br.Index == 0 { - if br.Name != "test_2" { - t.Errorf("%v: Name not test_2: %v", *br.Index, br.Name) - } - if br.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *br.Index, br.Cond) - } - if br.CondTest != "TRUE" { - t.Errorf("%v: CondTest not TRUE: %v", *br.Index, br.CondTest) - } - } else if *br.Index == 1 { - if br.Name != "%[req.cookie(foo)]" { - t.Errorf("%v: Name not %%[req.cookie(foo)]: %v", *br.Index, br.Name) - } - } - } + mbsr["frontend/test"] = bckRules _, bckRules, err = clientTest.GetBackendSwitchingRules("test_2", "") if err != nil { t.Error(err.Error()) } - if len(bckRules) > 0 { - t.Errorf("%v backend switching rules returned, expected 0", len(bckRules)) + mbsr["frontend/test_2"] = bckRules + + checkBackendSwitchingRules(t, mbsr) +} + +func checkBackendSwitchingRules(t *testing.T, got map[string]models.BackendSwitchingRules) { + exp := bsrExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } } } func TestGetBackendSwitchingRule(t *testing.T) { + mbsr := make(map[string]models.BackendSwitchingRules) + v, br, err := clientTest.GetBackendSwitchingRule(0, "test", "") if err != nil { t.Error(err.Error()) @@ -73,19 +89,9 @@ func TestGetBackendSwitchingRule(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } + mbsr["frontend/test/0"] = models.BackendSwitchingRules{br} - if *br.Index != 0 { - t.Errorf("ID only backend switching rule 0, %v found", *br.Index) - } - if br.Name != "test_2" { - t.Errorf("%v: Name not test_2: %v", *br.Index, br.Name) - } - if br.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *br.Index, br.Cond) - } - if br.CondTest != "TRUE" { - t.Errorf("%v: CondTest not TRUE: %v", *br.Index, br.CondTest) - } + checkBackendSwitchingRules(t, mbsr) _, err = br.MarshalBinary() if err != nil { diff --git a/test/backend_test.go b/test/backend_test.go new file mode 100644 index 00000000..317c3e47 --- /dev/null +++ b/test/backend_test.go @@ -0,0 +1,860 @@ +// 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. +// + +package test + +import ( + _ "embed" + "fmt" + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/haproxytech/client-native/v5/configuration" + "github.com/haproxytech/client-native/v5/misc" + "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" +) + +func backendExpectation() map[string]models.Backends { + initStructuredExpected() + res := StructuredToBackendMap() + // Add individual entries + for _, vs := range res { + for _, v := range vs { + key := v.Name + res[key] = models.Backends{v} + } + } + return res +} + +func TestGetBackends(t *testing.T) { //nolint:gocognit,gocyclo + m := make(map[string]models.Backends) + v, backends, err := clientTest.GetBackends("") + if err != nil { + t.Error(err.Error()) + } + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + m[""] = backends + + checkBackends(t, m) +} + +func checkBackends(t *testing.T, got map[string]models.Backends) { + exp := backendExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + +func TestGetBackend(t *testing.T) { + m := make(map[string]models.Backends) + + v, b, err := clientTest.GetBackend("test", "") + if err != nil { + t.Error(err.Error()) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + m["test"] = models.Backends{b} + + _, err = b.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + _, _, err = clientTest.GetBackend("doesnotexist", "") + if err == nil { + t.Error("Should throw error, non existent bck") + } + + checkBackends(t, m) +} + +func TestCreateEditDeleteBackend(t *testing.T) { + // TestCreateBackend + tOut := int64(5) + cookieName := "BLA" + balanceAlgorithm := "uri" + srvtcpkaCnt := int64(10) + srvtcpkaTimeout := int64(10000) + statsRealm := "Haproxy Stats" + b := &models.Backend{ + Name: "created", + Mode: "http", + Balance: &models.Balance{ + Algorithm: &balanceAlgorithm, + URILen: 100, + URIDepth: 250, + }, + BindProcess: "4", + Cookie: &models.Cookie{ + Domains: []*models.Domain{ + {Value: "dom1"}, + {Value: "dom2"}, + }, + Attrs: []*models.Attr{}, + Dynamic: true, + Httponly: true, + Indirect: true, + Maxidle: 5, + Maxlife: 20, + Name: &cookieName, + Nocache: true, + Postonly: true, + Preserve: false, + Secure: false, + Type: "prefix", + }, + HashType: &models.HashType{ + Method: "map-based", + Function: "crc32", + }, + DefaultServer: &models.DefaultServer{ + ServerParams: models.ServerParams{ + Fall: &tOut, + Inter: &tOut, + LogBufsize: misc.Int64P(123), + }, + }, + HTTPConnectionMode: "http-keep-alive", + HTTPKeepAlive: "enabled", + ConnectTimeout: &tOut, + ExternalCheck: "enabled", + ExternalCheckCommand: "/bin/false", + ExternalCheckPath: "/bin", + Allbackups: "enabled", + AdvCheck: "smtpchk", + SmtpchkParams: &models.SmtpchkParams{ + Hello: "HELO", + Domain: "example.com", + }, + AcceptInvalidHTTPResponse: "enabled", + Compression: &models.Compression{ + Offload: true, + }, + LogHealthChecks: "enabled", + Checkcache: "enabled", + IndependentStreams: "enabled", + Nolinger: "enabled", + Originalto: &models.Originalto{ + Enabled: misc.StringP("enabled"), + Except: "127.0.0.1", + Header: "X-Client-Dst", + }, + Persist: "enabled", + PreferLastServer: "enabled", + SpopCheck: "enabled", + TCPSmartConnect: "enabled", + Transparent: "enabled", + SpliceAuto: "enabled", + SpliceRequest: "enabled", + SpliceResponse: "enabled", + SrvtcpkaCnt: &srvtcpkaCnt, + SrvtcpkaIdle: &srvtcpkaTimeout, + SrvtcpkaIntvl: &srvtcpkaTimeout, + StatsOptions: &models.StatsOptions{ + StatsShowModules: true, + StatsRealm: true, + StatsRealmRealm: &statsRealm, + StatsAuths: []*models.StatsAuth{ + {User: misc.StringP("user1"), Passwd: misc.StringP("pwd1")}, + {User: misc.StringP("user2"), Passwd: misc.StringP("pwd2")}, + }, + StatsHTTPRequests: []*models.StatsHTTPRequest{ + {Type: misc.StringP("allow"), Cond: "if", CondTest: "something"}, + {Type: misc.StringP("auth"), Realm: "haproxy\\ stats"}, + }, + }, + EmailAlert: &models.EmailAlert{ + From: misc.StringP("prod01@example.com"), + To: misc.StringP("sre@example.com"), + Level: "warning", + Mailers: misc.StringP("localmailer1"), + }, + ErrorFilesFromHTTPErrors: []*models.Errorfiles{ + {Name: "test_errors", Codes: []int64{400}}, + {Name: "test_errors_all"}, + }, + Disabled: true, + } + + err := clientTest.CreateBackend(b, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, backend, err := clientTest.GetBackend("created", "") + if err != nil { + t.Error(err.Error()) + } + + var givenJSONB []byte + givenJSONB, err = b.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + var ondiskJSONB []byte + ondiskJSONB, err = backend.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + if string(givenJSONB) != string(ondiskJSONB) { + fmt.Printf("Created backend: %v\n", string(ondiskJSONB)) + fmt.Printf("Given backend: %v\n", string(givenJSONB)) + t.Error("Created backend not equal to given backend") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + err = clientTest.CreateBackend(b, "", version) + if err == nil { + t.Error("Should throw error bck already exists") + version++ + } + // TestEditBackend + tOut = int64(3) + e := int64(1200000) + kl := int64(128) + s := int64(25600) + backends := []*models.Backend{ + { + From: "test_defaults", + Name: "created", + Mode: "http", + Balance: &models.Balance{ + Algorithm: &balanceAlgorithm, + URILen: 10, + URIDepth: 25, + }, + BindProcess: "3", + Cookie: &models.Cookie{ + Domains: []*models.Domain{ + {Value: "dom1"}, + {Value: "dom3"}, + }, + Dynamic: true, + Httponly: true, + Indirect: false, + Maxidle: 150, + Maxlife: 100, + Name: &cookieName, + Nocache: false, + Postonly: false, + Preserve: true, + Secure: true, + Type: "rewrite", + }, + // Use non deprecated option only + HTTPConnectionMode: "httpclose", + ConnectTimeout: &tOut, + StickTable: &models.ConfigStickTable{ + Expire: &e, + Keylen: &kl, + Size: &s, + Store: "gpc0,http_req_rate(40s)", + Type: "string", + }, + AdvCheck: "mysql-check", + MysqlCheckParams: &models.MysqlCheckParams{ + Username: "user", + ClientVersion: "pre-41", + }, + EmailAlert: &models.EmailAlert{ + From: misc.StringP("prod01@example.com"), + To: misc.StringP("sre@example.com"), + Level: "warning", + Mailers: misc.StringP("localmailer1"), + }, + Originalto: &models.Originalto{ + Enabled: misc.StringP("enabled"), + Except: "127.0.0.1", + }, + }, + { + Name: "created", + Mode: "http", + Balance: &models.Balance{ + Algorithm: &balanceAlgorithm, + }, + Cookie: &models.Cookie{ + Domains: []*models.Domain{ + {Value: "dom1"}, + {Value: "dom2"}, + }, + Name: &cookieName, + }, + ConnectTimeout: &tOut, + StickTable: &models.ConfigStickTable{}, + AdvCheck: "pgsql-check", + PgsqlCheckParams: &models.PgsqlCheckParams{ + Username: "user", + }, + EmailAlert: &models.EmailAlert{ + From: misc.StringP("prod01@example.com"), + To: misc.StringP("sre@example.com"), + Level: "warning", + Mailers: misc.StringP("localmailer1"), + }, + // Use deprecated option only + Httpclose: "enabled", + Originalto: &models.Originalto{ + Enabled: misc.StringP("enabled"), + Header: "X-Client-Dst", + }, + }, + { + Name: "created", + Mode: "http", + Balance: &models.Balance{ + Algorithm: &balanceAlgorithm, + }, + Cookie: &models.Cookie{ + Domains: []*models.Domain{ + {Value: "dom4"}, + {Value: "dom5"}, + }, + Name: &cookieName, + }, + ConnectTimeout: &tOut, + StickTable: &models.ConfigStickTable{}, + AdvCheck: "httpchk", + HttpchkParams: &models.HttpchkParams{ + Method: "HEAD", + URI: "/", + }, + HTTPCheck: &models.HTTPCheck{ + Type: "send", + Method: "OPTIONS", + URI: "/", + Version: "HTTP/1.1", + Index: misc.Int64P(0), + }, + Checkcache: "disabled", + IndependentStreams: "disabled", + Nolinger: "disabled", + Persist: "disabled", + PreferLastServer: "disabled", + SpopCheck: "disabled", + TCPSmartConnect: "disabled", + Transparent: "disabled", + SpliceAuto: "disabled", + SpliceRequest: "disabled", + SpliceResponse: "disabled", + SrvtcpkaCnt: &srvtcpkaCnt, + SrvtcpkaIdle: &srvtcpkaTimeout, + SrvtcpkaIntvl: &srvtcpkaTimeout, + StatsOptions: &models.StatsOptions{ + StatsShowModules: true, + StatsRealm: true, + StatsRealmRealm: &statsRealm, + StatsAuths: []*models.StatsAuth{ + {User: misc.StringP("new_user1"), Passwd: misc.StringP("new_pwd1")}, + {User: misc.StringP("new_user2"), Passwd: misc.StringP("new_pwd2")}, + }, + StatsHTTPRequests: []*models.StatsHTTPRequest{ + {Type: misc.StringP("allow"), Cond: "if", CondTest: "something_else"}, + {Type: misc.StringP("auth"), Realm: "haproxy\\ stats2"}, + }, + }, + EmailAlert: &models.EmailAlert{ + From: misc.StringP("prod01@example.com"), + To: misc.StringP("sre@example.com"), + Level: "warning", + Mailers: misc.StringP("localmailer1"), + }, + Originalto: &models.Originalto{ + Enabled: misc.StringP("enabled"), + Except: "127.0.0.1", + Header: "X-Client-Dst", + }, + }, + } + + for i, backend := range backends { + if errB := testBackendUpdate(backend, t); errB != nil { + t.Errorf("failed update for backend %d: %v", i, errB) + } + } + + // TestDeleteBackend + err = clientTest.DeleteBackend("created", "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + if v, _ := clientTest.GetVersion(""); v != version { + t.Error("Version not incremented") + } + + err = clientTest.DeleteBackend("created", "", 999999999) + if err != nil { + if confErr, ok := err.(*configuration.ConfError); ok { + if !confErr.Is(configuration.ErrVersionMismatch) { + t.Error("Should throw configuration.ErrVersionMismatch error") + } + } else { + t.Error("Should throw configuration.ErrVersionMismatch error") + } + } + + _, _, err = clientTest.GetBackend("created", "") + if err == nil { + t.Error("DeleteBackend failed, bck test still exists") + } + + err = clientTest.DeleteBackend("doesnotexist", "", version) + if err == nil { + t.Error("Should throw error, non existent bck") + version++ + } +} + +func testBackendUpdate(b *models.Backend, t *testing.T) error { + err := clientTest.EditBackend("created", b, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, backend, err := clientTest.GetBackend("created", "") + if err != nil { + return err + } + + if !compareBackends(backend, b, t) { + fmt.Printf("Edited bck: %+v\n", backend) + fmt.Printf("Given bck: %+v\n", b) + return fmt.Errorf("edited backend not equal to given backend") + } + + if v != version { + return fmt.Errorf("version %v returned, expected %v", v, version) + } + return nil +} + +func compareBackends(x, y *models.Backend, t *testing.T) bool { //nolint:gocognit,gocyclo + if *x.Balance.Algorithm != *y.Balance.Algorithm { + return false + } + if x.Balance.HdrName != y.Balance.HdrName { + return false + } + if x.Balance.HdrUseDomainOnly != y.Balance.HdrUseDomainOnly { + return false + } + if x.Balance.RandomDraws != y.Balance.RandomDraws { + return false + } + if x.Balance.RdpCookieName != y.Balance.RdpCookieName { + return false + } + if x.Balance.URIDepth != y.Balance.URIDepth { + return false + } + if x.Balance.URILen != y.Balance.URILen { + return false + } + if x.Balance.URIWhole != y.Balance.URIWhole { + return false + } + if x.Balance.URLParam != y.Balance.URLParam { + return false + } + if x.Balance.URLParamCheckPost != y.Balance.URLParamCheckPost { + return false + } + if x.Balance.URLParamMaxWait != y.Balance.URLParamMaxWait { + return false + } + + x.Balance = nil + y.Balance = nil + + if *x.Cookie.Name != *y.Cookie.Name { + return false + } + if len(x.Cookie.Domains) != len(y.Cookie.Domains) { + return false + } + if x.Cookie.Domains[0].Value != y.Cookie.Domains[0].Value { + return false + } + if x.Cookie.Dynamic != y.Cookie.Dynamic { + return false + } + if x.Cookie.Httponly != y.Cookie.Httponly { + return false + } + if x.Cookie.Indirect != y.Cookie.Indirect { + return false + } + if x.Cookie.Maxidle != y.Cookie.Maxidle { + return false + } + if x.Cookie.Maxlife != y.Cookie.Maxlife { + return false + } + if x.Cookie.Nocache != y.Cookie.Nocache { + return false + } + if x.Cookie.Postonly != y.Cookie.Postonly { + return false + } + if x.Cookie.Preserve != y.Cookie.Preserve { + return false + } + if x.Cookie.Secure != y.Cookie.Secure { + return false + } + if x.Cookie.Type != y.Cookie.Type { + return false + } + + x.Cookie = nil + y.Cookie = nil + + if x.BindProcess != y.BindProcess { + return false + } + + if !reflect.DeepEqual(x.DefaultServer, y.DefaultServer) { + return false + } + + x.DefaultServer = nil + y.DefaultServer = nil + + if !reflect.DeepEqual(x.HttpchkParams, y.HttpchkParams) { + return false + } + + x.HttpchkParams = nil + y.HttpchkParams = nil + + if !cmp.Equal(x.HTTPCheck, y.HTTPCheck, cmpopts.EquateEmpty()) { + t.Errorf("Diff in HTTPChecK %s", cmp.Diff(x.HTTPCheck, y.HTTPCheck, cmpopts.EquateEmpty())) + return false + } + + x.HTTPCheck = nil + y.HTTPCheck = nil + + if !reflect.DeepEqual(x.StickTable, y.StickTable) { + return false + } + + x.StickTable = nil + y.StickTable = nil + + if !reflect.DeepEqual(x.Redispatch, y.Redispatch) { + return false + } + + x.Redispatch = nil + y.Redispatch = nil + + if !reflect.DeepEqual(x.Forwardfor, y.Forwardfor) { + return false + } + + x.Forwardfor = nil + y.Forwardfor = nil + + if !reflect.DeepEqual(x.SmtpchkParams, y.SmtpchkParams) { + return false + } + + x.SmtpchkParams = nil + y.SmtpchkParams = nil + + if !reflect.DeepEqual(x.MysqlCheckParams, y.MysqlCheckParams) { + return false + } + + x.MysqlCheckParams = nil + y.MysqlCheckParams = nil + + if !reflect.DeepEqual(x.PgsqlCheckParams, y.PgsqlCheckParams) { + return false + } + + x.PgsqlCheckParams = nil + y.PgsqlCheckParams = nil + + if !reflect.DeepEqual(x.Originalto, y.Originalto) { + return false + } + + x.Originalto = nil + y.Originalto = nil + + // Due to deprecated fields Httpclose, HTTPKeepAlive, HTTPServerClose + // in favor of HTTPConnectionMode + // If HTTPConnectionMode is set in original backend + // - Httpclose, HTTPKeepAlive, HTTPServerClose will be set in updated backend, even if not present in original backend + // If HTTPConnectionMode is unset in original backend: + // - it will be set in updated backend + switch y.HTTPConnectionMode { + case "http-keep-alive": + if x.HTTPKeepAlive != "enabled" { + return false + } + x.HTTPKeepAlive = "" + case "http-server-close": + if x.HTTPServerClose != "enabled" { + return false + } + x.HTTPServerClose = "" + case "httpclose": + if x.Httpclose != "enabled" { + return false + } + x.Httpclose = "" + case "": + x.HTTPConnectionMode = "" + } + + return reflect.DeepEqual(x, y) +} + +func TestCreateEditDeleteBackendHTTPConnectionMode(t *testing.T) { + // TestCreateBackend + tOut := int64(5) + + // Backend with HTTPConnectionMode only + b := &models.Backend{ + Name: "special-httpconnectionmode", + Mode: "http", + DefaultServer: &models.DefaultServer{ + ServerParams: models.ServerParams{ + Fall: &tOut, + Inter: &tOut, + }, + }, + HTTPConnectionMode: "http-keep-alive", + } + + err := clientTest.CreateBackend(b, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, backend, err := clientTest.GetBackend("special-httpconnectionmode", "") + if err != nil { + t.Error(err.Error()) + } + + if backend.HTTPConnectionMode != "http-keep-alive" { + t.Errorf("Created backend is not correct for HTTPConnectionMode: %s", backend.HTTPConnectionMode) + } + if backend.HTTPKeepAlive != "enabled" { + t.Errorf("Created backend is not correct for HTTPKeepAlive: %s", backend.HTTPConnectionMode) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + err = clientTest.CreateBackend(b, "", version) + if err == nil { + t.Error("Should throw error bck already exists") + version++ + } + + type testinput struct { + backend *models.Backend + expectedHTTPConnectionMode string + expectedHTTPKeepAlive string + expectedHttpclose string + exptectedHTTPServerClose string + } + // TestEditBackend + inputs := []testinput{ + { + // Update HTTPConnectionMode + backend: &models.Backend{ + Name: "special-httpconnectionmode", + Mode: "http", + DefaultServer: &models.DefaultServer{ + ServerParams: models.ServerParams{ + Fall: &tOut, + Inter: &tOut, + }, + }, + HTTPConnectionMode: "httpclose", + }, + expectedHTTPConnectionMode: "httpclose", + expectedHTTPKeepAlive: "", + exptectedHTTPServerClose: "", + expectedHttpclose: "enabled", + }, + { + // Use only deprecated option + backend: &models.Backend{ + Name: "special-httpconnectionmode", + Mode: "http", + DefaultServer: &models.DefaultServer{ + ServerParams: models.ServerParams{ + Fall: &tOut, + Inter: &tOut, + }, + }, + HTTPServerClose: "enabled", + }, + expectedHTTPConnectionMode: "http-server-close", + expectedHTTPKeepAlive: "", + exptectedHTTPServerClose: "enabled", + expectedHttpclose: "", + }, + { + // Use both - Priority on HTTPConnection + backend: &models.Backend{ + Name: "special-httpconnectionmode", + Mode: "http", + DefaultServer: &models.DefaultServer{ + ServerParams: models.ServerParams{ + Fall: &tOut, + Inter: &tOut, + }, + }, + HTTPConnectionMode: "http-keep-alive", + HTTPServerClose: "enabled", + }, + expectedHTTPConnectionMode: "http-keep-alive", + expectedHTTPKeepAlive: "enabled", + exptectedHTTPServerClose: "", + expectedHttpclose: "", + }, + { + // no option with deprecated option + backend: &models.Backend{ + Name: "special-httpconnectionmode", + Mode: "http", + DefaultServer: &models.DefaultServer{ + ServerParams: models.ServerParams{ + Fall: &tOut, + Inter: &tOut, + }, + }, + HTTPServerClose: "disabled", + }, + expectedHTTPConnectionMode: "", // not possible to set no option with this field + expectedHTTPKeepAlive: "", + exptectedHTTPServerClose: "disabled", + expectedHttpclose: "", + }, + { + // set back with HTTPConnectionMode + backend: &models.Backend{ + Name: "special-httpconnectionmode", + Mode: "http", + DefaultServer: &models.DefaultServer{ + ServerParams: models.ServerParams{ + Fall: &tOut, + Inter: &tOut, + }, + }, + HTTPConnectionMode: "httpclose", + }, + expectedHTTPConnectionMode: "httpclose", + expectedHTTPKeepAlive: "", + exptectedHTTPServerClose: "", + expectedHttpclose: "enabled", + }, + { + // remove option + backend: &models.Backend{ + Name: "special-httpconnectionmode", + Mode: "http", + DefaultServer: &models.DefaultServer{ + ServerParams: models.ServerParams{ + Fall: &tOut, + Inter: &tOut, + }, + }, + HTTPConnectionMode: "", + }, + expectedHTTPConnectionMode: "", + expectedHTTPKeepAlive: "", + exptectedHTTPServerClose: "", + expectedHttpclose: "", + }, + } + + for i, input := range inputs { + err := clientTest.EditBackend("special-httpconnectionmode", input.backend, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + _, backend, err := clientTest.GetBackend("special-httpconnectionmode", "") + if err != nil { + t.Error(err.Error()) + } + + if backend.HTTPConnectionMode != input.expectedHTTPConnectionMode { + t.Errorf("Updated backend %d is not correct for HTTPConnectionMode: %s", i, backend.HTTPConnectionMode) + } + if backend.HTTPKeepAlive != input.expectedHTTPKeepAlive { + t.Errorf("Updated backend %d is not correct for HTTPKeepAlive: %s", i, backend.HTTPConnectionMode) + } + if backend.HTTPServerClose != input.exptectedHTTPServerClose { + t.Errorf("Updated backend %d is not correct for HTTPServerClose: %s", i, backend.HTTPServerClose) + } + if backend.Httpclose != input.expectedHttpclose { + t.Errorf("Updated backend %d is not correct for Httpclose: %s", i, backend.Httpclose) + } + + } + + // TestDeleteBackend + err = clientTest.DeleteBackend("special-httpconnectionmode", "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } +} diff --git a/configuration/bind_test.go b/test/bind_test.go similarity index 56% rename from configuration/bind_test.go rename to test/bind_test.go index f1d405ea..07a3e707 100644 --- a/configuration/bind_test.go +++ b/test/bind_test.go @@ -13,18 +13,37 @@ // limitations under the License. // -package configuration +package test import ( + _ "embed" "fmt" "reflect" "testing" + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func bindExpectation() map[string]models.Binds { + initStructuredExpected() + res := StructuredToBindMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%s", k, v.Name) + res[key] = models.Binds{v} + } + } + return res +} + func TestGetBinds(t *testing.T) { - v, binds, err := clientTest.GetBinds("frontend", "test", "") + mbinds := map[string]models.Binds{} + + v, binds, err := clientTest.GetBinds(configuration.FrontendParentName, "test", "") if err != nil { t.Error(err.Error()) } @@ -36,42 +55,38 @@ func TestGetBinds(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } + mbinds["frontend/test"] = binds - for _, l := range binds { - if l.Name != "webserv" && l.Name != "webserv2" && l.Name != "webserv3" && l.Name != "ipv6" && l.Name != "test-quic" && l.Name != "testnbcon" { - t.Errorf("Expected only webserv,webserv2, or ipv6 binds, %v found", l.Name) - } - if l.Address != "192.168.1.1" && l.Address != "192.168.1.2" && l.Address != "2a01:c9c0:a3:8::3" { - t.Errorf("%v: Address not 192.168.1.1 or 192.168.1.2 or 2a01:c9c0:a3:8::3: %v", l.Name, l.Address) - } - if *l.Port != 80 && *l.Port != 8080 { - t.Errorf("%v: Port not 80 or 8080: %v", l.Name, *l.Port) - } - if l.Thread != "all" && l.Thread != "1/all" && l.Thread != "1/1" && l.Thread != "1/1-1" { - t.Errorf("%v: Thread not all or 1/all or 1/1-1: %v", l.Name, l.Thread) - } - if l.Name == "test-quic" && l.QuicSocket != "connection" { - t.Errorf("%v: quic-soket not connection: %v", l.Name, l.QuicSocket) - } - if l.Name != "testnbcon" && l.Nbconn != 0 { - t.Errorf("%v: nbcon should be 0: %v", l.Name, l.Nbconn) - } - if l.Name == "testnbcon" && l.Nbconn != 6 { - t.Errorf("%v: nbconn should be 6: %v", l.Name, l.Nbconn) - } - } - - _, binds, err = clientTest.GetBinds("frontend", "test_2", "") + _, binds, err = clientTest.GetBinds(configuration.FrontendParentName, "test_2", "") if err != nil { t.Error(err.Error()) } - if len(binds) > 0 { - t.Errorf("%v binds returned, expected 0", len(binds)) + + mbinds["frontend/test_2"] = binds + + checkBinds(t, mbinds) +} + +func checkBinds(t *testing.T, got map[string]models.Binds) { + exp := bindExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } } } func TestGetBind(t *testing.T) { - v, l, err := clientTest.GetBind("webserv", "frontend", "test", "") + m := make(map[string]models.Binds) + v, l, err := clientTest.GetBind("webserv", configuration.FrontendParentName, "test", "") if err != nil { t.Error(err.Error()) } @@ -79,36 +94,10 @@ func TestGetBind(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } + m["frontend/test/webserv"] = models.Binds{l} + checkBinds(t, m) - if l.Name != "webserv" { - t.Errorf("Expected only webserv or webserv2 binds, %v found", l.Name) - } - if l.Address != "192.168.1.1" { - t.Errorf("%v: Address not 192.168.1.1: %v", l.Name, l.Address) - } - if *l.Port != 80 { - t.Errorf("%v: Port not 80 or 8080: %v", l.Name, *l.Port) - } - if l.Sigalgs != "RSA+SHA256" { - t.Errorf("Sigalgs %v returned, expected on", l.Sigalgs) - } - if l.ClientSigalgs != "ECDSA+SHA256:RSA+SHA256" { - t.Errorf("ClientSigalgs %v returned, expected on", l.ClientSigalgs) - } - if l.CaVerifyFile != "ca.pem" { - t.Errorf("CaVerifyFile '%v' returned, expected 'ca.pem'", l.CaVerifyFile) - } - - if l.Nice != 789 { - t.Errorf("Nice '%v' returned, expected '789'", l.Nice) - } - - _, err = l.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } - - _, _, err = clientTest.GetBind("webserv", "frontend", "test_2", "") + _, _, err = clientTest.GetBind("webserv", configuration.FrontendParentName, "test_2", "") if err == nil { t.Error("Should throw error, non existent bind") } @@ -142,14 +131,14 @@ func TestCreateEditDeleteBind(t *testing.T) { }, } - err := clientTest.CreateBind("frontend", "test", l, "", version) + err := clientTest.CreateBind(configuration.FrontendParentName, "test", l, "", version) if err != nil { t.Error(err.Error()) } else { version++ } - v, bind, err := clientTest.GetBind("created", "frontend", "test", "") + v, bind, err := clientTest.GetBind("created", configuration.FrontendParentName, "test", "") if err != nil { t.Error(err.Error()) } @@ -164,7 +153,7 @@ func TestCreateEditDeleteBind(t *testing.T) { t.Errorf("Version %v returned, expected %v", v, version) } - err = clientTest.CreateBind("frontend", "test", l, "", version) + err = clientTest.CreateBind(configuration.FrontendParentName, "test", l, "", version) if err == nil { t.Error("Should throw error bind already exists") version++ @@ -190,14 +179,14 @@ func TestCreateEditDeleteBind(t *testing.T) { }, } - err = clientTest.EditBind("created", "frontend", "test", l, "", version) + err = clientTest.EditBind("created", configuration.FrontendParentName, "test", l, "", version) if err != nil { t.Error(err.Error()) } else { version++ } - v, bind, err = clientTest.GetBind("created", "frontend", "test", "") + v, bind, err = clientTest.GetBind("created", configuration.FrontendParentName, "test", "") if err != nil { t.Error(err.Error()) } @@ -213,7 +202,7 @@ func TestCreateEditDeleteBind(t *testing.T) { } // TestDeleteBind - err = clientTest.DeleteBind("created", "frontend", "test", "", version) + err = clientTest.DeleteBind("created", configuration.FrontendParentName, "test", "", version) if err != nil { t.Error(err.Error()) } else { @@ -224,12 +213,12 @@ func TestCreateEditDeleteBind(t *testing.T) { t.Error("Version not incremented") } - _, _, err = clientTest.GetBind("created", "frontend", "test", "") + _, _, err = clientTest.GetBind("created", configuration.FrontendParentName, "test", "") if err == nil { t.Error("DeleteBind failed, bind test still exists") } - err = clientTest.DeleteBind("created", "frontend", "test2", "", version) + err = clientTest.DeleteBind("created", configuration.FrontendParentName, "test2", "", version) if err == nil { t.Error("Should throw error, non existent bind") version++ diff --git a/configuration/cache_test.go b/test/cache_test.go similarity index 71% rename from configuration/cache_test.go rename to test/cache_test.go index d23712a8..1f931640 100644 --- a/configuration/cache_test.go +++ b/test/cache_test.go @@ -13,52 +13,67 @@ // limitations under the License. // -package configuration +package test import ( + _ "embed" "fmt" "reflect" "testing" + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" "github.com/haproxytech/client-native/v5/misc" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func cacheExpectation() map[string]models.Caches { + initStructuredExpected() + res := StructuredToCacheMap() + // Add individual entries + for _, vs := range res { + for _, v := range vs { + key := *v.Name + res[key] = models.Caches{v} + } + } + return res +} + func TestGetCaches(t *testing.T) { + m := make(map[string]models.Caches) v, caches, err := clientTest.GetCaches("") if err != nil { t.Error(err.Error()) } - - if len(caches) != 1 { - t.Errorf("%v caches returned, expected 1", len(caches)) - } - if v != version { t.Errorf("Version %v returned, expected %v", v, version) } + m[""] = caches + checkCaches(t, m) +} - if *caches[0].Name != "test" { - t.Errorf("Expected only test, %v found", caches[0].Name) - } - if caches[0].TotalMaxSize != 1024 { - t.Errorf("Expected only test, %v found", caches[0].Name) - } - if caches[0].MaxObjectSize != 8 { - t.Errorf("Expected only test, %v found", caches[0].Name) - } - if caches[0].MaxAge != 60 { - t.Errorf("Expected only test, %v found", caches[0].Name) - } - if *caches[0].ProcessVary != true { - t.Errorf("Expected only test, %v found", caches[0].Name) - } - if caches[0].MaxSecondaryEntries != 10 { - t.Errorf("Expected only test, %v found", caches[0].Name) +func checkCaches(t *testing.T, got map[string]models.Caches) { + exp := cacheExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } } } func TestGetCache(t *testing.T) { + m := make(map[string]models.Caches) + v, c, err := clientTest.GetCache("test", "") if err != nil { t.Error(err.Error()) @@ -67,26 +82,9 @@ func TestGetCache(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } + m["test"] = models.Caches{c} - if *c.Name != "test" { - t.Errorf("Expected only test, %v found", c.Name) - } - if c.TotalMaxSize != 1024 { - t.Errorf("Expected only test, %v found", c.Name) - } - if c.MaxObjectSize != 8 { - t.Errorf("Expected only test, %v found", c.Name) - } - if c.MaxAge != 60 { - t.Errorf("Expected only test, %v found", c.Name) - } - if *c.ProcessVary != true { - t.Errorf("Expected only test, %v found", c.Name) - } - if c.MaxSecondaryEntries != 10 { - t.Errorf("Expected only test, %v found", c.Name) - } - + checkCaches(t, m) _, err = c.MarshalBinary() if err != nil { t.Error(err.Error()) @@ -177,12 +175,12 @@ func TestCreateEditDeleteCache(t *testing.T) { err = clientTest.DeleteCache("created_cache", "", 999999) if err != nil { - if confErr, ok := err.(*ConfError); ok { - if !confErr.Is(ErrVersionMismatch) { - t.Error("Should throw ErrVersionMismatch error") + if confErr, ok := err.(*configuration.ConfError); ok { + if !confErr.Is(configuration.ErrVersionMismatch) { + t.Error("Should throw configuration.ErrVersionMismatch error") } } else { - t.Error("Should throw ErrVersionMismatch error") + t.Error("Should throw configuration.ErrVersionMismatch error") } } _, _, err = clientTest.GetCache("created_cache", "") diff --git a/configuration/capture_test.go b/test/capture_test.go similarity index 85% rename from configuration/capture_test.go rename to test/capture_test.go index d13e9675..698990f1 100644 --- a/configuration/capture_test.go +++ b/test/capture_test.go @@ -13,17 +13,34 @@ // limitations under the License. // -package configuration +package test import ( - "io/ioutil" + _ "embed" + "fmt" + "os" "testing" + "github.com/google/go-cmp/cmp" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func captureExpectation() map[string]models.Captures { + initStructuredExpected() + res := StructuredToCaptureMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%d", k, *v.Index) + res[key] = models.Captures{v} + } + } + return res +} + func generateDeclareCaptureConfig(config string) (string, error) { - f, err := ioutil.TempFile("/tmp", "capture") + f, err := os.CreateTemp("/tmp", "capture") if err != nil { return "", err } @@ -196,3 +213,21 @@ frontend test_delete }) } } + +// check based on configuration_test.go +func checkCaptures(t *testing.T, got map[string]models.Captures) { + exp := captureExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} diff --git a/configuration/configuration_test.go b/test/configuration_test.go similarity index 96% rename from configuration/configuration_test.go rename to test/configuration_test.go index c709c582..c47c03ba 100644 --- a/configuration/configuration_test.go +++ b/test/configuration_test.go @@ -13,14 +13,16 @@ // limitations under the License. // -package configuration +package test import ( "context" + _ "embed" "fmt" "os" "testing" + "github.com/haproxytech/client-native/v5/configuration" "github.com/haproxytech/client-native/v5/configuration/options" ) @@ -231,6 +233,20 @@ global ssl-provider default ssl-provider-path test setcap cap_net_raw,cap_net_bind_service + module-path /tmp/modules/path + module-load modsecurity.so + module-load test.so + waf-load /tmp/rules.conf + waf-body-limit 15000 + waf-json-levels 8 + modsecurity-deny-blocking-io + maxmind-update url CITY http://192.168.122.1/GeoIP2-City.mmdb url ISP http://192.168.122.1/GeoIP2-ISP.mmdb delay 24h checksum hash log + maxmind-load mlock_max 512000000 CITY /etc/hapee-2.5/GeoIP2-City.mmdb ISP /etc/hapee-2.5/GeoIP2-ISP.mmdb + maxmind-cache-size 200000 + maxmind-debug + fingerprint_ssl_bufsize 56 + log 127.0.0.1:10001 sample 1:4 local0 + log 127.0.0.1:10002 sample 2:4 local0 defaults test_defaults maxconn 2000 @@ -329,6 +345,7 @@ defaults http-send-name-header persist rdp-cookie source 192.168.1.200:80 usesrc 192.168.1.201:443 + tcp-check send GET\ /\ HTTP/2.0\r\n frontend test mode http @@ -885,12 +902,26 @@ backend test_2 from test_defaults_2 email-alert level warning email-alert myhostname prod01 email-alert mailers localmailer1 + +userlist first + group G1 users tiger,scott + group G2 users scott + user tiger password $6$k6y3o.eP$JlKBx9za9667qe4xHSwRv6J.C0/D7cV91 + user scott insecure-password elgato + +userlist second + group one + group two + group three + user neo password $6$k6y3o.eP$JlKBxxHSwRv6J.C0/D7cV91 groups one + user thomas insecure-password white-rabbit groups one,two + user anderson insecure-password hello groups two ` const testPath = "/tmp/haproxy-test.cfg" //nolint:gochecknoglobals var ( - clientTest Configuration + clientTest configuration.Configuration version int64 = 1 ) @@ -961,8 +992,8 @@ func deleteTestFile(path string) error { return nil } -func prepareClient(path string) (c Configuration, err error) { - c, err = New(context.Background(), +func prepareClient(path string) (c configuration.Configuration, err error) { + c, err = configuration.New(context.Background(), options.ConfigurationFile(path), options.HAProxyBin("echo"), options.UseModelsValidation, diff --git a/test/convert.go b/test/convert.go new file mode 100644 index 00000000..af647e39 --- /dev/null +++ b/test/convert.go @@ -0,0 +1,422 @@ +// 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. +// + +package test + +import ( + _ "embed" + "encoding/json" + "fmt" + "sync" + + "github.com/haproxytech/client-native/v5/configuration" + "github.com/haproxytech/client-native/v5/models" +) + +//go:embed expected/structured.json +var expectedStructuredJSON []byte +var expectedStructured map[string]interface{} + +var onceStrutructured sync.Once + +func initStructuredExpected() { + onceStrutructured.Do(func() { + err := json.Unmarshal(expectedStructuredJSON, &expectedStructured) + if err != nil { + panic(err) + } + }) +} + +func expectedResources[T any](res T, elementKey string) error { + v := expectedStructured[elementKey] + j, err := json.Marshal(v) + if err != nil { + return err + } + err = json.Unmarshal(j, &res) + if err != nil { + return err + } + return nil +} + +func expectedChildResources[P, T any](res map[string]T, parentKey, parentNameKey, elementKey string) error { + v := expectedStructured[parentKey] + vlist, ok := v.([]interface{}) + if ok { + for _, p := range vlist { + pj, err := json.Marshal(p) + if err != nil { + return err + } + var parent P + err = json.Unmarshal(pj, &parent) + if err != nil { + return err + } + + pmap := p.(map[string]interface{}) + pName, ok := pmap[parentNameKey] + if !ok { + continue + } + var pkey string + switch parentKey { + case "frontends": + pkey = configuration.FrontendParentName + case "backends": + pkey = configuration.BackendParentName + case "fcgi_apps": + pkey = configuration.FCGIAppParentName + case "log_forwards": + pkey = configuration.LogForwardParentName + case "userlists": + pkey = "userlist" + case "mailers_sections": + pkey = "mailers_sections" + case "resolvers": + pkey = configuration.ResolverParentName + case "peers": + pkey = configuration.PeersParentName + case "rings": + pkey = configuration.RingParentName + } + key := fmt.Sprintf("%s/%s", pkey, pName) + + ellist, ok := pmap[elementKey] + if !ok { + res[key] = *new(T) + continue + } + elistj, err := json.Marshal(ellist) + if err != nil { + return err + } + var resources T + err = json.Unmarshal(elistj, &resources) + if err != nil { + return err + } + res[key] = resources + } + } else { + pmap := v.(map[string]interface{}) + key := parentKey + + ellist, ok := pmap[elementKey] + if !ok { + res[key] = *new(T) + } + elistj, err := json.Marshal(ellist) + if err != nil { + return err + } + var resources T + err = json.Unmarshal(elistj, &resources) + if err != nil { + return err + } + res[key] = resources + } + + return nil +} + +func StructuredToBackendMap() map[string]models.Backends { + var l models.Backends + _ = expectedResources(&l, "backends") + res := make(map[string]models.Backends) + keyRoot := "" + res[keyRoot] = l + return res +} + +func StructuredToFrontendMap() map[string]models.Frontends { + var l models.Frontends + _ = expectedResources(&l, "frontends") + res := make(map[string]models.Frontends) + keyRoot := "" + res[keyRoot] = l + return res +} + +func StructuredToCacheMap() map[string]models.Caches { + var l models.Caches + _ = expectedResources(&l, "caches") + res := make(map[string]models.Caches) + keyRoot := "" + res[keyRoot] = l + return res +} + +func StructuredToACLMap() map[string]models.Acls { + res := make(map[string]models.Acls) + _ = expectedChildResources[models.Frontend](res, "frontends", "name", "acls") + _ = expectedChildResources[models.Backend](res, "backends", "name", "acls") + _ = expectedChildResources[models.FCGIApp](res, "fcgi_apps", "name", "acls") + return res +} + +func StructuredToBackendSwitchingRuleMap() map[string]models.BackendSwitchingRules { + res := make(map[string]models.BackendSwitchingRules) + _ = expectedChildResources[models.Frontend](res, "frontends", "name", "backend_switching_rules") + return res +} + +func StructuredToBindMap() map[string]models.Binds { + res := make(map[string]models.Binds) + _ = expectedChildResources[models.Frontend](res, "frontends", "name", "binds") + _ = expectedChildResources[models.LogForward](res, "log_forwards", "name", "binds") + _ = expectedChildResources[models.PeerSection](res, "peers", "name", "binds") + return res +} + +func StructuredToCaptureMap() map[string]models.Captures { + res := make(map[string]models.Captures) + _ = expectedChildResources[models.Frontend](res, "frontends", "name", "captures") + return res +} + +func StructuredToDefaultsMap() models.Defaults { + var l models.Defaults + _ = expectedResources(&l, "defaults") + return l +} + +func StructuredToGlobalMap() models.Global { + var l models.Global + _ = expectedResources(&l, "global") + return l +} + +func StructuredToNamedDefaultsMap() map[string][]*models.Defaults { + var l []*models.Defaults + res := make(map[string][]*models.Defaults) + _ = expectedResources(&l, "named_defaults") + for _, v := range l { + res[v.Name] = append(res[v.Name], v) + } + return res +} + +func StructuredToDgramBindMap() map[string]models.DgramBinds { + res := make(map[string]models.DgramBinds) + _ = expectedChildResources[models.LogForward](res, "log_forwards", "name", "dgram_binds") + return res +} + +func StructuredToFCGIAppMap() map[string]models.FCGIApps { + res := make(map[string]models.FCGIApps) + var l models.FCGIApps + _ = expectedResources(&l, "fcgi_apps") + keyRoot := "" + res[keyRoot] = l + return res +} + +func StructuredToFilterMap() map[string]models.Filters { + res := make(map[string]models.Filters) + _ = expectedChildResources[models.Frontend](res, "frontends", "name", "filters") + _ = expectedChildResources[models.Backend](res, "backends", "name", "filters") + return res +} + +func StructuredToGroupMap() map[string]models.Groups { + res := make(map[string]models.Groups) + _ = expectedChildResources[models.Userlist](res, "userlists", "name", "groups") + return res +} + +func StructuredToHTTPAfterResponseRuleMap() map[string]models.HTTPAfterResponseRules { + res := make(map[string]models.HTTPAfterResponseRules) + _ = expectedChildResources[models.Frontend](res, "frontends", "name", "http_after_response_rules") + _ = expectedChildResources[models.Backend](res, "backends", "name", "http_after_response_rules") + return res +} + +func StructuredToHTTPCheckMap() map[string]models.HTTPChecks { + res := make(map[string]models.HTTPChecks) + _ = expectedChildResources[models.Backend](res, "backends", "name", "http_checks") + _ = expectedChildResources[models.Defaults](res, "defaults", "name", "http_checks") + return res +} + +func StructuredToHTTPErrorRuleMap() map[string]models.HTTPErrorRules { + res := make(map[string]models.HTTPErrorRules) + _ = expectedChildResources[models.Backend](res, "backends", "name", "http_error_rules") + _ = expectedChildResources[models.Frontend](res, "frontends", "name", "http_error_rules") + _ = expectedChildResources[models.Defaults](res, "defaults", "name", "http_error_rules") + return res +} + +func StructuredToHTTPErrorSectionMap() map[string]models.HTTPErrorsSections { + res := make(map[string]models.HTTPErrorsSections) + var l models.HTTPErrorsSections + _ = expectedResources(&l, "http_errors") + keyRoot := "" + res[keyRoot] = l + return res +} + +func StructuredToHTTPRequestRuleMap() map[string]models.HTTPRequestRules { + res := make(map[string]models.HTTPRequestRules) + _ = expectedChildResources[models.Backend](res, "backends", "name", "http_request_rules") + _ = expectedChildResources[models.Frontend](res, "frontends", "name", "http_request_rules") + return res +} + +func StructuredToHTTPResponseRuleMap() map[string]models.HTTPResponseRules { + res := make(map[string]models.HTTPResponseRules) + _ = expectedChildResources[models.Backend](res, "backends", "name", "http_response_rules") + _ = expectedChildResources[models.Frontend](res, "frontends", "name", "http_response_rules") + return res +} + +func StructuredToLogForwardMap() map[string]models.LogForwards { + res := make(map[string]models.LogForwards) + var l models.LogForwards + _ = expectedResources(&l, "log_forwards") + keyRoot := "" + res[keyRoot] = l + return res +} + +func StructuredToLogTargetMap() map[string]models.LogTargets { + res := make(map[string]models.LogTargets) + _ = expectedChildResources[models.Backend](res, "backends", "name", "log_targets") + _ = expectedChildResources[models.Frontend](res, "frontends", "name", "log_targets") + _ = expectedChildResources[models.LogForward](res, "log_forwards", "name", "log_targets") + _ = expectedChildResources[models.PeerSection](res, "peers", "name", "log_targets") + _ = expectedChildResources[models.Defaults](res, "defaults", "name", "log_targets") + _ = expectedChildResources[models.Global](res, "global", "name", "log_targets") + return res +} + +func StructuredToMailerEntryMap() map[string]models.MailerEntries { + res := make(map[string]models.MailerEntries) + _ = expectedChildResources[models.MailersSection](res, "mailers_sections", "name", "mailer_entries") + return res +} + +func StructuredToMailersSectionMap() map[string]models.MailersSections { + res := make(map[string]models.MailersSections) + var l models.MailersSections + _ = expectedResources(&l, "mailers_sections") + keyRoot := "" + res[keyRoot] = l + return res +} + +func StructuredToNameserverMap() map[string]models.Nameservers { + res := make(map[string]models.Nameservers) + _ = expectedChildResources[models.Resolver](res, "resolvers", "name", "nameservers") + return res +} + +func StructuredToPeerEntryMap() map[string]models.PeerEntries { + res := make(map[string]models.PeerEntries) + _ = expectedChildResources[models.PeerSection](res, "peers", "name", "peer_entries") + return res +} + +func StructuredToPeerSectionMap() map[string]models.PeerSections { + res := make(map[string]models.PeerSections) + var l models.PeerSections + _ = expectedResources(&l, "peers") + keyRoot := "" + res[keyRoot] = l + return res +} + +func StructuredToProgramMap() map[string]models.Programs { + res := make(map[string]models.Programs) + var l models.Programs + _ = expectedResources(&l, "programs") + keyRoot := "" + res[keyRoot] = l + return res +} + +func StructuredToResolverMap() map[string]models.Resolvers { + res := make(map[string]models.Resolvers) + var l models.Resolvers + _ = expectedResources(&l, "resolvers") + keyRoot := "" + res[keyRoot] = l + return res +} + +func StructuredToRingMap() map[string]models.Rings { + res := make(map[string]models.Rings) + var l models.Rings + _ = expectedResources(&l, "rings") + keyRoot := "" + res[keyRoot] = l + return res +} + +func StructuredToServerSwitchingRuleMap() map[string]models.ServerSwitchingRules { + res := make(map[string]models.ServerSwitchingRules) + _ = expectedChildResources[models.Backend](res, "backends", "name", "server_switching_rules") + return res +} + +func StructuredToServerTemplateMap() map[string]models.ServerTemplates { + res := make(map[string]models.ServerTemplates) + _ = expectedChildResources[models.Backend](res, "backends", "name", "server_templates") + + return res +} + +func StructuredToServerMap() map[string]models.Servers { //nolint:dupl + res := make(map[string]models.Servers) + _ = expectedChildResources[models.Backend](res, "backends", "name", "servers") + _ = expectedChildResources[models.Ring](res, "rings", "name", "servers") + _ = expectedChildResources[models.PeerSection](res, "peers", "name", "servers") + return res +} + +func StructuredToStickRuleMap() map[string]models.StickRules { + res := make(map[string]models.StickRules) + _ = expectedChildResources[models.Backend](res, "backends", "name", "stick_rules") + return res +} + +func StructuredToTCPRequestRuleMap() map[string]models.TCPRequestRules { + res := make(map[string]models.TCPRequestRules) + _ = expectedChildResources[models.Backend](res, "backends", "name", "tcp_request_rules") + _ = expectedChildResources[models.Frontend](res, "frontends", "name", "tcp_request_rules") + return res +} + +func StructuredToTCPResponseRuleMap() map[string]models.TCPResponseRules { + res := make(map[string]models.TCPResponseRules) + _ = expectedChildResources[models.Backend](res, "backends", "name", "tcp_response_rules") + return res +} + +func StructuredToTCPCheckMap() map[string]models.TCPChecks { + res := make(map[string]models.TCPChecks) + _ = expectedChildResources[models.Backend](res, "backends", "name", "tcp_checks") + _ = expectedChildResources[models.Defaults](res, "defaults", "name", "tcp_checks") + return res +} + +func StructuredToUserMap() map[string]models.Users { + res := make(map[string]models.Users) + _ = expectedChildResources[models.Defaults](res, "userlists", "name", "users") + return res +} diff --git a/test/defaults_test.go b/test/defaults_test.go new file mode 100644 index 00000000..438a473c --- /dev/null +++ b/test/defaults_test.go @@ -0,0 +1,363 @@ +package test + +import ( + _ "embed" + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/misc" + "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" +) + +func defaultsExpectation() models.Defaults { + initStructuredExpected() + res := StructuredToDefaultsMap() + return res +} + +func namedDefaultsExpectation() map[string][]*models.Defaults { + initStructuredExpected() + res := StructuredToNamedDefaultsMap() + return res +} + +func TestGetDefaults(t *testing.T) { //nolint:gocognit,gocyclo + v, d, err := clientTest.GetDefaultsConfiguration("") + if err != nil { + t.Error(err.Error()) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + checkDefaults(t, d) +} + +func checkDefaults(t *testing.T, g *models.Defaults) { + want := defaultsExpectation() + require.True(t, g.Equal(want), "%s - diff %v", g.Name, cmp.Diff(*g, want)) +} + +func TestPushDefaults(t *testing.T) { + tOut := int64(6000) + tOutS := int64(200) + balanceAlgorithm := "leastconn" + cpkaCnt := int64(10) + cpkaTimeout := int64(10000) + statsRealm := "Haproxy Stats" + d := &models.Defaults{ + Clitcpka: "disabled", + BindProcess: "1-4", + DefaultBackend: "test2", + ErrorFiles: []*models.Errorfile{ + { + Code: 400, + File: "/test/400.html", + }, + { + Code: 403, + File: "/test/403.html", + }, + { + Code: 429, + File: "/test/429.html", + }, + { + Code: 500, + File: "/test/500.html", + }, + }, + CheckTimeout: &tOutS, + ConnectTimeout: &tOut, + ServerTimeout: &tOutS, + QueueTimeout: &tOutS, + Mode: "tcp", + MonitorURI: "/healthz", + HTTPUseHtx: "enabled", + Balance: &models.Balance{ + Algorithm: &balanceAlgorithm, + }, + ExternalCheck: "", + ExternalCheckPath: "/bin", + ExternalCheckCommand: "/bin/false", + Logasap: "disabled", + Allbackups: "enabled", + HTTPCheck: &models.HTTPCheck{ + Index: misc.Int64P(0), + Type: "send-state", + }, + AcceptInvalidHTTPRequest: "disabled", + AcceptInvalidHTTPResponse: "disabled", + DisableH2Upgrade: "disabled", + LogHealthChecks: "disabled", + ClitcpkaCnt: &cpkaCnt, + ClitcpkaIdle: &cpkaTimeout, + ClitcpkaIntvl: &cpkaTimeout, + SrvtcpkaCnt: &cpkaCnt, + SrvtcpkaIdle: &cpkaTimeout, + SrvtcpkaIntvl: &cpkaTimeout, + Checkcache: "enabled", + HTTPIgnoreProbes: "enabled", + HTTPUseProxyHeader: "enabled", + Httpslog: "enabled", + IndependentStreams: "enabled", + Nolinger: "enabled", + Originalto: &models.Originalto{ + Enabled: misc.StringP("enabled"), + Except: "127.0.0.1", + Header: "X-Client-Dst", + }, + Persist: "disabled", + PreferLastServer: "disabled", + SocketStats: "disabled", + TCPSmartAccept: "disabled", + TCPSmartConnect: "disabled", + Transparent: "disabled", + DontlogNormal: "disabled", + HTTPNoDelay: "disabled", + SpliceAuto: "disabled", + SpliceRequest: "disabled", + SpliceResponse: "disabled", + IdleCloseOnResponse: "disabled", + StatsOptions: &models.StatsOptions{ + StatsShowModules: true, + StatsRealm: true, + StatsRealmRealm: &statsRealm, + StatsAuths: []*models.StatsAuth{ + {User: misc.StringP("user1"), Passwd: misc.StringP("pwd1")}, + {User: misc.StringP("user2"), Passwd: misc.StringP("pwd2")}, + }, + }, + EmailAlert: &models.EmailAlert{ + From: misc.StringP("srv01@example.com"), + To: misc.StringP("support@example.com"), + Level: "err", + Myhostname: "srv01", + Mailers: misc.StringP("localmailer1"), + }, + HTTPSendNameHeader: misc.StringP(""), + Source: &models.Source{ + Address: misc.StringP("127.0.0.1"), + Interface: "lo", + }, + } + + err := clientTest.PushDefaultsConfiguration(d, "", version) + + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + ver, defaults, err := clientTest.GetDefaultsConfiguration("") + if err != nil { + t.Error(err.Error()) + } + + var givenJSON []byte + givenJSON, err = d.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + var ondiskJSON []byte + ondiskJSON, err = defaults.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + if string(givenJSON) != string(ondiskJSON) { + fmt.Printf("Created defaults: %v\n", string(ondiskJSON)) + fmt.Printf("Given defaults: %v\n", string(givenJSON)) + t.Error("Created defaults not equal to given defaults") + } + + if ver != version { + t.Error("Version not incremented!") + } + + err = clientTest.PushDefaultsConfiguration(d, "", 1055) + + if err == nil { + t.Error("Should have returned version conflict.") + } +} + +func TestGetDefaultsSections(t *testing.T) { + m := make(map[string][]*models.Defaults) + v, defaults, err := clientTest.GetDefaultsSections("") + if err != nil { + t.Error(err.Error()) + } + + for _, v := range defaults { + d := *v + m[d.Name] = []*models.Defaults{&d} + } + + if len(defaults) != 3 { + t.Errorf("%v defaults returned, expected 2", len(defaults)) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + checkNamedDefaults(t, m) +} + +func checkNamedDefaults(t *testing.T, got map[string][]*models.Defaults) { + exp := namedDefaultsExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + // This is due to the fact the unnamed defaults is modified here in TestEditCreateDeleteDefaultsSection + // So value is not equal to what was in configuration_test.go is the test runs after the edit one. + if g.Name != "unnamed_defaults_1" { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } + } +} + +func TestGetDefaultsSection(t *testing.T) { + m := make(map[string][]*models.Defaults) + + v, d, err := clientTest.GetDefaultsSection("test_defaults", "") + if err != nil { + t.Error(err.Error()) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + m["test_defaults"] = append(m[""], d) + + checkNamedDefaults(t, m) +} + +func TestEditCreateDeleteDefaultsSection(t *testing.T) { + // test creating a new section + d := &models.Defaults{ + Name: "created", + Clitcpka: "disabled", + BindProcess: "1-4", + DefaultBackend: "test2", + } + err := clientTest.CreateDefaultsSection(d, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, defaults, err := clientTest.GetDefaultsSection("created", "") + if err != nil { + t.Error(err.Error()) + } + + var givenJSON []byte + givenJSON, err = d.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + var ondiskJSON []byte + ondiskJSON, err = defaults.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + if string(givenJSON) != string(ondiskJSON) { + fmt.Printf("Created defaults: %v\n", string(ondiskJSON)) + fmt.Printf("Given defaults: %v\n", string(givenJSON)) + t.Error("Created defaults not equal to given defaults") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + err = clientTest.CreateDefaultsSection(d, "", version) + if err == nil { + t.Error("Should throw error defaults section already exists") + version++ + } + + d = &models.Defaults{ + From: "unnamed_defaults_1", + Name: "created", + Clitcpka: "enabled", + BindProcess: "1-4", + DefaultBackend: "test2", + } + err = clientTest.EditDefaultsSection("created", d, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, defaults, err = clientTest.GetDefaultsSection("created", "") + if err != nil { + t.Error(err.Error()) + } + + givenJSON, err = d.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + ondiskJSON, err = defaults.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + if string(givenJSON) != string(ondiskJSON) { + fmt.Printf("Created defaults: %v\n", string(ondiskJSON)) + fmt.Printf("Given defaults: %v\n", string(givenJSON)) + t.Error("Created defaults not equal to given defaults") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + err = clientTest.EditDefaultsSection("i_dont_exist", d, "", version) + if err == nil { + t.Error("editing non-existing defaults section succeeded") + } + + // TestDeleteDefaultsSection + err = clientTest.DeleteDefaultsSection("created", "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + if v, _ := clientTest.GetVersion(""); v != version { + t.Error("Version not incremented") + } + + _, _, err = clientTest.GetDefaultsSection("created", "") + if err == nil { + t.Error("DeleteDefaultsSection failed, defaults section created still exists") + } + + err = clientTest.DeleteDefaultsSection("i_dont_exist", "", version) + if err == nil { + t.Error("Should throw error, non existent defaults section") + version++ + } +} diff --git a/configuration/dgram_bind_test.go b/test/dgram_bind_test.go similarity index 77% rename from configuration/dgram_bind_test.go rename to test/dgram_bind_test.go index f777bc98..fcfae269 100644 --- a/configuration/dgram_bind_test.go +++ b/test/dgram_bind_test.go @@ -13,17 +13,35 @@ // limitations under the License. // -package configuration +package test import ( + _ "embed" "fmt" "reflect" "testing" + "github.com/google/go-cmp/cmp" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func dgramBindExpectation() map[string]models.DgramBinds { + initStructuredExpected() + res := StructuredToDgramBindMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%s", k, v.Name) + res[key] = models.DgramBinds{v} + } + } + return res +} + func TestGetDgramBinds(t *testing.T) { + m := make(map[string]models.DgramBinds) + v, dBinds, err := clientTest.GetDgramBinds("sylog-loadb", "") if err != nil { t.Error(err.Error()) @@ -32,22 +50,14 @@ func TestGetDgramBinds(t *testing.T) { if len(dBinds) != 1 { t.Errorf("%v dgram-binds returned, expected 1", len(dBinds)) } + for _, e := range dBinds { + m[fmt.Sprintf("log_forward/sylog-loadb/%s", e.Name)] = models.DgramBinds{e} + } if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - - for _, l := range dBinds { - if l.Name != "webserv" { - t.Errorf("Expected webserv dgram-binds, %v found", l.Name) - } - if l.Address != "127.0.0.1" { - t.Errorf("%v: Address not 127.0.0.1: %v", l.Name, l.Address) - } - if *l.Port != 1514 { - t.Errorf("%v: Port not 1514 : %v", l.Name, *l.Port) - } - } + checkDgramBinds(t, m) // _, dBinds, err = clientTest.GetDgramBinds("test_2", "") // if err != nil { @@ -59,6 +69,7 @@ func TestGetDgramBinds(t *testing.T) { } func TestGetDgramBind(t *testing.T) { + m := make(map[string]models.DgramBinds) v, l, err := clientTest.GetDgramBind("webserv", "sylog-loadb", "") if err != nil { t.Error(err.Error()) @@ -67,21 +78,9 @@ func TestGetDgramBind(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } + m["log_forward/sylog-loadb/webserv"] = models.DgramBinds{l} - if l.Name != "webserv" { - t.Errorf("Expected only webserv dgram-bind, %v found", l.Name) - } - if l.Address != "127.0.0.1" { - t.Errorf("%v: Address not 127.0.0.1: %v", l.Name, l.Address) - } - if *l.Port != 1514 { - t.Errorf("%v: Port not 1514: %v", l.Name, *l.Port) - } - - _, err = l.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } + checkDgramBinds(t, m) _, _, err = clientTest.GetDgramBind("webserv", "test_2", "") if err == nil { @@ -89,6 +88,23 @@ func TestGetDgramBind(t *testing.T) { } } +func checkDgramBinds(t *testing.T, got map[string]models.DgramBinds) { + exp := dgramBindExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + func TestCreateEditDeleteDgramBind(t *testing.T) { // TestCreateBind port := int64(4300) diff --git a/test/expected/structured.json b/test/expected/structured.json new file mode 100644 index 00000000..cdfac823 --- /dev/null +++ b/test/expected/structured.json @@ -0,0 +1,3364 @@ +{ + "defaults": { + "error_files": [ + { + "code": 403, + "file": "/test/403.html" + }, + { + "code": 500, + "file": "/test/500.html" + }, + { + "code": 429, + "file": "/test/429.html" + } + ], + "accept_invalid_http_request": "enabled", + "accept_invalid_http_response": "enabled", + "backlog": 1024, + "balance": { + "algorithm": "roundrobin" + }, + "bind_process": "1-4", + "check_timeout": 2000, + "checkcache": "disabled", + "client_fin_timeout": 1000, + "client_timeout": 4000, + "clitcpka": "enabled", + "clitcpka_cnt": 10, + "clitcpka_idle": 10000, + "clitcpka_intvl": 10000, + "compression": { + "offload": true + }, + "connect_timeout": 5000, + "default_backend": "test", + "default_server": { + "fall": 2000, + "health_check_port": 8888, + "inter": 5000, + "rise": 4000 + }, + "disable_h2_upgrade": "enabled", + "dontlog_normal": "enabled", + "dontlognull": "enabled", + "email_alert": { + "from": "srv01@example.com", + "level": "err", + "mailers": "localmailer1", + "myhostname": "srv01", + "to": "support@example.com" + }, + "external_check": "enabled", + "external_check_command": "/bin/true", + "external_check_path": "/bin", + "forwardfor": { + "enabled": "enabled", + "header": "X-Forwarded-For" + }, + "fullconn": 10, + "h1_case_adjust_bogus_client": "enabled", + "h1_case_adjust_bogus_server": "enabled", + "http-check": { + "index": 0, + "type": "send-state" + }, + "http-use-htx": "enabled", + "http_connection_mode": "httpclose", + "http_ignore_probes": "disabled", + "http_keep_alive_timeout": 3000, + "http_no_delay": "enabled", + "http_request_timeout": 2000, + "http_restrict_req_hdr_names": "reject", + "http_send_name_header": "", + "http_use_proxy_header": "disabled", + "httplog": true, + "httpslog": "disabled", + "idle_close_on_response": "enabled", + "independent_streams": "disabled", + "load_server_state_from_file": "global", + "log_health_checks": "enabled", + "max_keep_alive_queue": 100, + "maxconn": 2000, + "mode": "http", + "monitor_uri": "/monitor", + "nolinger": "disabled", + "originalto": { + "enabled": "enabled" + }, + "persist": "enabled", + "persist_rule": { + "type": "rdp-cookie" + }, + "prefer_last_server": "enabled", + "queue_timeout": 900, + "retry_on": "503 504", + "server_fin_timeout": 1000, + "server_timeout": 2000, + "socket_stats": "enabled", + "source": { + "address": "192.168.1.200", + "address_second": "192.168.1.201", + "port": 80, + "port_second": 443, + "usesrc": "address" + }, + "splice_auto": "enabled", + "splice_request": "enabled", + "splice_response": "enabled", + "srvtcpka": "enabled", + "srvtcpka_cnt": 10, + "srvtcpka_idle": 10000, + "srvtcpka_intvl": 10000, + "stats_options": { + "stats_auths": [ + { + "passwd": "AdMiN123", + "user": "admin" + }, + { + "passwd": "AdMiN1234", + "user": "admin2" + } + ], + "stats_realm": true, + "stats_realm_realm": "HAProxy\\\\ Statistics", + "stats_show_modules": true, + "stats_show_node_name": null + }, + "tarpit_timeout": 2000, + "tcp_smart_accept": "enabled", + "tcp_smart_connect": "enabled", + "tcpka": "enabled", + "transparent": "enabled", + "http_checks": [ + { + "index": 0, + "type": "send-state" + }, + { + "index": 1, + "type": "disable-on-404" + } + ], + "http_error_rules": [ + { + "index": 0, + "return_content": "/test/503", + "return_content_format": "file", + "return_content_type": "\"application/json\"", + "status": 503, + "type": "status" + }, + { + "index": 1, + "return_content": "/test/429", + "return_content_format": "file", + "return_content_type": "application/json", + "status": 429, + "type": "status" + } + ], + "tcp_check_rules": [ + { + "action": "send", + "data": "GET\\ /\\ HTTP/2.0\\r\\n", + "index": 0 + } + ] + }, + "global": { + "h1_case_adjust": [ + { + "from": "host", + "to": "Host" + }, + { + "from": "content-type", + "to": "Content-Type" + } + ], + "module-loads": [ + { + "value": "modsecurity.so" + }, + { + "value": "test.so" + } + ], + "presetenv": [ + { + "name": "first", + "value": "order" + } + ], + "runtime_apis": [ + { + "level": "admin", + "mode": "0660", + "address": "/var/run/haproxy.sock" + } + ], + "setenv": [ + { + "name": "third", + "value": "sister" + } + ], + "set_var_fmt": [ + { + "format": "\"%pid|%t\"", + "name": "proc.bootid" + }, + { + "format": "\"primary\"", + "name": "proc.current_state" + } + ], + "set_var": [ + { + "expr": "str(primary)", + "name": "proc.current_state" + }, + { + "expr": "int(100)", + "name": "proc.prio" + }, + { + "expr": "int(200),sub(proc.prio)", + "name": "proc.threshold" + } + ], + "ssl_engines": [ + { + "algorithms": "", + "name": "first" + }, + { + "algorithms": "RSA,DSA,DH,EC,RAND", + "name": "second" + }, + { + "algorithms": "CIPHERS,DIGESTS,PKEY,PKEY_CRYPTO,PKEY_ASN1", + "name": "third" + } + ], + "thread_group_lines": [ + { + "group": "first", + "num_or_range": "1-16" + } + ], + "anonkey": 25, + "busy_polling": true, + "ca_base": "/etc/ssl/certs", + "chroot": "/var/www", + "close_spread_time": 1000, + "cluster_secret": "my_secret", + "crt_base": "/etc/ssl/private", + "daemon": "enabled", + "default_path": { + "path": "/some/path", + "type": "origin" + }, + "description": "description", + "device_atlas_options": { + "json_file": "atlas.json", + "log_level": "1", + "properties_cookie": "chocolate", + "separator": "-" + }, + "expose_experimental_directives": true, + "external_check": true, + "fifty_one_degrees_options": { + "cache_size": 51, + "data_file": "51.file", + "property_name_list": "first second third fourth fifth", + "property_separator": "/" + }, + "fingerprint_ssl_bufsize": 56, + "gid": 1, + "grace": 10000, + "group": "anderson", + "h1_case_adjust_file": "/etc/headers.adjust", + "h2_workaround_bogus_websocket_clients": true, + "hard_stop_after": 2000, + "httpclient_resolvers_disabled": "enabled", + "httpclient_resolvers_id": "resolver_1", + "httpclient_resolvers_prefer": "ipv4", + "httpclient_retries": 3, + "httpclient_ssl_ca_file": "my_test_file.ca", + "httpclient_ssl_verify": "none", + "httpclient_timeout_connect": 2000, + "insecure_fork_wanted": true, + "insecure_setuid_wanted": true, + "issuers_chain_path": "issuers-chain-path", + "limited_quic": true, + "localpeer": "test", + "lua_load_per_thread": "file.ext", + "lua_loads": [ + { + "file": "/etc/foo.lua" + }, + { + "file": "/etc/bar.lua" + } + ], + "lua_prepend_path": [ + { + "path": "/usr/share/haproxy-lua/?/init.lua" + }, + { + "path": "/usr/share/haproxy-lua/?.lua", + "type": "cpath" + } + ], + "max_spread_checks": 1, + "maxcompcpuusage": 4, + "maxcomprate": 3, + "maxconn": 2000, + "maxconnrate": 2, + "maxmind_cache_size": 200000, + "maxmind_debug": true, + "maxmind_load": { + "maxmind_dbs": [ + { + "key": "CITY", + "path": "/etc/hapee-2.5/GeoIP2-City.mmdb" + }, + { + "key": "ISP", + "path": "/etc/hapee-2.5/GeoIP2-ISP.mmdb" + } + ], + "mlock_max": 512000000 + }, + "maxmind_update": { + "maxmind_urls": [ + { + "key": "CITY", + "url": "http://192.168.122.1/GeoIP2-City.mmdb" + }, + { + "key": "ISP", + "url": "http://192.168.122.1/GeoIP2-ISP.mmdb" + } + ], + "checksum": true, + "delay": 86400000, + "hash": true, + "log": true + }, + "maxpipes": 5, + "maxsessrate": 6, + "maxsslconn": 7, + "maxsslrate": 8, + "maxzlibmem": 9, + "modsecurity-deny-blocking-io": true, + "module-path": "/tmp/modules/path", + "mworker_max_reloads": 5, + "nbproc": 4, + "nbthread": 128, + "no-quic": true, + "node": "node", + "noepoll": true, + "noevports": true, + "nogetaddrinfo": true, + "nokqueue": true, + "nopoll": true, + "noreuseport": true, + "nosplice": true, + "numa_cpu_mapping": "enabled", + "pidfile": "pidfile.text", + "pp2_never_send_local": true, + "prealloc-fd": true, + "profiling_tasks": "enabled", + "quiet": true, + "resetenv": "first second", + "server_state_base": "/path", + "server_state_file": "serverstatefile", + "set_dumpable": true, + "setcap": "cap_net_raw,cap_net_bind_service", + "spread_checks": 10, + "ssl_default_bind_ciphers": "ECDH+AESGCM:ECDH+CHACHA20", + "ssl_default_bind_ciphersuites": "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384", + "ssl_default_bind_client_sigalgs": "ECDSA+SHA256:RSA+SHA256", + "ssl_default_bind_curves": "X25519:P-256", + "ssl_default_bind_sigalgs": "RSA+SHA256", + "ssl_default_server_ciphers": "ECDH+AESGCM:ECDH+CHACHA20:ECDH+AES256:ECDH+AES128:!aNULL:!SHA1:!AESCCM", + "ssl_default_server_ciphersuites": "TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256", + "ssl_default_server_client_sigalgs": "ECDSA+SHA256:RSA+SHA256", + "ssl_default_server_curves": "brainpoolP384r1,brainpoolP512r1", + "ssl_default_server_options": "ssl-min-ver TLSv1.1 no-tls-tickets", + "ssl_default_server_sigalgs": "RSA+SHA256", + "ssl_dh_param_file": "ssl-dh-param-file.txt", + "ssl_load_extra_files": "bundle", + "ssl_mode_async": "enabled", + "ssl_propquery": "provider", + "ssl_provider": "default", + "ssl_provider_path": "test", + "ssl_server_verify": "required", + "ssl_skip_self_issued_ca": true, + "stats_maxconn": 20, + "strict_limits": true, + "thread_groups": 1, + "tune_options": { + "buffers_limit": 11, + "buffers_reserve": 12, + "bufsize": 13, + "comp_maxlevel": 14, + "disable_zero_copy_forwarding": true, + "events_max_events_at_once": 10, + "fail_alloc": true, + "fd_edge_triggered": "enabled", + "h1_zero_copy_fwd_recv": "enabled", + "h1_zero_copy_fwd_send": "enabled", + "h2_be_initial_window_size": 201, + "h2_be_max_concurrent_streams": 202, + "h2_fe_initial_window_size": 203, + "h2_fe_max_concurrent_streams": 204, + "h2_header_table_size": 15, + "h2_initial_window_size": 16, + "h2_max_concurrent_streams": 17, + "h2_max_frame_size": 18, + "h2_zero_copy_fwd_send": "enabled", + "http_cookielen": 19, + "http_logurilen": 20, + "http_maxhdr": 21, + "idle_pool_shared": "enabled", + "idletimer": 22, + "listener_default_shards": "by-process", + "listener_multi_queue": "enabled", + "lua_burst_timeout": 205, + "lua_forced_yield": 23, + "lua_log_loggers": "enabled", + "lua_log_stderr": "auto", + "lua_maxmem": true, + "lua_service_timeout": 27, + "lua_session_timeout": 25, + "lua_task_timeout": 26, + "max_checks_per_thread": 0, + "maxaccept": 28, + "maxpollevents": 29, + "maxrewrite": 30, + "memory_hot_size": 56, + "pattern_cache_size": 31, + "peers_max_updates_at_once": 200, + "pipesize": 32, + "pool_high_fd_ratio": 33, + "pool_low_fd_ratio": 34, + "pt_zero_copy_forwarding": "enabled", + "quic_frontend_conn_tx_buffers_limit": 10, + "quic_frontend_max_idle_timeout": 10000, + "quic_frontend_max_streams_bidi": 100, + "quic_max_frame_loss": 5, + "quic_retry_threshold": 5, + "quic_socket_owner": "connection", + "rcvbuf_backend": 1024, + "rcvbuf_client": 35, + "rcvbuf_frontend": 2048, + "rcvbuf_server": 36, + "recv_enough": 37, + "runqueue_depth": 38, + "sched_low_latency": "enabled", + "sndbuf_backend": 1024, + "sndbuf_client": 39, + "sndbuf_frontend": 2048, + "sndbuf_server": 40, + "ssl_cachesize": 41, + "ssl_capture_buffer_size": 47, + "ssl_ctx_cache_size": 46, + "ssl_default_dh_param": 45, + "ssl_force_private_cache": true, + "ssl_keylog": "enabled", + "ssl_lifetime": 43, + "ssl_maxrecord": 44, + "ssl_ocsp_update_max_delay": 48, + "ssl_ocsp_update_min_delay": 49, + "stick_counters": 50, + "vars_global_max_size": 51, + "vars_proc_max_size": 52, + "vars_reqres_max_size": 53, + "vars_sess_max_size": 54, + "vars_txn_max_size": 55, + "zlib_memlevel": 54, + "zlib_windowsize": 55 + }, + "tune_ssl_default_dh_param": 45, + "uid": 1, + "ulimit_n": 10, + "unsetenv": "third fourth", + "user": "thomas", + "waf-body-limit": 15000, + "waf-json-levels": 8, + "waf-load": "/tmp/rules.conf", + "wurfl_options": { + "cache_size": 64, + "data_file": "path", + "information_list": "wurfl_id,wurfl_root_id,wurfl_isdevroot,wurfl_useragent,wurfl_api_version,wurfl_info,wurfl_last_load_time,wurfl_normalized_useragent", + "information_list_separator": ",", + "patch_file": "path1,path2" + }, + "zero_warning": true, + "log_targets": [ + { + "address": "127.0.0.1:10001", + "facility": "local0", + "index": 0, + "sample_range": "1", + "sample_size": 4 + }, + { + "address": "127.0.0.1:10002", + "facility": "local0", + "index": 1, + "sample_range": "2", + "sample_size": 4 + } + ] + }, + "backends": [ + { + "error_files": [ + { + "code": 403, + "file": "/test/403.html" + }, + { + "code": 500, + "file": "/test/500.html" + }, + { + "code": 429, + "file": "/test/429.html" + } + ], + "errorfiles_from_http_errors": [ + { + "codes": [ + 404, + 401, + 500 + ], + "name": "my_errors" + }, + { + "name": "other_errors" + }, + { + "codes": [ + 501 + ], + "name": "another_errors" + } + ], + "accept_invalid_http_response": "disabled", + "adv_check": "httpchk", + "balance": { + "algorithm": "roundrobin" + }, + "bind_process": "all", + "check_timeout": 2000, + "checkcache": "enabled", + "compression": { + "types": [ + "application/json", + "text/plain" + ] + }, + "cookie": { + "httponly": true, + "name": "BLA", + "nocache": true, + "type": "rewrite" + }, + "default_server": { + "fall": 2000, + "health_check_port": 8888, + "inter": 5000, + "log-bufsize": 6, + "pool_low_conn": 128, + "rise": 4000, + "ws": "auto" + }, + "description": "this is a backend description", + "email_alert": { + "from": "prod01@example.com", + "level": "warning", + "mailers": "localmailer1", + "myhostname": "prod01", + "to": "sre@example.com" + }, + "enabled": true, + "errorloc302": { + "code": 404, + "url": "http://www.myawesomesite.com/not_found" + }, + "errorloc303": { + "code": 404, + "url": "http://www.myawesomesite.com/not_found" + }, + "external_check": "enabled", + "external_check_command": "/bin/false", + "force_persist": { + "cond": "unless", + "cond_test": "acl-name-2" + }, + "forwardfor": { + "enabled": "enabled", + "header": "X-Forwarded-For" + }, + "fullconn": 11, + "h1_case_adjust_bogus_server": "disabled", + "hash_type": { + "function": "sdbm", + "method": "consistent", + "modifier": "avalanche" + }, + "http-check": { + "index": 0, + "type": "connect" + }, + "http-keep-alive": "enabled", + "http_connection_mode": "http-keep-alive", + "http_restrict_req_hdr_names": "preserve", + "http_send_name_header": "X-My-Awesome-Header", + "httpchk_params": { + "method": "HEAD", + "uri": "/" + }, + "id": 456, + "ignore_persist": { + "cond": "if", + "cond_test": "acl-name" + }, + "independent_streams": "enabled", + "load_server_state_from_file": "local", + "log_tag": "bla", + "max_keep_alive_queue": 101, + "mode": "http", + "name": "test", + "nolinger": "enabled", + "originalto": { + "enabled": "enabled", + "header": "X-Client-Dst" + }, + "persist": "enabled", + "persist_rule": { + "rdp_cookie_name": "name", + "type": "rdp-cookie" + }, + "prefer_last_server": "enabled", + "retry_on": "504 505", + "server_fin_timeout": 1000, + "server_state_file_name": "use-backend-name", + "server_timeout": 3000, + "source": { + "address": "192.168.1.222", + "hdr": "hdr", + "occ": "occ", + "usesrc": "hdr_ip" + }, + "splice_auto": "enabled", + "splice_request": "enabled", + "splice_response": "enabled", + "spop_check": "enabled", + "srvtcpka": "enabled", + "srvtcpka_cnt": 10, + "srvtcpka_idle": 10000, + "srvtcpka_intvl": 10000, + "stats_options": { + "stats_auths": [ + { + "passwd": "AdMiN123", + "user": "admin" + }, + { + "passwd": "AdMiN1234", + "user": "admin2" + } + ], + "stats_http_requests": [ + { + "realm": "HAProxy\\\\ Statistics", + "type": "auth" + }, + { + "cond": "if", + "cond_test": "something", + "type": "allow" + } + ], + "stats_realm": true, + "stats_realm_realm": "HAProxy\\\\ Statistics", + "stats_show_modules": true, + "stats_show_node_name": null + }, + "tarpit_timeout": 2000, + "tcp_smart_connect": "enabled", + "tcpka": "enabled", + "transparent": "enabled", + "tunnel_timeout": 5000, + "use_fcgi_app": "app-name", + "http_checks": [ + { + "index": 0, + "type": "connect" + }, + { + "headers": [ + { + "fmt": "haproxy.1wt.eu", + "name": "host" + } + ], + "index": 1, + "method": "GET", + "type": "send", + "uri": "/", + "version": "HTTP/1.1" + }, + { + "index": 2, + "match": "status", + "pattern": "200-399", + "type": "expect" + }, + { + "index": 3, + "port": 443, + "sni": "haproxy.1wt.eu", + "ssl": true, + "type": "connect" + }, + { + "index": 4, + "match": "status", + "pattern": "200,201,300-310", + "type": "expect" + }, + { + "index": 5, + "match": "header", + "pattern": "name \"set-cookie\" value -m beg \"sessid=\"", + "type": "expect" + }, + { + "exclamation_mark": true, + "index": 6, + "match": "string", + "pattern": "SQL\\ Error", + "type": "expect" + }, + { + "exclamation_mark": true, + "index": 7, + "match": "rstatus", + "pattern": "^5", + "type": "expect" + }, + { + "index": 8, + "match": "rstring", + "pattern": "\u003c!--tag:[0-9a-f]*--\u003e\u003c/html\u003e", + "type": "expect" + }, + { + "index": 9, + "type": "unset-var", + "var_name": "port", + "var_scope": "check" + }, + { + "index": 10, + "type": "set-var", + "var_expr": "int(1234)", + "var_name": "port", + "var_scope": "check" + }, + { + "index": 11, + "type": "set-var-fmt", + "var_expr": "int(1234)", + "var_name": "port", + "var_scope": "check" + }, + { + "index": 12, + "type": "send-state" + }, + { + "index": 13, + "type": "disable-on-404" + } + ], + "http_request_rules": [ + { + "expr": "hdr(x-dst)", + "index": 0, + "type": "set-dst" + }, + { + "expr": "int(4000)", + "index": 1, + "type": "set-dst-port" + } + ], + "server_switching_rules": [ + { + "cond": "if", + "cond_test": "TRUE", + "index": 0, + "target_server": "webserv" + }, + { + "cond": "unless", + "cond_test": "TRUE", + "index": 1, + "target_server": "webserv2" + } + ], + "server_templates": [ + { + "check": "enabled", + "fqdn": "google.com", + "num_or_range": "1-3", + "port": 80, + "prefix": "srv" + }, + { + "backup": "enabled", + "check": "enabled", + "fqdn": "google.com", + "num_or_range": "1-10", + "port": 8080, + "prefix": "site" + }, + { + "backup": "disabled", + "check": "enabled", + "fqdn": "google.com", + "num_or_range": "10-100", + "port": 443, + "prefix": "website" + }, + { + "backup": "enabled", + "check": "enabled", + "fqdn": "test.com", + "num_or_range": "5", + "port": 0, + "prefix": "test" + } + ], + "servers": [ + { + "client_sigalgs": "ECDSA+SHA256:RSA+SHA256", + "cookie": "BLAH", + "curves": "secp384r1", + "inter": 2000, + "log-bufsize": 10, + "maxconn": 1000, + "pool_low_conn": 128, + "pool_purge_delay": 10000, + "proxy-v2-options": [ + "authority", + "crc32c" + ], + "set-proxy-v2-tlv-fmt": { + "id": "0x20", + "value": "%[fc_pp_tlv(0x20)]" + }, + "sigalgs": "ECDSA+SHA256", + "slowstart": 6000, + "ssl": "enabled", + "tcp_ut": 2000, + "weight": 10, + "ws": "h1", + "address": "192.168.1.1", + "id": 1234, + "name": "webserv", + "port": 9200 + }, + { + "cookie": "BLAH", + "inter": 2000, + "maxconn": 1000, + "pool_low_conn": 128, + "proxy-v2-options": [ + "authority", + "crc32c" + ], + "slowstart": 6000, + "ssl": "enabled", + "weight": 10, + "ws": "h1", + "address": "192.168.1.1", + "name": "webserv2", + "port": 9300 + } + ], + "stick_rules": [ + { + "index": 0, + "pattern": "src", + "table": "test", + "type": "store-request" + }, + { + "index": 1, + "pattern": "src", + "table": "test", + "type": "match" + }, + { + "index": 2, + "pattern": "src", + "table": "test", + "type": "on" + }, + { + "index": 3, + "pattern": "src", + "type": "store-response" + }, + { + "index": 4, + "pattern": "src_port", + "table": "test_port", + "type": "store-response" + }, + { + "cond": "if", + "cond_test": "TRUE", + "index": 5, + "pattern": "src", + "table": "test", + "type": "store-response" + } + ], + "tcp_response_rules": [ + { + "action": "accept", + "cond": "if", + "cond_test": "TRUE", + "index": 0, + "type": "content" + }, + { + "action": "reject", + "cond": "if", + "cond_test": "FALSE", + "index": 1, + "type": "content" + }, + { + "action": "lua", + "cond": "if", + "cond_test": "FALSE", + "index": 2, + "lua_action": "foo", + "lua_params": "param1 param2", + "type": "content" + }, + { + "action": "set-bandwidth-limit", + "bandwidth_limit_limit": "1m", + "bandwidth_limit_name": "my-limit", + "bandwidth_limit_period": "10s", + "index": 3, + "type": "content" + }, + { + "action": "set-bandwidth-limit", + "bandwidth_limit_limit": "2m", + "bandwidth_limit_name": "my-limit-reverse", + "bandwidth_limit_period": "20s", + "index": 4, + "type": "content" + }, + { + "action": "set-bandwidth-limit", + "bandwidth_limit_limit": "3m", + "bandwidth_limit_name": "my-limit-cond", + "cond": "if", + "cond_test": "FALSE", + "index": 5, + "type": "content" + }, + { + "action": "close", + "cond": "if", + "cond_test": "FALSE", + "index": 6, + "type": "content" + }, + { + "action": "sc-add-gpc", + "cond": "if", + "cond_test": "FALSE", + "index": 7, + "sc_id": 1, + "sc_int": 1, + "type": "content" + }, + { + "action": "sc-inc-gpc0", + "cond": "if", + "cond_test": "FALSE", + "index": 8, + "sc_id": 1, + "type": "content" + }, + { + "action": "sc-inc-gpc1", + "cond": "if", + "cond_test": "FALSE", + "index": 9, + "sc_id": 2, + "type": "content" + }, + { + "action": "sc-set-gpt0", + "cond": "if", + "cond_test": "FALSE", + "expr": "hdr(Host),lower", + "index": 10, + "sc_id": 3, + "type": "content" + }, + { + "action": "send-spoe-group", + "cond": "if", + "cond_test": "FALSE", + "index": 11, + "spoe_engine": "engine", + "spoe_group": "group", + "type": "content" + }, + { + "action": "set-log-level", + "cond": "if", + "cond_test": "FALSE", + "index": 12, + "log_level": "silent", + "type": "content" + }, + { + "action": "set-mark", + "cond": "if", + "cond_test": "FALSE", + "index": 13, + "mark_value": "0x1Ab", + "type": "content" + }, + { + "action": "set-nice", + "cond": "if", + "cond_test": "FALSE", + "index": 14, + "nice_value": 1, + "type": "content" + }, + { + "action": "set-tos", + "cond": "if", + "cond_test": "FALSE", + "index": 15, + "tos_value": "2", + "type": "content" + }, + { + "action": "silent-drop", + "cond": "if", + "cond_test": "FALSE", + "index": 16, + "type": "content" + }, + { + "action": "unset-var", + "cond": "if", + "cond_test": "FALSE", + "index": 17, + "type": "content", + "var_name": "my_var", + "var_scope": "req" + } + ], + "waf_body_rules": [ + { + "index": 0, + "type": "allow" + }, + { + "cond": "if", + "cond_test": "{ var(txn.myip) -m ip 127.0.0.0/8 10.0.0.0/8 }", + "index": 1, + "type": "deny" + } + ] + }, + { + "adv_check": "httpchk", + "balance": { + "algorithm": "roundrobin" + }, + "bind_process": "all", + "check_timeout": 2000, + "checkcache": "disabled", + "cookie": { + "httponly": true, + "name": "BLA", + "nocache": true, + "type": "rewrite" + }, + "default_server": { + "fall": 2000, + "health_check_port": 8888, + "inter": 5000, + "rise": 4000, + "slowstart": 6000 + }, + "email_alert": { + "from": "prod01@example.com", + "level": "warning", + "mailers": "localmailer1", + "myhostname": "prod01", + "to": "sre@example.com" + }, + "forwardfor": { + "enabled": "enabled", + "header": "X-Forwarded-For" + }, + "from": "test_defaults_2", + "hash_type": { + "function": "sdbm", + "method": "consistent", + "modifier": "avalanche" + }, + "http-check": { + "index": 0, + "match": "rstatus", + "pattern": "some-pattern", + "type": "expect" + }, + "http-keep-alive": "enabled", + "http_connection_mode": "http-keep-alive", + "httpchk_params": { + "method": "HEAD", + "uri": "/" + }, + "independent_streams": "disabled", + "log_tag": "bla", + "mode": "http", + "name": "test_2", + "nolinger": "disabled", + "originalto": { + "enabled": "enabled", + "except": "127.0.0.1", + "header": "X-Client-Dst" + }, + "persist": "disabled", + "prefer_last_server": "disabled", + "server_timeout": 3000, + "splice_auto": "disabled", + "splice_request": "disabled", + "splice_response": "disabled", + "spop_check": "disabled", + "srvtcpka": "enabled", + "srvtcpka_cnt": 10, + "srvtcpka_idle": 10000, + "srvtcpka_intvl": 10000, + "stats_options": { + "stats_auths": [ + { + "passwd": "AdMiN123", + "user": "admin" + }, + { + "passwd": "AdMiN1234", + "user": "admin2" + } + ], + "stats_http_requests": [ + { + "realm": "HAProxy\\\\ Statistics", + "type": "auth" + }, + { + "cond": "if", + "cond_test": "something", + "type": "allow" + } + ], + "stats_realm": true, + "stats_realm_realm": "HAProxy\\\\ Statistics", + "stats_show_modules": true, + "stats_show_node_name": null + }, + "stick_table": { + "expire": 3600000, + "peers": "mycluster", + "size": 102400, + "store": "http_req_rate(10s)", + "type": "ip", + "write_to": "t99" + }, + "tcp_smart_connect": "disabled", + "tcpka": "enabled", + "transparent": "disabled", + "tunnel_timeout": 5000, + "http_checks": [ + { + "index": 0, + "match": "rstatus", + "pattern": "some-pattern", + "type": "expect" + } + ], + "http_error_rules": [ + { + "return_hdrs": [ + { + "fmt": "value", + "name": "Some-Header" + } + ], + "index": 0, + "return_content": "\"My content\"", + "return_content_format": "string", + "return_content_type": "\"text/plain\"", + "status": 200, + "type": "status" + }, + { + "return_hdrs": [ + { + "fmt": "value1", + "name": "Additional-Header" + }, + { + "fmt": "value", + "name": "Some-Header" + } + ], + "index": 1, + "return_content": "\"My content\"", + "return_content_format": "string", + "return_content_type": "application/json", + "status": 503, + "type": "status" + } + ] + } + ], + "caches": [ + { + "max_age": 60, + "max_object_size": 8, + "max_secondary_entries": 10, + "name": "test", + "process_vary": true, + "total_max_size": 1024 + } + ], + "dynamic_update": { + "dynamic_update_rules": [ + { + "ciphers": "ECDHE+aRSA+AES256", + "crt": "/etc/haproxy/site.pem", + "force_sslv3": true, + "force_tlsv10": true, + "force_tlsv11": true, + "force_tlsv12": true, + "no_sslv3": true, + "no_tls_tickets": true, + "no_tlsv10": true, + "no_tlsv11": true, + "no_tlsv12": true, + "verify": "required", + "verifyhost": "site.com", + "delay": 300000, + "dontlog-normal": true, + "id": "/etc/hapee-2.5/redirects.map", + "index": 0, + "log": true, + "map": true, + "modified": true, + "purge_count": 1000, + "purge_id": "5000", + "purge_interval": 10000, + "retries": 3, + "source_address": "127.0.0.1", + "source_port": 80, + "timeout": 5000, + "tls_ticket_keys": true, + "url": "http://10.0.0.1:80/redirects.map", + "xdelay": 300000, + "xmodified": true, + "xnext": 10000, + "xretry": 5000, + "xstart": 5000 + }, + { + "id": "/etc/hapee-2.4/redirects.map", + "index": 1, + "url": "http://10.0.0.2:81/redirects.map" + } + ] + }, + "fcgi_apps": [ + { + "docroot": "/path/to/chroot", + "get_values": "enabled", + "index": "index.php", + "keep_conn": "disabled", + "log_stderrs": [ + { + "address": "127.0.0.1:1515", + "facility": "local2", + "format": "rfc5424", + "len": 8192, + "level": "info", + "minlevel": "debug", + "sample": { + "ranges": "1,2-5", + "size": 6 + } + }, + { + "address": "127.0.0.1:1515", + "facility": "local2", + "format": "rfc5424", + "len": 8192, + "level": "info", + "sample": { + "ranges": "1,2-5", + "size": 6 + } + }, + { + "address": "127.0.0.1:1515", + "facility": "local2" + }, + { + "global": true + } + ], + "max_reqs": 1024, + "mpxs_conns": "disabled", + "name": "test", + "pass_headers": [ + { + "cond": "unless", + "cond_test": "acl", + "name": "x-header" + }, + { + "cond": "if", + "cond_test": "acl", + "name": "x-header" + }, + { + "name": "x-header" + } + ], + "path_info": "^(/.+\\.php)(/.*)?$", + "set_params": [ + { + "cond": "if", + "cond_test": "acl", + "format": "fmt", + "name": "name" + }, + { + "cond": "unless", + "cond_test": "acl", + "format": "fmt", + "name": "name" + }, + { + "format": "fmt", + "name": "name" + } + ], + "acls": [ + { + "acl_name": "invalid_src", + "criterion": "src", + "index": 0, + "value": "0.0.0.0/7 224.0.0.0/3" + }, + { + "acl_name": "invalid_src", + "criterion": "src_port", + "index": 1, + "value": "0:1023" + }, + { + "acl_name": "local_dst", + "criterion": "hdr(host)", + "index": 2, + "value": "-i localhost" + } + ] + }, + { + "docroot": "/path/to/chroot", + "get_values": "enabled", + "index": "index.php", + "keep_conn": "disabled", + "log_stderrs": [ + { + "address": "127.0.0.1:1515", + "facility": "local2", + "format": "rfc5424", + "len": 8192, + "level": "info", + "minlevel": "debug", + "sample": { + "ranges": "1,2-5", + "size": 6 + } + }, + { + "address": "127.0.0.1:1515", + "facility": "local2", + "format": "rfc5424", + "len": 8192, + "level": "info", + "sample": { + "ranges": "1,2-5", + "size": 6 + } + }, + { + "address": "127.0.0.1:1515", + "facility": "local2" + }, + { + "global": true + } + ], + "max_reqs": 1024, + "mpxs_conns": "disabled", + "name": "test_2", + "pass_headers": [ + { + "cond": "unless", + "cond_test": "acl", + "name": "x-header" + }, + { + "cond": "if", + "cond_test": "acl", + "name": "x-header" + }, + { + "name": "x-header" + } + ], + "path_info": "^(/.+\\.php)(/.*)?$", + "set_params": [ + { + "cond": "if", + "cond_test": "acl", + "format": "fmt", + "name": "name" + }, + { + "cond": "unless", + "cond_test": "acl", + "format": "fmt", + "name": "name" + }, + { + "format": "fmt", + "name": "name" + } + ], + "acls": [ + { + "acl_name": "invalid_src", + "criterion": "src", + "index": 0, + "value": "0.0.0.0/7 224.0.0.0/3" + }, + { + "acl_name": "invalid_src", + "criterion": "src_port", + "index": 1, + "value": "0:1023" + }, + { + "acl_name": "local_dst", + "criterion": "hdr(host)", + "index": 2, + "value": "-i localhost" + } + ] + } + ], + "frontends": [ + { + "backlog": 2048, + "bind_process": "even", + "client_timeout": 4000, + "clitcpka": "enabled", + "clitcpka_cnt": 10, + "clitcpka_idle": 10000, + "clitcpka_intvl": 10000, + "contstats": "enabled", + "default_backend": "test_2", + "dontlog_normal": "disabled", + "dontlognull": "enabled", + "from": "test_defaults", + "http_connection_mode": "httpclose", + "http_ignore_probes": "disabled", + "http_keep_alive_timeout": 3000, + "http_no_delay": "disabled", + "http_request_timeout": 2000, + "http_use_proxy_header": "disabled", + "httplog": true, + "httpslog": "disabled", + "idle_close_on_response": "disabled", + "independent_streams": "disabled", + "log_separate_errors": "enabled", + "log_tag": "bla", + "maxconn": 2000, + "mode": "http", + "name": "test_2", + "nolinger": "disabled", + "originalto": { + "enabled": "enabled", + "except": "127.0.0.1", + "header": "X-Client-Dst" + }, + "socket_stats": "disabled", + "splice_auto": "disabled", + "splice_request": "disabled", + "splice_response": "disabled", + "stats_options": { + "stats_auths": [ + { + "passwd": "AdMiN123", + "user": "admin" + }, + { + "passwd": "AdMiN1234", + "user": "admin2" + } + ], + "stats_realm": true, + "stats_realm_realm": "HAProxy\\\\ Statistics", + "stats_show_modules": true, + "stats_show_node_name": null + }, + "tcp_smart_accept": "disabled", + "tcpka": "enabled", + "unique_id_format": "%{+X}o%ci:%cp_%fi:%fp_%Ts_%rt", + "unique_id_header": "X-Unique-ID-test-2", + "http_request_rules": [ + { + "capture_len": 10, + "capture_sample": "req.cook_cnt(FirstVisit),bool", + "index": 0, + "type": "capture" + }, + { + "capture_id": 0, + "capture_sample": "req.cook_cnt(FirstVisit),bool", + "index": 1, + "type": "capture" + } + ], + "http_response_rules": [ + { + "capture_id": 0, + "capture_sample": "res.header", + "index": 0, + "type": "capture" + } + ], + "waf_body_rules": [ + { + "cond": "unless", + "cond_test": "{ var(txn.jwt_alg) \"RS256\" }", + "index": 0, + "type": "deny" + } + ] + }, + { + "error_files": [ + { + "code": 403, + "file": "/test/403.html" + }, + { + "code": 500, + "file": "/test/500.html" + }, + { + "code": 429, + "file": "/test/429.html" + } + ], + "accept_invalid_http_request": "disabled", + "backlog": 2048, + "bind_process": "odd", + "client_fin_timeout": 1000, + "client_timeout": 4000, + "clitcpka": "enabled", + "clitcpka_cnt": 10, + "clitcpka_idle": 10000, + "clitcpka_intvl": 10000, + "compression": { + "algorithms": [ + "identity", + "gzip" + ], + "offload": true, + "types": [ + "text/plain" + ] + }, + "contstats": "enabled", + "default_backend": "test", + "description": "this is a frontend description", + "disabled": true, + "dontlog_normal": "enabled", + "dontlognull": "enabled", + "email_alert": { + "from": "srv01@example.com", + "level": "warning", + "mailers": "localmailer1", + "myhostname": "srv01", + "to": "problems@example.com" + }, + "error_log_format": "%T\\ %t\\ Some\\ Text", + "errorloc302": { + "code": 404, + "url": "http://www.myawesomesite.com/not_found" + }, + "errorloc303": { + "code": 404, + "url": "http://www.myawesomesite.com/not_found" + }, + "fingerprint": true, + "fingerprint_ssl": true, + "h1_case_adjust_bogus_client": "disabled", + "http_connection_mode": "httpclose", + "http_ignore_probes": "enabled", + "http_keep_alive_timeout": 3000, + "http_no_delay": "enabled", + "http_request_timeout": 2000, + "http_restrict_req_hdr_names": "delete", + "http_use_proxy_header": "enabled", + "httplog": true, + "httpslog": "enabled", + "id": 123, + "idle_close_on_response": "enabled", + "independent_streams": "enabled", + "log_separate_errors": "enabled", + "log_tag": "bla", + "maxconn": 2000, + "mode": "http", + "monitor_fail": { + "cond": "if", + "cond_test": "site_dead" + }, + "monitor_uri": "/healthz", + "name": "test", + "nolinger": "enabled", + "originalto": { + "enabled": "enabled", + "except": "127.0.0.1" + }, + "socket_stats": "enabled", + "splice_auto": "enabled", + "splice_request": "enabled", + "splice_response": "enabled", + "stats_options": { + "stats_auths": [ + { + "passwd": "AdMiN123", + "user": "admin" + }, + { + "passwd": "AdMiN1234", + "user": "admin2" + } + ], + "stats_realm": true, + "stats_realm_realm": "HAProxy\\\\ Statistics", + "stats_show_modules": true, + "stats_show_node_name": null + }, + "tarpit_timeout": 2000, + "tcp_smart_accept": "enabled", + "tcpka": "enabled", + "unique_id_format": "%{+X}o%ci:%cp_%fi:%fp_%Ts_%rt:%pid", + "unique_id_header": "X-Unique-ID", + "acls": [ + { + "acl_name": "invalid_src", + "criterion": "src", + "index": 0, + "value": "0.0.0.0/7 224.0.0.0/3" + }, + { + "acl_name": "invalid_src", + "criterion": "src_port", + "index": 1, + "value": "0:1023" + }, + { + "acl_name": "local_dst", + "criterion": "hdr(host)", + "index": 2, + "value": "-i localhost" + }, + { + "acl_name": "waf_wafTest_drop", + "criterion": "var(txn.wafTest.drop),bool", + "index": 3 + } + ], + "backend_switching_rules": [ + { + "cond": "if", + "cond_test": "TRUE", + "index": 0, + "name": "test_2" + }, + { + "index": 1, + "name": "%[req.cookie(foo)]" + } + ], + "binds": [ + { + "ca_verify_file": "ca.pem", + "client_sigalgs": "ECDSA+SHA256:RSA+SHA256", + "name": "webserv", + "nice": 789, + "sigalgs": "RSA+SHA256", + "thread": "all", + "address": "192.168.1.1", + "port": 80 + }, + { + "name": "webserv2", + "thread": "1/all", + "address": "192.168.1.1", + "port": 8080 + }, + { + "name": "webserv3", + "thread": "1/1", + "address": "192.168.1.2", + "port": 8080 + }, + { + "name": "ipv6", + "thread": "1/1-1", + "address": "2a01:c9c0:a3:8::3", + "port": 80 + }, + { + "name": "test-quic", + "quic-socket": "connection", + "thread": "1/1", + "address": "192.168.1.1", + "port": 80 + }, + { + "name": "testnbcon", + "nbconn": 6, + "thread": "1/all", + "address": "192.168.1.1", + "port": 80 + } + ], + "captures": [ + { + "index": 0, + "length": 1, + "type": "request" + } + ], + "filters": [ + { + "index": 0, + "rule-files": null, + "trace_hexdump": true, + "trace_name": "BEFORE-HTTP-COMP", + "trace_rnd_parsing": true, + "type": "trace" + }, + { + "index": 1, + "rule-files": null, + "type": "compression" + }, + { + "index": 2, + "rule-files": null, + "trace_name": "AFTER-HTTP-COMP", + "trace_rnd_forwarding": true, + "type": "trace" + }, + { + "app_name": "my-app", + "index": 3, + "rule-files": null, + "type": "fcgi-app" + }, + { + "bandwidth_limit_name": "in", + "default_limit": 1024, + "default_period": 1000, + "index": 4, + "min_size": 1048576, + "rule-files": null, + "type": "bwlim-in" + }, + { + "bandwidth_limit_name": "out", + "index": 5, + "key": "name(arg1)", + "limit": 1024, + "min_size": 32, + "rule-files": null, + "table": "st_src_global", + "type": "bwlim-out" + } + ], + "http_after_response_rules": [ + { + "index": 0, + "map_file": "map.lst", + "map_keyfmt": "%[src]", + "map_valuefmt": "%[res.hdr(X-Value)]", + "type": "set-map" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 1, + "map_file": "map.lst", + "map_keyfmt": "%[src]", + "type": "del-map" + }, + { + "acl_file": "map.lst", + "acl_keyfmt": "%[src]", + "cond": "if", + "cond_test": "FALSE", + "index": 2, + "type": "del-acl" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 3, + "sc_id": 1, + "type": "sc-add-gpc" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 4, + "sc_id": 1, + "type": "sc-inc-gpc" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 5, + "type": "sc-inc-gpc0" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 6, + "type": "sc-inc-gpc1" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 7, + "sc_expr": "hdr(Host),lower", + "sc_id": 1, + "type": "sc-set-gpt0" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 8, + "sc_id": 1, + "sc_int": 20, + "type": "sc-set-gpt0" + }, + { + "hdr_format": "\"max-age=31536000\"", + "hdr_name": "Strict-Transport-Security", + "index": 9, + "type": "set-header" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 10, + "log_level": "silent", + "type": "set-log-level" + }, + { + "hdr_format": "\\1;ip=%bi;\\2", + "hdr_match": "(C=[^;]*);(.*)", + "hdr_name": "Set-Cookie", + "index": 11, + "type": "replace-header" + }, + { + "hdr_format": "private", + "hdr_match": "^public$", + "hdr_name": "Cache-control", + "index": 12, + "type": "replace-value" + }, + { + "index": 13, + "status": 503, + "status_reason": "\"SlowDown\"", + "type": "set-status" + }, + { + "index": 14, + "type": "set-var", + "var_expr": "res.hdr(location)", + "var_name": "last_redir", + "var_scope": "sess" + }, + { + "index": 15, + "type": "unset-var", + "var_name": "last_redir", + "var_scope": "sess" + } + ], + "http_error_rules": [ + { + "index": 0, + "return_content": "/var/errors.file", + "return_content_format": "lf-file", + "return_content_type": "application/json", + "status": 400, + "type": "status" + } + ], + "http_request_rules": [ + { + "cond": "if", + "cond_test": "src 192.168.0.0/16", + "index": 0, + "type": "allow" + }, + { + "hdr_format": "%[ssl_fc]", + "hdr_name": "X-SSL", + "index": 1, + "type": "set-header" + }, + { + "index": 2, + "type": "set-var", + "var_expr": "req.fhdr(user-agent),lower", + "var_name": "my_var", + "var_scope": "req" + }, + { + "index": 3, + "map_file": "map.lst", + "map_keyfmt": "%[src]", + "map_valuefmt": "%[req.hdr(X-Value)]", + "type": "set-map" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 4, + "map_file": "map.lst", + "map_keyfmt": "%[src]", + "type": "del-map" + }, + { + "acl_file": "map.lst", + "acl_keyfmt": "%[src]", + "cond": "if", + "cond_test": "FALSE", + "index": 5, + "type": "del-acl" + }, + { + "cache_name": "cache-name", + "cond": "if", + "cond_test": "FALSE", + "index": 6, + "type": "cache-use" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 7, + "type": "disable-l7-retry" + }, + { + "cond": "if", + "cond_test": "FALSE", + "hint_format": "%[src]", + "hint_name": "hint-name", + "index": 8, + "type": "early-hint" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 9, + "type": "replace-uri", + "uri-fmt": "https://1", + "uri-match": "^http://(.*)" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 10, + "sc_id": 1, + "sc_int": 1, + "type": "sc-add-gpc" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 11, + "sc_id": 1, + "type": "sc-inc-gpc" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 12, + "type": "sc-inc-gpc0" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 13, + "type": "sc-inc-gpc1" + }, + { + "expr": "hdr(Host),lower", + "index": 14, + "protocol": "ipv4", + "resolvers": "mydns", + "type": "do-resolve", + "var_name": "txn.myip" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 15, + "sc_expr": "hdr(Host),lower", + "sc_id": 1, + "type": "sc-set-gpt0" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 16, + "sc_id": 1, + "sc_int": 20, + "type": "sc-set-gpt0" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 17, + "mark_value": "20", + "type": "set-mark" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 18, + "nice_value": 20, + "type": "set-nice" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 19, + "method_fmt": "POST", + "type": "set-method" + }, + { + "cond": "if", + "cond_test": "FALSE", + "expr": "req.hdr(class)", + "index": 20, + "type": "set-priority-class" + }, + { + "cond": "if", + "cond_test": "FALSE", + "expr": "req.hdr(offset)", + "index": 21, + "type": "set-priority-offset" + }, + { + "cond": "if", + "cond_test": "FALSE", + "expr": "req.hdr(src)", + "index": 22, + "type": "set-src" + }, + { + "cond": "if", + "cond_test": "FALSE", + "expr": "req.hdr(port)", + "index": 23, + "type": "set-src-port" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 24, + "type": "wait-for-handshake" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 25, + "tos_value": "0", + "type": "set-tos" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 26, + "type": "silent-drop" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 27, + "type": "unset-var", + "var_name": "my_var", + "var_scope": "req" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 28, + "strict_mode": "on", + "type": "strict-mode" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 29, + "lua_action": "foo", + "lua_params": "param1 param2", + "type": "lua" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 30, + "service_name": "svrs", + "type": "use-service" + }, + { + "return_hdrs": [ + { + "fmt": "value", + "name": "Some-Header" + } + ], + "cond": "if", + "cond_test": "FALSE", + "index": 31, + "return_content": "\"My content\"", + "return_content_format": "string", + "return_content_type": "\"text/plain\"", + "return_status_code": 200, + "type": "return" + }, + { + "cond": "if", + "cond_test": "!{ ssl_fc }", + "index": 32, + "redir_type": "scheme", + "redir_value": "https", + "type": "redirect" + }, + { + "index": 33, + "redir_code": 302, + "redir_type": "location", + "redir_value": "https://%[hdr(host),field(1,:)]:443%[capture.req.uri]", + "type": "redirect" + }, + { + "cond": "unless", + "cond_test": "src 192.168.0.0/16", + "index": 34, + "return_content_type": "", + "type": "deny" + }, + { + "deny_status": 400, + "index": 35, + "return_content": "/var/errors.file", + "return_content_format": "lf-file", + "return_content_type": "application/json", + "type": "deny" + }, + { + "index": 36, + "type": "wait-for-body", + "wait_at_least": 102400, + "wait_time": 20000 + }, + { + "index": 37, + "timeout": "20", + "timeout_type": "server", + "type": "set-timeout" + }, + { + "index": 38, + "timeout": "20", + "timeout_type": "tunnel", + "type": "set-timeout" + }, + { + "index": 39, + "timeout": "20", + "timeout_type": "client", + "type": "set-timeout" + }, + { + "bandwidth_limit_limit": "1m", + "bandwidth_limit_name": "my-limit", + "bandwidth_limit_period": "10s", + "index": 40, + "type": "set-bandwidth-limit" + }, + { + "bandwidth_limit_limit": "2m", + "bandwidth_limit_name": "my-limit-reverse", + "bandwidth_limit_period": "20s", + "index": 41, + "type": "set-bandwidth-limit" + }, + { + "bandwidth_limit_limit": "3m", + "bandwidth_limit_name": "my-limit-cond", + "cond": "if", + "cond_test": "FALSE", + "index": 42, + "type": "set-bandwidth-limit" + }, + { + "cond": "if", + "cond_test": "TRUE", + "index": 43, + "track_sc_key": "src", + "track_sc_stick_counter": 0, + "track_sc_table": "tr0", + "type": "track-sc" + }, + { + "cond": "if", + "cond_test": "TRUE", + "index": 44, + "track_sc_key": "src", + "track_sc_stick_counter": 1, + "track_sc_table": "tr1", + "type": "track-sc" + }, + { + "cond": "if", + "cond_test": "TRUE", + "index": 45, + "track_sc_key": "src", + "track_sc_stick_counter": 2, + "track_sc_table": "tr2", + "type": "track-sc" + }, + { + "cond": "if", + "cond_test": "TRUE", + "index": 46, + "track_sc_key": "src", + "track_sc_stick_counter": 5, + "track_sc_table": "test", + "type": "track-sc" + } + ], + "http_response_rules": [ + { + "cond": "if", + "cond_test": "src 192.168.0.0/16", + "index": 0, + "type": "allow" + }, + { + "hdr_format": "%[ssl_fc]", + "hdr_name": "X-SSL", + "index": 1, + "type": "set-header" + }, + { + "index": 2, + "type": "set-var", + "var_expr": "req.fhdr(user-agent),lower", + "var_name": "my_var", + "var_scope": "req" + }, + { + "index": 3, + "map_file": "map.lst", + "map_keyfmt": "%[src]", + "map_valuefmt": "%[res.hdr(X-Value)]", + "type": "set-map" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 4, + "map_file": "map.lst", + "map_keyfmt": "%[src]", + "type": "del-map" + }, + { + "acl_file": "map.lst", + "acl_keyfmt": "%[src]", + "cond": "if", + "cond_test": "FALSE", + "index": 5, + "type": "del-acl" + }, + { + "cache_name": "cache-name", + "cond": "if", + "cond_test": "FALSE", + "index": 6, + "type": "cache-store" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 7, + "sc_id": 1, + "sc_int": 1, + "type": "sc-add-gpc" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 8, + "sc_id": 1, + "type": "sc-inc-gpc" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 9, + "type": "sc-inc-gpc0" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 10, + "type": "sc-inc-gpc1" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 11, + "sc_expr": "hdr(Host),lower", + "sc_id": 1, + "type": "sc-set-gpt0" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 12, + "sc_id": 1, + "sc_int": 20, + "type": "sc-set-gpt0" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 13, + "mark_value": "20", + "type": "set-mark" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 14, + "nice_value": 20, + "type": "set-nice" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 15, + "tos_value": "0", + "type": "set-tos" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 16, + "type": "silent-drop" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 17, + "type": "unset-var", + "var_name": "my_var", + "var_scope": "req" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 18, + "track_sc_key": "src", + "track_sc_stick_counter": 0, + "track_sc_table": "tr0", + "type": "track-sc" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 19, + "track_sc_key": "src", + "track_sc_stick_counter": 1, + "track_sc_table": "tr1", + "type": "track-sc" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 20, + "track_sc_key": "src", + "track_sc_stick_counter": 2, + "track_sc_table": "tr2", + "type": "track-sc" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 21, + "strict_mode": "on", + "type": "strict-mode" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 22, + "lua_action": "foo", + "lua_params": "param1 param2", + "type": "lua" + }, + { + "deny_status": 400, + "index": 23, + "return_content": "/var/errors.file", + "return_content_format": "lf-file", + "return_content_type": "application/json", + "type": "deny" + }, + { + "index": 24, + "type": "wait-for-body", + "wait_at_least": 102400, + "wait_time": 20000 + }, + { + "bandwidth_limit_limit": "1m", + "bandwidth_limit_name": "my-limit", + "bandwidth_limit_period": "10s", + "index": 25, + "type": "set-bandwidth-limit" + }, + { + "bandwidth_limit_limit": "2m", + "bandwidth_limit_name": "my-limit-reverse", + "bandwidth_limit_period": "20s", + "index": 26, + "type": "set-bandwidth-limit" + }, + { + "bandwidth_limit_limit": "3m", + "bandwidth_limit_name": "my-limit-cond", + "cond": "if", + "cond_test": "FALSE", + "index": 27, + "type": "set-bandwidth-limit" + }, + { + "cond": "if", + "cond_test": "TRUE", + "index": 28, + "track_sc_key": "src", + "track_sc_stick_counter": 0, + "track_sc_table": "tr0", + "type": "track-sc" + }, + { + "cond": "if", + "cond_test": "TRUE", + "index": 29, + "track_sc_key": "src", + "track_sc_stick_counter": 1, + "track_sc_table": "tr1", + "type": "track-sc" + }, + { + "cond": "if", + "cond_test": "TRUE", + "index": 30, + "track_sc_key": "src", + "track_sc_stick_counter": 2, + "track_sc_table": "tr2", + "type": "track-sc" + }, + { + "cond": "if", + "cond_test": "TRUE", + "index": 31, + "track_sc_key": "src", + "track_sc_stick_counter": 5, + "track_sc_table": "test", + "type": "track-sc" + }, + { + "index": 32, + "timeout": "20", + "timeout_type": "server", + "type": "set-timeout" + }, + { + "index": 33, + "timeout": "20", + "timeout_type": "tunnel", + "type": "set-timeout" + }, + { + "index": 34, + "timeout": "20", + "timeout_type": "client", + "type": "set-timeout" + } + ], + "log_targets": [ + { + "global": true, + "index": 0 + }, + { + "index": 1, + "nolog": true + }, + { + "address": "127.0.0.1:514", + "facility": "local0", + "index": 2, + "level": "notice", + "minlevel": "notice" + } + ], + "tcp_request_rules": [ + { + "action": "accept", + "cond": "if", + "cond_test": "TRUE", + "index": 0, + "type": "connection" + }, + { + "action": "reject", + "cond": "if", + "cond_test": "FALSE", + "index": 1, + "type": "connection" + }, + { + "action": "accept", + "cond": "if", + "cond_test": "TRUE", + "index": 2, + "type": "content" + }, + { + "action": "reject", + "cond": "if", + "cond_test": "FALSE", + "index": 3, + "type": "content" + }, + { + "action": "silent-drop", + "index": 4, + "type": "connection" + }, + { + "action": "silent-drop", + "cond": "if", + "cond_test": "TRUE", + "index": 5, + "type": "connection" + }, + { + "action": "lua", + "cond": "if", + "cond_test": "FALSE", + "index": 6, + "lua_action": "foo", + "lua_params": "param1 param2", + "type": "connection" + }, + { + "action": "sc-add-gpc", + "cond": "if", + "cond_test": "FALSE", + "index": 7, + "sc_idx": "0", + "sc_inc_id": "1", + "sc_int": 1, + "type": "connection" + }, + { + "action": "lua", + "cond": "if", + "cond_test": "FALSE", + "index": 8, + "lua_action": "foo", + "lua_params": "param1 param2", + "type": "content" + }, + { + "action": "sc-add-gpc", + "cond": "if", + "cond_test": "FALSE", + "index": 9, + "sc_idx": "0", + "sc_inc_id": "1", + "sc_int": 1, + "type": "content" + }, + { + "action": "set-bandwidth-limit", + "bandwidth_limit_limit": "1m", + "bandwidth_limit_name": "my-limit", + "bandwidth_limit_period": "10s", + "index": 10, + "type": "content" + }, + { + "action": "set-bandwidth-limit", + "bandwidth_limit_limit": "2m", + "bandwidth_limit_name": "my-limit-reverse", + "bandwidth_limit_period": "20s", + "index": 11, + "type": "content" + }, + { + "action": "set-bandwidth-limit", + "bandwidth_limit_limit": "3m", + "bandwidth_limit_name": "my-limit-cond", + "cond": "if", + "cond_test": "FALSE", + "index": 12, + "type": "content" + }, + { + "action": "set-mark", + "cond": "if", + "cond_test": "FALSE", + "index": 13, + "mark_value": "0x1Ab", + "type": "connection" + }, + { + "action": "set-src-port", + "cond": "if", + "cond_test": "FALSE", + "expr": "hdr(port)", + "index": 14, + "type": "connection" + }, + { + "action": "set-tos", + "cond": "if", + "cond_test": "FALSE", + "index": 15, + "tos_value": "1", + "type": "connection" + }, + { + "action": "set-log-level", + "cond": "if", + "cond_test": "FALSE", + "index": 16, + "log_level": "silent", + "type": "content" + }, + { + "action": "set-mark", + "cond": "if", + "cond_test": "FALSE", + "index": 17, + "mark_value": "0x1Ac", + "type": "content" + }, + { + "action": "set-nice", + "cond": "if", + "cond_test": "FALSE", + "index": 18, + "nice_value": 2, + "type": "content" + }, + { + "action": "set-src-port", + "cond": "if", + "cond_test": "FALSE", + "expr": "hdr(port)", + "index": 19, + "type": "content" + }, + { + "action": "set-tos", + "cond": "if", + "cond_test": "FALSE", + "index": 20, + "tos_value": "3", + "type": "content" + }, + { + "action": "set-var-fmt", + "cond": "if", + "cond_test": "FALSE", + "index": 21, + "type": "content", + "var_format": "ssl_c_s_tn", + "var_name": "tn", + "var_scope": "req" + }, + { + "action": "switch-mode", + "cond": "if", + "cond_test": "FALSE", + "index": 22, + "switch_mode_proto": "my-proto", + "type": "content" + }, + { + "action": "sc-add-gpc", + "cond": "if", + "cond_test": "FALSE", + "index": 23, + "sc_idx": "0", + "sc_inc_id": "1", + "sc_int": 1, + "type": "session" + }, + { + "action": "track-sc", + "cond": "if", + "cond_test": "TRUE", + "index": 24, + "track_key": "src", + "track_stick_counter": 0, + "track_table": "tr0", + "type": "content" + }, + { + "action": "track-sc", + "cond": "if", + "cond_test": "TRUE", + "index": 25, + "track_key": "src", + "track_stick_counter": 0, + "track_table": "tr0", + "type": "connection" + }, + { + "action": "track-sc", + "cond": "if", + "cond_test": "TRUE", + "index": 26, + "track_key": "src", + "track_stick_counter": 0, + "track_table": "tr0", + "type": "session" + }, + { + "action": "track-sc", + "cond": "if", + "cond_test": "TRUE", + "index": 27, + "track_key": "src", + "track_stick_counter": 5, + "track_table": "test", + "type": "content" + }, + { + "action": "track-sc", + "cond": "if", + "cond_test": "TRUE", + "index": 28, + "track_key": "src", + "track_stick_counter": 5, + "track_table": "test", + "type": "connection" + }, + { + "action": "track-sc", + "cond": "if", + "cond_test": "TRUE", + "index": 29, + "track_key": "src", + "track_stick_counter": 5, + "track_table": "test", + "type": "session" + }, + { + "action": "attach-srv", + "index": 30, + "server_name": "srv1", + "type": "session" + }, + { + "action": "attach-srv", + "expr": "example.com", + "index": 31, + "server_name": "srv2", + "type": "session" + }, + { + "action": "attach-srv", + "cond": "if", + "cond_test": "is_cached", + "index": 32, + "server_name": "srv3", + "type": "session" + } + ], + "waf_body_rules": [ + { + "cond": "if", + "cond_test": "src 192.168.0.0/16", + "index": 0, + "type": "allow" + }, + { + "index": 1, + "type": "set-var", + "var_expr": "req.fhdr(user-agent),lower", + "var_name": "my_var", + "var_scope": "req" + }, + { + "cond": "if", + "cond_test": "FALSE", + "index": 2, + "type": "unset-var", + "var_name": "my_var", + "var_scope": "req" + }, + { + "cond": "unless", + "cond_test": "src 192.168.0.0/16", + "index": 3, + "type": "deny" + }, + { + "deny_status": 400, + "index": 4, + "type": "deny" + } + ] + } + ], + "http_errors": [ + { + "error_files": [ + { + "code": 400, + "file": "/etc/haproxy/errorfiles/site2/400.http" + }, + { + "code": 404, + "file": "/etc/haproxy/errorfiles/site2/404.http" + }, + { + "code": 501, + "file": "/etc/haproxy/errorfiles/site2/501.http" + } + ], + "name": "website-2" + }, + { + "error_files": [ + { + "code": 400, + "file": "/etc/haproxy/errorfiles/site1/400.http" + }, + { + "code": 404, + "file": "/etc/haproxy/errorfiles/site1/404.http" + }, + { + "code": 408, + "file": "/dev/null" + } + ], + "name": "website-1" + } + ], + "log_forwards": [ + { + "backlog": 10, + "maxconn": 1000, + "name": "sylog-loadb", + "timeout_client": 10000, + "binds": [ + { + "name": "127.0.0.1:1514", + "address": "127.0.0.1", + "port": 1514 + } + ], + "dgram_binds": [ + { + "address": "127.0.0.1", + "name": "webserv", + "port": 1514, + "transparent": true + } + ], + "log_targets": [ + { + "global": true, + "index": 0 + }, + { + "address": "ring@myring", + "facility": "local0", + "index": 1 + }, + { + "address": "127.0.0.1:10001", + "facility": "local0", + "index": 2, + "sample_range": "1", + "sample_size": 4 + }, + { + "address": "127.0.0.1:10002", + "facility": "local0", + "index": 3, + "sample_range": "2", + "sample_size": 4 + }, + { + "address": "127.0.0.1:10003", + "facility": "local0", + "index": 4, + "sample_range": "3", + "sample_size": 4 + }, + { + "address": "127.0.0.1:10004", + "facility": "local0", + "index": 5, + "sample_range": "4", + "sample_size": 4 + } + ] + } + ], + "mailers_sections": [ + { + "name": "localmailer1", + "timeout": 15000, + "mailer_entries": [ + { + "address": "10.0.10.1", + "name": "smtp1", + "port": 514 + }, + { + "address": "10.0.10.2", + "name": "smtp2", + "port": 514 + } + ] + } + ], + "named_defaults": [ + { + "error_files": [ + { + "code": 403, + "file": "/test/403.html" + }, + { + "code": 500, + "file": "/test/500.html" + }, + { + "code": 429, + "file": "/test/429.html" + } + ], + "accept_invalid_http_request": "enabled", + "accept_invalid_http_response": "enabled", + "backlog": 1024, + "balance": { + "algorithm": "roundrobin" + }, + "bind_process": "1-4", + "check_timeout": 2000, + "checkcache": "disabled", + "client_fin_timeout": 1000, + "client_timeout": 4000, + "clitcpka": "enabled", + "clitcpka_cnt": 10, + "clitcpka_idle": 10000, + "clitcpka_intvl": 10000, + "compression": { + "offload": true + }, + "connect_timeout": 5000, + "default_backend": "test", + "default_server": { + "fall": 2000, + "health_check_port": 8888, + "inter": 5000, + "rise": 4000 + }, + "disable_h2_upgrade": "enabled", + "dontlog_normal": "enabled", + "dontlognull": "enabled", + "email_alert": { + "from": "srv01@example.com", + "level": "err", + "mailers": "localmailer1", + "myhostname": "srv01", + "to": "support@example.com" + }, + "external_check": "enabled", + "external_check_command": "/bin/true", + "external_check_path": "/bin", + "forwardfor": { + "enabled": "enabled", + "header": "X-Forwarded-For" + }, + "fullconn": 10, + "h1_case_adjust_bogus_client": "enabled", + "h1_case_adjust_bogus_server": "enabled", + "http-check": { + "index": 0, + "type": "send-state" + }, + "http-use-htx": "enabled", + "http_connection_mode": "httpclose", + "http_ignore_probes": "disabled", + "http_keep_alive_timeout": 3000, + "http_no_delay": "enabled", + "http_request_timeout": 2000, + "http_restrict_req_hdr_names": "reject", + "http_send_name_header": "", + "http_use_proxy_header": "disabled", + "httplog": true, + "httpslog": "disabled", + "idle_close_on_response": "enabled", + "independent_streams": "disabled", + "load_server_state_from_file": "global", + "log_health_checks": "enabled", + "max_keep_alive_queue": 100, + "maxconn": 2000, + "mode": "http", + "monitor_uri": "/monitor", + "name": "unnamed_defaults_1", + "nolinger": "disabled", + "originalto": { + "enabled": "enabled" + }, + "persist": "enabled", + "persist_rule": { + "type": "rdp-cookie" + }, + "prefer_last_server": "enabled", + "queue_timeout": 900, + "retry_on": "503 504", + "server_fin_timeout": 1000, + "server_timeout": 2000, + "socket_stats": "enabled", + "source": { + "address": "192.168.1.200", + "address_second": "192.168.1.201", + "port": 80, + "port_second": 443, + "usesrc": "address" + }, + "splice_auto": "enabled", + "splice_request": "enabled", + "splice_response": "enabled", + "srvtcpka": "enabled", + "srvtcpka_cnt": 10, + "srvtcpka_idle": 10000, + "srvtcpka_intvl": 10000, + "stats_options": { + "stats_auths": [ + { + "passwd": "AdMiN123", + "user": "admin" + }, + { + "passwd": "AdMiN1234", + "user": "admin2" + } + ], + "stats_realm": true, + "stats_realm_realm": "HAProxy\\\\ Statistics", + "stats_show_modules": true, + "stats_show_node_name": null + }, + "tarpit_timeout": 2000, + "tcp_smart_accept": "enabled", + "tcp_smart_connect": "enabled", + "tcpka": "enabled", + "transparent": "enabled", + "http_checks": [ + { + "index": 0, + "type": "send-state" + }, + { + "index": 1, + "type": "disable-on-404" + } + ], + "http_error_rules": [ + { + "index": 0, + "return_content": "/test/503", + "return_content_format": "file", + "return_content_type": "\"application/json\"", + "status": 503, + "type": "status" + }, + { + "index": 1, + "return_content": "/test/429", + "return_content_format": "file", + "return_content_type": "application/json", + "status": 429, + "type": "status" + } + ], + "tcp_check_rules": [ + { + "action": "send", + "data": "GET\\ /\\ HTTP/2.0\\r\\n", + "index": 0 + } + ] + }, + { + "backlog": 1024, + "balance": { + "algorithm": "roundrobin" + }, + "bind_process": "1-4", + "maxconn": 2000, + "mode": "http", + "name": "test_defaults" + }, + { + "clitcpka": "enabled", + "from": "test_defaults", + "name": "test_defaults_2", + "srvtcpka": "enabled" + } + ], + "peers": [ + { + "default_bind": { + "alpn": "h2,http/1.1", + "ssl": true, + "ssl_certificate": "/etc/haproxy/site.pem", + "v4v6": true + }, + "default_server": { + "fall": 2000, + "health_check_port": 8888, + "inter": 5000, + "rise": 4000, + "slowstart": 6000 + }, + "enabled": true, + "name": "mycluster", + "shards": 3, + "peer_entries": [ + { + "address": "192.168.1.1", + "name": "hapee", + "port": 1023, + "shard": 1 + }, + { + "address": "HARDCODEDCLUSTERIP", + "name": "aggregator", + "port": 10023 + } + ] + } + ], + "programs": [ + { + "command": "echo \"Hello, World!\"", + "group": "hapee", + "name": "test", + "start-on-reload": "enabled", + "user": "hapee-lb" + }, + { + "command": "echo \"Hello, World!\"", + "name": "test_2", + "start-on-reload": "disabled" + } + ], + "resolvers": [ + { + "accepted_payload_size": 8192, + "hold_nx": 30000, + "hold_other": 30000, + "hold_refused": 30000, + "hold_timeout": 30000, + "hold_valid": 5000, + "name": "test", + "resolve_retries": 3, + "timeout_resolve": 1000, + "timeout_retry": 1000, + "nameservers": [ + { + "address": "10.0.0.1", + "name": "dns1", + "port": 53 + } + ] + } + ], + "rings": [ + { + "description": "\"My local buffer\"", + "format": "rfc3164", + "maxlen": 1200, + "name": "myring", + "size": 32764, + "timeout_connect": 5000, + "timeout_server": 10000, + "servers": [ + { + "log_proto": "octet-count", + "address": "127.0.0.1", + "name": "mysyslogsrv", + "port": 6514 + }, + { + "check": "enabled", + "resolve-net": "10.0.0.0/8,10.200.200.0/12", + "resolve_opts": "allow-dup-ip,ignore-weight", + "address": "192.168.1.1", + "name": "s1", + "port": 80 + } + ] + } + ], + "userlists": [ + { + "name": "first", + "groups": [ + { + "name": "G1", + "users": "tiger,scott" + }, + { + "name": "G2", + "users": "scott" + } + ], + "users": [ + { + "password": "$6$k6y3o.eP$JlKBx9za9667qe4xHSwRv6J.C0/D7cV91", + "secure_password": true, + "username": "tiger" + }, + { + "password": "elgato", + "secure_password": false, + "username": "scott" + } + ] + }, + { + "name": "second", + "groups": [ + { + "name": "one" + }, + { + "name": "two" + }, + { + "name": "three" + } + ], + "users": [ + { + "groups": "one", + "password": "$6$k6y3o.eP$JlKBxxHSwRv6J.C0/D7cV91", + "secure_password": true, + "username": "neo" + }, + { + "groups": "one,two", + "password": "white-rabbit", + "secure_password": false, + "username": "thomas" + }, + { + "groups": "two", + "password": "hello", + "secure_password": false, + "username": "anderson" + } + ] + } + ] +} diff --git a/configuration/fcgi_app_test.go b/test/fcgi_app_test.go similarity index 54% rename from configuration/fcgi_app_test.go rename to test/fcgi_app_test.go index fb5fe91d..1ce54329 100644 --- a/configuration/fcgi_app_test.go +++ b/test/fcgi_app_test.go @@ -12,11 +12,13 @@ // See the License for the specific language governing permissions and // limitations under the License. -package configuration +package test import ( + _ "embed" "testing" + "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -24,102 +26,58 @@ import ( "github.com/haproxytech/client-native/v5/models" ) +func fcgiAppExpectation() map[string]models.FCGIApps { + initStructuredExpected() + res := StructuredToFCGIAppMap() + // Add individual entries + for _, vs := range res { + for _, v := range vs { + key := v.Name + res[key] = models.FCGIApps{v} + } + } + return res +} + func TestGetFCGIApps(t *testing.T) { + m := make(map[string]models.FCGIApps) v, apps, err := clientTest.GetFCGIApplications("") + m[""] = apps require.NoError(t, err) require.Len(t, apps, 2) require.Equal(t, version, v) + checkFCGIApp(t, m) } func TestGetFCGIApp(t *testing.T) { + mapps := make(map[string]models.FCGIApps) v, app, err := clientTest.GetFCGIApplication("test", "") require.NoError(t, err) require.NotNil(t, app) + mapps["test"] = models.FCGIApps{app} + require.Equal(t, version, v) - assert.Equal(t, "/path/to/chroot", *app.Docroot) - assert.Equal(t, "index.php", app.Index) - assert.Equal(t, `^(/.+\.php)(/.*)?$`, app.PathInfo) - assert.Equal(t, models.FCGIAppGetValuesEnabled, app.GetValues) - assert.Equal(t, models.FCGIAppGetValuesDisabled, app.KeepConn) - assert.Equal(t, models.FCGIAppGetValuesDisabled, app.MpxsConns) - assert.Equal(t, int64(1024), app.MaxReqs) - // set-param - require.Len(t, app.SetParams, 3) - - assert.Equal(t, "name", app.SetParams[0].Name) - assert.Equal(t, "fmt", app.SetParams[0].Format) - assert.Equal(t, "if", app.SetParams[0].Cond) - assert.Equal(t, "acl", app.SetParams[0].CondTest) - - assert.Equal(t, "name", app.SetParams[1].Name) - assert.Equal(t, "fmt", app.SetParams[1].Format) - assert.Equal(t, "unless", app.SetParams[1].Cond) - assert.Equal(t, "acl", app.SetParams[1].CondTest) - - assert.Equal(t, "name", app.SetParams[2].Name) - assert.Equal(t, "fmt", app.SetParams[2].Format) - assert.Empty(t, app.SetParams[2].Cond) - assert.Empty(t, app.SetParams[2].CondTest) - // pass-header - require.Len(t, app.PassHeaders, 3) - - assert.Equal(t, "x-header", app.PassHeaders[0].Name) - assert.Equal(t, models.FCGIPassHeaderCondUnless, app.PassHeaders[0].Cond) - assert.Equal(t, "acl", app.PassHeaders[0].CondTest) - - assert.Equal(t, "x-header", app.PassHeaders[1].Name) - assert.Equal(t, models.FCGIPassHeaderCondIf, app.PassHeaders[1].Cond) - assert.Equal(t, "acl", app.PassHeaders[1].CondTest) - - assert.Equal(t, "x-header", app.PassHeaders[1].Name) - assert.Empty(t, app.PassHeaders[2].Cond) - assert.Empty(t, app.PassHeaders[2].CondTest) - // log-stderr - - require.Len(t, app.LogStderrs, 4) - - assert.False(t, app.LogStderrs[0].Global) - assert.Equal(t, "127.0.0.1:1515", app.LogStderrs[0].Address) - assert.Equal(t, int64(8192), app.LogStderrs[0].Len) - assert.Equal(t, "rfc5424", app.LogStderrs[0].Format) - require.NotNil(t, app.LogStderrs[0].Sample) - assert.Equal(t, "1,2-5", *app.LogStderrs[0].Sample.Ranges) - assert.Equal(t, int64(6), *app.LogStderrs[0].Sample.Size) - assert.Equal(t, "local2", app.LogStderrs[0].Facility) - assert.Equal(t, "info", app.LogStderrs[0].Level) - assert.Equal(t, "debug", app.LogStderrs[0].Minlevel) - - assert.False(t, app.LogStderrs[1].Global) - assert.Equal(t, "127.0.0.1:1515", app.LogStderrs[1].Address) - assert.Equal(t, int64(8192), app.LogStderrs[1].Len) - assert.Equal(t, "rfc5424", app.LogStderrs[1].Format) - require.NotNil(t, app.LogStderrs[1].Sample) - assert.Equal(t, "1,2-5", *app.LogStderrs[1].Sample.Ranges) - assert.Equal(t, int64(6), *app.LogStderrs[1].Sample.Size) - assert.Equal(t, "local2", app.LogStderrs[1].Facility) - assert.Equal(t, "info", app.LogStderrs[1].Level) - assert.Empty(t, app.LogStderrs[1].Minlevel) - - assert.False(t, app.LogStderrs[2].Global) - assert.Equal(t, "127.0.0.1:1515", app.LogStderrs[2].Address) - assert.Empty(t, app.LogStderrs[2].Len) - assert.Empty(t, app.LogStderrs[2].Format) - assert.Nil(t, app.LogStderrs[2].Sample) - assert.Equal(t, "local2", app.LogStderrs[2].Facility) - assert.Empty(t, app.LogStderrs[2].Level) - assert.Empty(t, app.LogStderrs[2].Minlevel) - - assert.True(t, app.LogStderrs[3].Global) - assert.Empty(t, app.LogStderrs[3].Address) - assert.Empty(t, app.LogStderrs[3].Len) - assert.Empty(t, app.LogStderrs[3].Format) - assert.Nil(t, app.LogStderrs[3].Sample) - assert.Empty(t, app.LogStderrs[3].Facility) - assert.Empty(t, app.LogStderrs[3].Level) - assert.Empty(t, app.LogStderrs[3].Minlevel) + checkFCGIApp(t, mapps) +} + +func checkFCGIApp(t *testing.T, got map[string]models.FCGIApps) { + exp := fcgiAppExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } } func TestCreateEditDeleteFCGIApp(t *testing.T) { diff --git a/test/filter_test.go b/test/filter_test.go new file mode 100644 index 00000000..e20d8958 --- /dev/null +++ b/test/filter_test.go @@ -0,0 +1,192 @@ +// 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. +// + +package test + +import ( + _ "embed" + "fmt" + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" + "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" +) + +func filterExpectation() map[string]models.Filters { + initStructuredExpected() + res := StructuredToFilterMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%d", k, *v.Index) + res[key] = models.Filters{v} + } + } + return res +} + +func TestGetFilters(t *testing.T) { //nolint:gocognit + mfilters := make(map[string]models.Filters) + v, filters, err := clientTest.GetFilters(configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + mfilters["frontend/test"] = filters + + _, filters, err = clientTest.GetFilters(configuration.BackendParentName, "test_2", "") + if err != nil { + t.Error(err.Error()) + } + mfilters["backend/test_2"] = filters + + checkFilters(t, mfilters) +} + +func checkFilters(t *testing.T, got map[string]models.Filters) { + exp := filterExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + +func TestGetFilter(t *testing.T) { + m := make(map[string]models.Filters) + v, f, err := clientTest.GetFilter(0, configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + m["frontend/test/0"] = models.Filters{f} + + _, err = f.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + _, _, err = clientTest.GetFilter(3, configuration.BackendParentName, "test2", "") + if err == nil { + t.Error("Should throw error, non existent filter") + } + + checkFilters(t, m) +} + +func TestCreateEditDeleteFilter(t *testing.T) { + // TestCreateFilter + id := int64(1) + f := &models.Filter{ + Index: &id, + Type: "spoe", + SpoeEngine: "test", + SpoeConfig: "test.cfg", + } + + err := clientTest.CreateFilter(configuration.FrontendParentName, "test", f, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, ondiskF, err := clientTest.GetFilter(1, configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(ondiskF, f) { + fmt.Printf("Created filter: %v\n", ondiskF) + fmt.Printf("Given filter: %v\n", f) + t.Error("Created filter not equal to given filter") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestEditFilter + f = &models.Filter{ + Index: &id, + Type: "spoe", + SpoeConfig: "bla.cfg", + SpoeEngine: "bla", + } + + err = clientTest.EditFilter(1, configuration.FrontendParentName, "test", f, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, ondiskF, err = clientTest.GetFilter(1, configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(ondiskF, f) { + fmt.Printf("Edited filter: %v\n", ondiskF) + fmt.Printf("Given filter: %v\n", f) + t.Error("Edited filter not equal to given filter") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestDeleteFilter + err = clientTest.DeleteFilter(3, "frontend", "test", "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + if v, _ := clientTest.GetVersion(""); v != version { + t.Error("Version not incremented") + } + + _, filters, _ := clientTest.GetFilters(configuration.FrontendParentName, "test", "") + _ = filters + + _, _, err = clientTest.GetFilter(6, "frontend", "test", "") + if err == nil { + t.Error("DeleteFilter failed, filter 5 still exists") + } + + err = clientTest.DeleteFilter(1, configuration.BackendParentName, "test_2", "", version) + if err == nil { + t.Error("Should throw error, non existent filter") + version++ + } +} diff --git a/test/frontend_test.go b/test/frontend_test.go new file mode 100644 index 00000000..423f654f --- /dev/null +++ b/test/frontend_test.go @@ -0,0 +1,297 @@ +// 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. +// + +package test + +import ( + _ "embed" + "fmt" + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" + "github.com/haproxytech/client-native/v5/misc" + "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" +) + +func frontendExpectation() map[string]models.Frontends { + initStructuredExpected() + res := StructuredToFrontendMap() + // Add individual entries + for _, vs := range res { + for _, v := range vs { + key := v.Name + res[key] = models.Frontends{v} + } + } + return res +} + +func TestGetFrontends(t *testing.T) { //nolint:gocognit + m := make(map[string]models.Frontends) + v, frontends, err := clientTest.GetFrontends("") + if err != nil { + t.Error(err.Error()) + } + + if len(frontends) != 2 { + t.Errorf("%v frontends returned, expected 2", len(frontends)) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + m[""] = frontends + + checkFrontends(t, m) +} + +func checkFrontends(t *testing.T, got map[string]models.Frontends) { + exp := frontendExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + +func TestGetFrontend(t *testing.T) { + m := make(map[string]models.Frontends) + + v, f, err := clientTest.GetFrontend("test", "") + if err != nil { + t.Error(err.Error()) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + m["test"] = models.Frontends{f} + checkFrontends(t, m) + + _, err = f.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + _, _, err = clientTest.GetFrontend("doesnotexist", "") + if err == nil { + t.Error("Should throw error, non existent frontend") + } +} + +func TestCreateEditDeleteFrontend(t *testing.T) { + // TestCreateFrontend + mConn := int64(3000) + tOut := int64(2) + clitcpkaCnt := int64(10) + clitcpkaTimeout := int64(10000) + statsRealm := "Haproxy Stats" + f := &models.Frontend{ + From: "unnamed_defaults_1", + Name: "created", + Mode: "tcp", + Maxconn: &mConn, + Httplog: true, + HTTPConnectionMode: "http-keep-alive", + HTTPKeepAliveTimeout: &tOut, + BindProcess: "4", + Logasap: "disabled", + UniqueIDFormat: "%{+X}o_%fi:%fp_%Ts_%rt:%pid", + UniqueIDHeader: "X-Unique-Id", + AcceptInvalidHTTPRequest: "enabled", + DisableH2Upgrade: "enabled", + ClitcpkaCnt: &clitcpkaCnt, + ClitcpkaIdle: &clitcpkaTimeout, + ClitcpkaIntvl: &clitcpkaTimeout, + HTTPIgnoreProbes: "enabled", + HTTPUseProxyHeader: "enabled", + Httpslog: "enabled", + IndependentStreams: "enabled", + Nolinger: "enabled", + Originalto: &models.Originalto{ + Enabled: misc.StringP("enabled"), + Except: "127.0.0.1", + Header: "X-Client-Dst", + }, + SocketStats: "enabled", + TCPSmartAccept: "enabled", + DontlogNormal: "enabled", + HTTPNoDelay: "enabled", + SpliceAuto: "enabled", + SpliceRequest: "enabled", + SpliceResponse: "enabled", + IdleCloseOnResponse: "enabled", + StatsOptions: &models.StatsOptions{ + StatsShowModules: true, + StatsRealm: true, + StatsRealmRealm: &statsRealm, + StatsAuths: []*models.StatsAuth{ + {User: misc.StringP("user1"), Passwd: misc.StringP("pwd1")}, + {User: misc.StringP("user2"), Passwd: misc.StringP("pwd2")}, + }, + }, + Enabled: true, + } + + err := clientTest.CreateFrontend(f, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, frontend, err := clientTest.GetFrontend("created", "") + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(frontend, f) { + fmt.Printf("Created frontend: %v\n", frontend) + fmt.Printf("Given frontend: %v\n", f) + t.Error("Created frontend not equal to given frontend") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + err = clientTest.CreateFrontend(f, "", version) + if err == nil { + t.Error("Should throw error frontend already exists") + version++ + } + + // TestEditFrontend + mConn = int64(4000) + f = &models.Frontend{ + Name: "created", + Mode: "tcp", + Maxconn: &mConn, + Backlog: misc.Int64P(1024), + Clflog: true, + HTTPConnectionMode: "httpclose", + BindProcess: "3", + MonitorURI: "/healthz", + MonitorFail: &models.MonitorFail{ + Cond: misc.StringP("if"), + CondTest: misc.StringP("site_is_dead"), + }, + Compression: &models.Compression{ + Offload: true, + }, + ClitcpkaCnt: &clitcpkaCnt, + ClitcpkaIdle: &clitcpkaTimeout, + ClitcpkaIntvl: &clitcpkaTimeout, + HTTPIgnoreProbes: "disabled", + HTTPUseProxyHeader: "disabled", + Httpslog: "disabled", + IndependentStreams: "disabled", + Nolinger: "disabled", + Originalto: &models.Originalto{ + Enabled: misc.StringP("enabled"), + Except: "127.0.0.1", + Header: "X-Client-Dst", + }, + SocketStats: "disabled", + TCPSmartAccept: "disabled", + DontlogNormal: "disabled", + HTTPNoDelay: "disabled", + SpliceAuto: "disabled", + SpliceRequest: "disabled", + SpliceResponse: "disabled", + IdleCloseOnResponse: "disabled", + StatsOptions: &models.StatsOptions{ + StatsShowModules: true, + StatsRealm: true, + StatsRealmRealm: &statsRealm, + StatsAuths: []*models.StatsAuth{ + {User: misc.StringP("new_user1"), Passwd: misc.StringP("new_pwd1")}, + {User: misc.StringP("new_user2"), Passwd: misc.StringP("new_pwd2")}, + }, + }, + EmailAlert: &models.EmailAlert{ + From: misc.StringP("srv01@example.com"), + To: misc.StringP("problems@example.com"), + Level: "warning", + Mailers: misc.StringP("localmailer1"), + }, + } + + err = clientTest.EditFrontend("created", f, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, frontend, err = clientTest.GetFrontend("created", "") + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(frontend, f) { + fmt.Printf("Edited frontend: %v\n", frontend) + fmt.Printf("Given frontend: %v\n", f) + t.Error("Edited frontend not equal to given frontend") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestDeleteFrontend + err = clientTest.DeleteFrontend("created", "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + if v, _ := clientTest.GetVersion(""); v != version { + t.Error("Version not incremented") + } + + err = clientTest.DeleteFrontend("created", "", 999999) + if err != nil { + if confErr, ok := err.(*configuration.ConfError); ok { + if !confErr.Is(configuration.ErrVersionMismatch) { + t.Error("Should throw configuration.ErrVersionMismatch error") + } + } else { + t.Error("Should throw configuration.ErrVersionMismatch error") + } + } + _, _, err = clientTest.GetFrontend("created", "") + if err == nil { + t.Error("DeleteFrontend failed, frontend test still exists") + } + + err = clientTest.DeleteFrontend("doesnotexist", "", version) + if err == nil { + t.Error("Should throw error, non existent frontend") + version++ + } +} diff --git a/test/global_test.go b/test/global_test.go new file mode 100644 index 00000000..223f568c --- /dev/null +++ b/test/global_test.go @@ -0,0 +1,190 @@ +// 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. +// + +package test + +import ( + _ "embed" + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/misc" + "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" +) + +func globalExpcectation() *models.Global { + initStructuredExpected() + res := StructuredToGlobalMap() + return &res +} + +func TestGetGlobal(t *testing.T) { + v, global, err := clientTest.GetGlobalConfiguration("") + if err != nil { + t.Error(err.Error()) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + checkGlobal(t, global) +} + +func checkGlobal(t *testing.T, global *models.Global) { + want := globalExpcectation() + require.True(t, global.Equal(*want), "diff %v", cmp.Diff(*global, *want)) +} + +func TestPutGlobal(t *testing.T) { + tOut := int64(3600) + n := "1/1" + v := "0" + a := "/var/run/haproxy.sock" + f := "/etc/foo.lua" + luaPrependPath := "/usr/share/haproxy-lua/?/init.lua" + enabled := "enabled" + g := &models.Global{ + Daemon: "enabled", + CPUMaps: []*models.CPUMap{ + { + Process: &n, + CPUSet: &v, + }, + }, + RuntimeAPIs: []*models.RuntimeAPI{ + { + Address: &a, + BindParams: models.BindParams{ + Level: "admin", + }, + }, + }, + Maxconn: 1000, + SslDefaultBindCiphers: "test", + SslDefaultBindOptions: "ssl-min-ver TLSv1.0 no-tls-tickets", + SslDefaultServerCurves: "secp384r1", + StatsTimeout: &tOut, + TuneSslDefaultDhParam: 1024, + ExternalCheck: false, + LuaPrependPath: []*models.LuaPrependPath{ + { + Path: &luaPrependPath, + Type: "cpath", + }, + }, + LuaLoads: []*models.LuaLoad{ + { + File: &f, + }, + }, + LogSendHostname: &models.GlobalLogSendHostname{ + Enabled: &enabled, + Param: "something", + }, + TuneOptions: &models.GlobalTuneOptions{ + DisableZeroCopyForwarding: true, + EventsMaxEventsAtOnce: 50, + H1ZeroCopyFwdRecv: "disabled", + H1ZeroCopyFwdSend: "disabled", + H2ZeroCopyFwdSend: "disabled", + LuaLogLoggers: "disabled", + LuaLogStderr: "disabled", + MaxChecksPerThread: misc.Int64P(20), + PeersMaxUpdatesAtOnce: 100, + PtZeroCopyForwarding: "disabled", + QuicFrontendConnTxBuffersLimit: nil, + QuicFrontendMaxIdleTimeout: misc.Int64P(5000), + QuicSocketOwner: "listener", + RcvbufBackend: misc.Int64P(8192), + RcvbufFrontend: misc.Int64P(4096), + SndbufBackend: misc.Int64P(1234), + SndbufFrontend: misc.Int64P(5678), + SslOcspUpdateMaxDelay: misc.Int64P(48), + SslOcspUpdateMinDelay: misc.Int64P(49), + StickCounters: misc.Int64P(50), + }, + HttpclientResolversDisabled: "disabled", + HttpclientResolversPrefer: "ipv6", + HttpclientResolversID: "my2", + HttpclientRetries: 5, + HttpclientSslCaFile: "my_ca_file.ca", + HttpclientTimeoutConnect: misc.Int64P(5000), + HttpclientSslVerify: misc.StringP(""), + UID: 1234, + WurflOptions: &models.GlobalWurflOptions{}, + DeviceAtlasOptions: &models.GlobalDeviceAtlasOptions{}, + FiftyOneDegreesOptions: &models.GlobalFiftyOneDegreesOptions{}, + StatsMaxconn: misc.Int64P(30), + Anonkey: misc.Int64P(40), + NumaCPUMapping: "disabled", + DefaultPath: &models.GlobalDefaultPath{ + Type: "origin", + Path: "/some/other/path", + }, + NoQuic: false, + ClusterSecret: "", + SslDefaultServerSigalgs: "ECDSA+SHA256", + SslDefaultServerClientSigalgs: "ECDSA+SHA256", + SslPropquery: "foo", + SslProvider: "my_provider", + SslProviderPath: "providers/", + Setcap: "none", + LimitedQuic: true, + } + + err := clientTest.PushGlobalConfiguration(g, "", version) + + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + ver, global, err := clientTest.GetGlobalConfiguration("") + if err != nil { + t.Error(err.Error()) + } + + var givenJSON []byte + givenJSON, err = g.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + var onDiskJSON []byte + onDiskJSON, err = global.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + if string(givenJSON) != string(onDiskJSON) { + fmt.Printf("Created global: %v\n", string(onDiskJSON)) + fmt.Printf("Given global: %v\n", string(givenJSON)) + t.Error("Created global not equal to given global") + } + + if ver != version { + t.Error("Version not incremented!") + } + + err = clientTest.PushGlobalConfiguration(g, "", 55) + + if err == nil { + t.Error("Should have returned version conflict.") + } +} diff --git a/configuration/group_test.go b/test/group_test.go similarity index 81% rename from configuration/group_test.go rename to test/group_test.go index b53f5b77..511ef5e4 100644 --- a/configuration/group_test.go +++ b/test/group_test.go @@ -13,17 +13,34 @@ // limitations under the License. // -package configuration +package test import ( - "io/ioutil" + _ "embed" + "fmt" + "os" "testing" + "github.com/google/go-cmp/cmp" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func groupExpectation() map[string]models.Groups { + initStructuredExpected() + res := StructuredToGroupMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%s", k, v.Name) + res[key] = models.Groups{v} + } + } + return res +} + func generateGroupConfig(config string) (string, error) { - f, err := ioutil.TempFile("/tmp", "group") + f, err := os.CreateTemp("/tmp", "group") if err != nil { return "", err } @@ -95,6 +112,8 @@ userlist delete_test } for _, tt := range tests { + m := make(map[string]models.Groups) + t.Run(tt.name, func(t *testing.T) { c, err := prepareClient(tt.configurationFile) if (err != nil) != tt.wantErr { @@ -110,9 +129,7 @@ userlist delete_test if groups == nil { t.Errorf("No groups configurations found in userlist, expected 2") } - if len(groups) != 2 { - t.Errorf("Expected 2 groups in the userlist, found %v", len(groups)) - } + m["userlist/first"] = groups _, groups, err = c.GetGroups("second", "") if err != nil { @@ -121,9 +138,7 @@ userlist delete_test if groups == nil { t.Errorf("No groups configurations found in userlist, expected 3") } - if len(groups) != 3 { - t.Errorf("Expected 3 groups in the userlist, found %v", len(groups)) - } + m["userlist/second"] = groups _, groups, err = c.GetGroups("empty", "") if err != nil { @@ -143,8 +158,10 @@ userlist delete_test if groups != nil { t.Errorf("Group found in userlist, expected 0") } + checkGroups(t, m) // fetch test, single group - userlist first + clear(m) _, group, err := c.GetGroup("G1", "first", "") if err != nil { t.Error(err.Error()) @@ -152,12 +169,7 @@ userlist delete_test if group == nil { t.Errorf("Expected a group instead of nil") } - if group.Name != "G1" { - t.Errorf("Name %v returned, expected %v", group.Name, "G1") - } - if group.Users != "tiger,scott" { - t.Errorf("Users %v returned, expected %v", group.Users, "tiger,scott") - } + m["userlist/first/G1"] = models.Groups{group} _, group, err = c.GetGroup("G2", "first", "") if err != nil { @@ -166,12 +178,7 @@ userlist delete_test if group == nil { t.Errorf("Expected a group instead of nil") } - if group.Name != "G2" { - t.Errorf("Name %v returned, expected %v", group.Name, "G2") - } - if group.Users != "scott" { - t.Errorf("Users %v returned, expected %v", group.Users, "scott") - } + m["userlist/first/G2"] = models.Groups{group} _, group, err = c.GetGroup("G3", "first", "") if group != nil { @@ -191,12 +198,7 @@ userlist delete_test if group == nil { t.Errorf("Expected a group instead of nil") } - if group.Name != "one" { - t.Errorf("Name %v returned, expected %v", group.Name, "one") - } - if group.Users != "" { - t.Errorf("Users %v returned, expected %v", group.Users, "") - } + m["userlist/second/one"] = models.Groups{group} _, group, err = c.GetGroup("two", "second", "") if err != nil { @@ -205,12 +207,7 @@ userlist delete_test if group == nil { t.Errorf("Expected a group instead of nil") } - if group.Name != "two" { - t.Errorf("Name %v returned, expected %v", group.Name, "two") - } - if group.Users != "" { - t.Errorf("Users %v returned, expected %v", group.Users, "") - } + m["userlist/second/two"] = models.Groups{group} _, group, err = c.GetGroup("three", "second", "") if err != nil { @@ -219,12 +216,7 @@ userlist delete_test if group == nil { t.Errorf("Expected a group instead of nil") } - if group.Name != "three" { - t.Errorf("Name %v returned, expected %v", group.Name, "three") - } - if group.Users != "" { - t.Errorf("Users %v returned, expected %v", group.Users, "") - } + m["userlist/second/three"] = models.Groups{group} _, group, err = c.GetGroup("four", "second", "") if group != nil { @@ -244,6 +236,8 @@ userlist delete_test t.Errorf("Expected 0 groups in the userlist, found %v", len(groups)) } + checkGroups(t, m) + // test add add := models.Group{ Name: "avengers", @@ -272,3 +266,20 @@ userlist delete_test }) } } + +func checkGroups(t *testing.T, got map[string]models.Groups) { + exp := groupExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} diff --git a/configuration/helpers.go b/test/helpers.go similarity index 96% rename from configuration/helpers.go rename to test/helpers.go index ab15e42f..64aad2b5 100644 --- a/configuration/helpers.go +++ b/test/helpers.go @@ -13,7 +13,7 @@ // limitations under the License. // -package configuration +package test type Counter struct { count int64 diff --git a/test/http_after_response_rule_test.go b/test/http_after_response_rule_test.go new file mode 100644 index 00000000..2b5ab553 --- /dev/null +++ b/test/http_after_response_rule_test.go @@ -0,0 +1,130 @@ +// 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. +// + +package test + +import ( + _ "embed" + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" + "github.com/haproxytech/client-native/v5/misc" + "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" +) + +func hTTPAfterResponseRuleExpectation() map[string]models.HTTPAfterResponseRules { + initStructuredExpected() + res := StructuredToHTTPAfterResponseRuleMap() + return res +} + +func TestGetHTTPAfterResponseRules(t *testing.T) { + mrules := make(map[string]models.HTTPAfterResponseRules) + v, hRules, err := clientTest.GetHTTPAfterResponseRules(configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + mrules["frontend/test"] = hRules + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + _, hRules, err = clientTest.GetHTTPAfterResponseRules(configuration.BackendParentName, "test_2", "") + if err != nil { + t.Error(err.Error()) + } + mrules["backend/test_2"] = hRules + + checkHTTPAfterResponseRules(t, mrules) +} + +func checkHTTPAfterResponseRules(t *testing.T, got map[string]models.HTTPAfterResponseRules) { + exp := hTTPAfterResponseRuleExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + +func TestCreateHTTPAfterResponseRule(t *testing.T) { + v, err := clientTest.GetVersion("") + if err != nil { + t.Error(err.Error()) + } + + tx, err := clientTest.StartTransaction(v) + if err != nil { + t.Error(err.Error()) + } + + har := &models.HTTPAfterResponseRule{ + Index: misc.Int64P(0), + StrictMode: "on", + Type: "strict-mode", + } + if err = clientTest.CreateHTTPAfterResponseRule(configuration.BackendParentName, "test", har, tx.ID, 0); err != nil { + t.Error(err.Error()) + } + + _, found, err := clientTest.GetHTTPAfterResponseRule(0, configuration.BackendParentName, "test", tx.ID) + if err != nil { + t.Error(err.Error()) + } + + if expected, got := har.Type, found.Type; expected != got { + t.Error(fmt.Errorf("expected type %s, got %s", expected, got)) + } + + if expected, got := har.StrictMode, found.StrictMode; expected != got { + t.Error(fmt.Errorf("expected strict-mode %s, got %s", expected, got)) + } +} + +func TestDeleteHTTPAfterResponseRule(t *testing.T) { + v, err := clientTest.GetVersion("") + if err != nil { + t.Error(err.Error()) + } + + tx, err := clientTest.StartTransaction(v) + if err != nil { + t.Error(err.Error()) + } + + _, hRules, err := clientTest.GetHTTPAfterResponseRules(configuration.FrontendParentName, "test", tx.ID) + if err != nil { + t.Error(err.Error()) + } + + for range hRules { + if err = clientTest.DeleteHTTPAfterResponseRule(int64(0), configuration.FrontendParentName, "test", tx.ID, 0); err != nil { + t.Error(err.Error()) + } + } +} diff --git a/test/http_check_test.go b/test/http_check_test.go new file mode 100644 index 00000000..92ec2a56 --- /dev/null +++ b/test/http_check_test.go @@ -0,0 +1,238 @@ +// Copyright 2022 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 test + +import ( + _ "embed" + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" + "github.com/haproxytech/client-native/v5/misc" + "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" +) + +func hTTPCheckExpectation() map[string]models.HTTPChecks { + initStructuredExpected() + res := StructuredToHTTPCheckMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%d", k, *v.Index) + res[key] = models.HTTPChecks{v} + } + } + return res +} + +func TestGetHTTPChecks(t *testing.T) { //nolint:gocognit,gocyclo + mchecks := make(map[string]models.HTTPChecks) + + v, checks, err := clientTest.GetHTTPChecks(configuration.BackendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if len(checks) != 14 { + t.Errorf("%v http checks returned, expected 14", len(checks)) + } + mchecks["backend/test"] = checks + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + _, checks, err = clientTest.GetHTTPChecks(configuration.DefaultsParentName, "", "") + if err != nil { + t.Error(err.Error()) + } + mchecks[configuration.DefaultsParentName] = checks + + _, checks, err = clientTest.GetHTTPChecks(configuration.BackendParentName, "test_2", "") + if err != nil { + t.Error(err.Error()) + } + mchecks["backend/test_2"] = checks + + checkHttpChecks(t, mchecks) +} + +func checkHttpChecks(t *testing.T, got map[string]models.HTTPChecks) { + exp := hTTPCheckExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + +func TestGetHTTPCheck(t *testing.T) { + m := make(map[string]models.HTTPChecks) + v, check, err := clientTest.GetHTTPCheck(0, configuration.BackendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + m["backend/test/0"] = models.HTTPChecks{check} + + _, err = check.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + _, _, err = clientTest.GetHTTPCheck(3, configuration.BackendParentName, "test_2", "") + if err == nil { + t.Error("Should throw error, non existent HTTP Request Rule") + } + + _, check, err = clientTest.GetHTTPCheck(0, configuration.DefaultsParentName, "", "") + if err != nil { + t.Error(err.Error()) + } + m[configuration.DefaultsParentName+"/0"] = models.HTTPChecks{check} + checkHttpChecks(t, m) +} + +func TestCreateEditDeleteHTTPCheck(t *testing.T) { + id := int64(1) + + // TestCreateHTTPCheck + r := &models.HTTPCheck{ + Index: &id, + Type: "send", + Method: "GET", + Version: "HTTP/1.1", + URI: "/", + CheckHeaders: []*models.ReturnHeader{}, + } + + err := clientTest.CreateHTTPCheck(configuration.BackendParentName, "test", r, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, ondiskR, err := clientTest.GetHTTPCheck(1, configuration.BackendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + var givenJSONB []byte + givenJSONB, err = r.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + var ondiskJSONB []byte + ondiskJSONB, err = ondiskR.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + if string(givenJSONB) != string(ondiskJSONB) { + fmt.Printf("Created HTTP check: %v\n", string(ondiskJSONB)) + fmt.Printf("Given HTTP check: %v\n", string(givenJSONB)) + t.Error("Created HTTP check not equal to given HTTP check") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestEditHTTPRequestRule + r = &models.HTTPCheck{ + Index: &id, + Type: "send", + Method: "GET", + Version: "HTTP/1.1", + URI: "/", + CheckHeaders: []*models.ReturnHeader{ + { + Name: misc.StringP("Host"), + Fmt: misc.StringP("google.com"), + }, + }, + } + + err = clientTest.EditHTTPCheck(1, configuration.BackendParentName, "test", r, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, ondiskR, err = clientTest.GetHTTPCheck(1, configuration.BackendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + givenJSONB, err = r.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + ondiskJSONB, err = ondiskR.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + if string(givenJSONB) != string(ondiskJSONB) { + fmt.Printf("Created HTTP check: %v\n", string(ondiskJSONB)) + fmt.Printf("Given HTTP check: %v\n", string(givenJSONB)) + t.Error("Created HTTP check not equal to given HTTP check") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestDeleteHTTPRequest + err = clientTest.DeleteHTTPCheck(14, configuration.BackendParentName, "test", "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + if v, _ := clientTest.GetVersion(""); v != version { + t.Error("Version not incremented") + } + + _, _, err = clientTest.GetHTTPCheck(14, configuration.BackendParentName, "test", "") + if err == nil { + t.Error("DeleteHTTPCheck failed, HTTP check 13 still exists") + } + + err = clientTest.DeleteHTTPCheck(5, configuration.BackendParentName, "test_2", "", version) + if err == nil { + t.Error("Should throw error, non existent HTTP Check") + version++ + } +} diff --git a/test/http_error_rule_test.go b/test/http_error_rule_test.go new file mode 100644 index 00000000..29be422d --- /dev/null +++ b/test/http_error_rule_test.go @@ -0,0 +1,251 @@ +// Copyright 2022 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 test + +import ( + _ "embed" + "fmt" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" + "github.com/haproxytech/client-native/v5/misc" + "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" +) + +func hTTPErrorRulesExpectation() map[string]models.HTTPErrorRules { + initStructuredExpected() + res := StructuredToHTTPErrorRuleMap() + return res +} + +func TestGetHTTPErrorRules(t *testing.T) { //nolint:gocognit,gocyclo + mr := make(map[string]models.HTTPErrorRules) + + v, checks, err := clientTest.GetHTTPErrorRules(configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + if len(checks) != 1 { + t.Errorf("%v http-error rules returned, expected 1", len(checks)) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + mr["frontend/test"] = checks + + _, checks, err = clientTest.GetHTTPErrorRules(configuration.DefaultsParentName, "", "") + if err != nil { + t.Error(err.Error()) + } + mr[configuration.DefaultsParentName] = checks + + _, checks, err = clientTest.GetHTTPErrorRules(configuration.BackendParentName, "test_2", "") + if err != nil { + t.Error(err.Error()) + } + mr["backend/test_2"] = checks + + checkErrorRules(t, mr) +} + +func checkErrorRules(t *testing.T, got map[string]models.HTTPErrorRules) { + exp := hTTPErrorRulesExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + +func TestGetHTTPErrorRule(t *testing.T) { + v, check, err := clientTest.GetHTTPErrorRule(0, configuration.BackendParentName, "test_2", "") + if err != nil { + t.Error(err.Error()) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + if *check.Index != 0 { + t.Errorf("http-error rule index not 0: %v", *check.Index) + } + if check.Type != "status" { + t.Errorf("%v: Action not status: %v", *check.Index, check.Type) + } + if check.Status != 200 { + t.Errorf("%v: Status not 200: %v", *check.Index, check.Type) + } + _, err = check.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + _, _, err = clientTest.GetHTTPErrorRule(3, configuration.BackendParentName, "test", "") + if err == nil { + t.Error("no http-error rules in backend section named test - expected an error") + } + + _, check, err = clientTest.GetHTTPErrorRule(1, configuration.DefaultsParentName, "", "") + if err != nil { + t.Error(err.Error()) + } + if *check.Index != 1 { + t.Errorf("http-error rule index not 1: %v", *check.Index) + } + if check.Type != "status" { + t.Errorf("%v: Action not status: %v", *check.Index, check.Type) + } + if check.Status != 429 { + t.Errorf("%v: Status not 429: %v", *check.Index, check.Type) + } +} + +func TestCreateEditDeleteHTTPErrorRule(t *testing.T) { + id := int64(1) + r := &models.HTTPErrorRule{ + Index: &id, + Type: "status", + Status: 429, + ReturnContentType: misc.StringP("application/json"), + ReturnContentFormat: "file", + ReturnContent: "/test/429", + ReturnHeaders: []*models.ReturnHeader{ + { + Name: misc.StringP("Some-Header"), + Fmt: misc.StringP("value"), + }, + }, + } + + // TestCreateHTTPErrorRule + err := clientTest.CreateHTTPErrorRule(configuration.BackendParentName, "test_2", r, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, ondiskR, err := clientTest.GetHTTPErrorRule(1, configuration.BackendParentName, "test_2", "") + if err != nil { + t.Error(err.Error()) + } + + var givenJSONB []byte + givenJSONB, err = r.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + var ondiskJSONB []byte + ondiskJSONB, err = ondiskR.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + if string(givenJSONB) != string(ondiskJSONB) { + fmt.Printf("Created HTTP error rule: %v\n", string(ondiskJSONB)) + fmt.Printf("Given HTTP error rule: %v\n", string(givenJSONB)) + t.Error("Created HTTP error rule not equal to given HTTP error rule") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestEditHTTPErrorRule + err = clientTest.EditHTTPErrorRule(1, configuration.BackendParentName, "test_2", r, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, ondiskR, err = clientTest.GetHTTPErrorRule(1, configuration.BackendParentName, "test_2", "") + if err != nil { + t.Error(err.Error()) + } + + givenJSONB, err = r.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + ondiskJSONB, err = ondiskR.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + if string(givenJSONB) != string(ondiskJSONB) { + fmt.Printf("Created HTTP error rule: %v\n", string(ondiskJSONB)) + fmt.Printf("Given HTTP error rule: %v\n", string(givenJSONB)) + t.Error("Created HTTP error rule not equal to given HTTP error rule") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestDeleteHTTPErrorRule + err = clientTest.DeleteHTTPErrorRule(0, configuration.FrontendParentName, "test", "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + if v, _ := clientTest.GetVersion(""); v != version { + t.Error("Version not incremented") + } + + _, _, err = clientTest.GetHTTPErrorRule(0, configuration.FrontendParentName, "test", "") + if err == nil { + t.Error("deleting http-error rule failed - http-error rule 0 still exists") + } + + err = clientTest.DeleteHTTPErrorRule(1, configuration.DefaultsParentName, "", "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + if v, _ := clientTest.GetVersion(""); v != version { + t.Error("Version not incremented") + } + + _, _, err = clientTest.GetHTTPErrorRule(1, configuration.DefaultsParentName, "", "") + if err == nil { + t.Error("deleting http-error rule failed - http-error rule 1 still exists") + } + + err = clientTest.DeleteHTTPErrorRule(3, configuration.BackendParentName, "test_2", "", version) + if err == nil { + t.Error("deleting http-error rule that does not exist - expected an error") + version++ + } +} diff --git a/configuration/http_errors_section_test.go b/test/http_errors_section_test.go similarity index 84% rename from configuration/http_errors_section_test.go rename to test/http_errors_section_test.go index 2cf3524d..a6bc31ec 100644 --- a/configuration/http_errors_section_test.go +++ b/test/http_errors_section_test.go @@ -12,37 +12,39 @@ // See the License for the specific language governing permissions and // limitations under the License. -package configuration +package test import ( + _ "embed" "testing" + "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/haproxytech/client-native/v5/models" ) +func httpErrorSectionExpectation() map[string]models.HTTPErrorsSections { + initStructuredExpected() + res := StructuredToHTTPErrorSectionMap() + // Add individual entries + for _, vs := range res { + for _, v := range vs { + key := v.Name + res[key] = models.HTTPErrorsSections{v} + } + } + return res +} + var testDataHTTPErrors map[string]models.HTTPErrorsSection func init() { + exp := httpErrorSectionExpectation() testDataHTTPErrors = map[string]models.HTTPErrorsSection{ - "website-1": { - Name: "website-1", - ErrorFiles: []*models.Errorfile{ - {Code: 400, File: "/etc/haproxy/errorfiles/site1/400.http"}, - {Code: 404, File: "/etc/haproxy/errorfiles/site1/404.http"}, - {Code: 408, File: "/dev/null"}, - }, - }, - "website-2": { - Name: "website-2", - ErrorFiles: []*models.Errorfile{ - {Code: 400, File: "/etc/haproxy/errorfiles/site2/400.http"}, - {Code: 404, File: "/etc/haproxy/errorfiles/site2/404.http"}, - {Code: 501, File: "/etc/haproxy/errorfiles/site2/501.http"}, - }, - }, + "website-1": *exp["website-1"][0], + "website-2": *exp["website-2"][0], "new": { Name: "website-3", ErrorFiles: []*models.Errorfile{ @@ -89,39 +91,45 @@ func init() { } func TestGetHTTPErrorsSections(t *testing.T) { + m := make(map[string]models.HTTPErrorsSections) v, sections, err := clientTest.GetHTTPErrorsSections("") require.NoError(t, err) require.Len(t, sections, 2) require.Equal(t, version, v) + m[""] = sections - for _, section := range sections { - switch section.Name { - case "website-1": - assert.Equal(t, - testDataHTTPErrors["website-1"].ErrorFiles, - section.ErrorFiles, - "section entries should match") - case "website-2": - assert.Equal(t, - testDataHTTPErrors["website-2"].ErrorFiles, - section.ErrorFiles, - "section entries should match") - default: - t.Errorf("retrieved unexpected section with name '%s'", section.Name) + checkHTTPErrorSection(t, m) +} + +func checkHTTPErrorSection(t *testing.T, got map[string]models.HTTPErrorsSections) { + exp := httpErrorSectionExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } } } } func TestGetHTTPErrorsSection(t *testing.T) { + m := make(map[string]models.HTTPErrorsSections) + // Test a successful operation. v, section, err := clientTest.GetHTTPErrorsSection("website-2", "") require.NoError(t, err) require.NotNil(t, section) require.Equal(t, version, v) + m["website-2"] = models.HTTPErrorsSections{section} - assert.Equal(t, testDataHTTPErrors["website-2"], *section, "retrieved section should match test data") - + checkHTTPErrorSection(t, m) // Test expected failures. _, _, err = clientTest.GetHTTPErrorsSection(testDataHTTPErrors["not-there"].Name, "") assert.Error(t, err, "attempt to retrieve a section that does not exist should fail") diff --git a/test/http_request_rule_test.go b/test/http_request_rule_test.go new file mode 100644 index 00000000..ac0e56e8 --- /dev/null +++ b/test/http_request_rule_test.go @@ -0,0 +1,276 @@ +// 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. +// + +package test + +import ( + _ "embed" + "fmt" + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" + "github.com/haproxytech/client-native/v5/misc" + "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" +) + +func hTTPRequestRuleExpectation() map[string]models.HTTPRequestRules { + initStructuredExpected() + res := StructuredToHTTPRequestRuleMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%d", k, *v.Index) + res[key] = models.HTTPRequestRules{v} + } + } + return res +} + +func TestGetHTTPRequestRules(t *testing.T) { //nolint:gocognit,gocyclo + mrules := make(map[string]models.HTTPRequestRules) + v, hRules, err := clientTest.GetHTTPRequestRules(configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + mrules["frontend/test"] = hRules + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + _, hRules, err = clientTest.GetHTTPRequestRules(configuration.BackendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + mrules["backend/test"] = hRules + + _, hRules, err = clientTest.GetHTTPRequestRules(configuration.BackendParentName, "test_2", "") + if err != nil { + t.Error(err.Error()) + } + mrules["backend/test_2"] = hRules + + checkHTTPRequestRules(t, mrules) +} + +func checkHTTPRequestRules(t *testing.T, got map[string]models.HTTPRequestRules) { + exp := hTTPRequestRuleExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + +func TestGetHTTPRequestRule(t *testing.T) { + m := make(map[string]models.HTTPRequestRules) + v, r, err := clientTest.GetHTTPRequestRule(0, configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + m["frontend/test/0"] = models.HTTPRequestRules{r} + + _, err = r.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + _, _, err = clientTest.GetHTTPRequestRule(3, configuration.BackendParentName, "test_2", "") + if err == nil { + t.Error("Should throw error, non existent HTTP Request Rule") + } + + _, r, err = clientTest.GetHTTPRequestRule(0, configuration.FrontendParentName, "test_2", "") + if err != nil { + t.Error("Should throw error, non existent HTTP Request Rule") + } + m["frontend/test_2/0"] = models.HTTPRequestRules{r} + + _, r, err = clientTest.GetHTTPRequestRule(1, configuration.FrontendParentName, "test_2", "") + if err != nil { + t.Error("Should throw error, non existent HTTP Request Rule") + } + m["frontend/test_2/1"] = models.HTTPRequestRules{r} + + checkHTTPRequestRules(t, m) +} + +func TestCreateEditDeleteHTTPRequestRule(t *testing.T) { + id := int64(1) + + // TestCreateHTTPRequestRule + var redirCode int64 = 301 + r := &models.HTTPRequestRule{ + Index: &id, + Type: "redirect", + RedirCode: &redirCode, + RedirValue: "http://www.%[hdr(host)]%[capture.req.uri]", + RedirType: "location", + } + + err := clientTest.CreateHTTPRequestRule(configuration.FrontendParentName, "test", r, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, ondiskR, err := clientTest.GetHTTPRequestRule(1, configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(ondiskR, r) { + fmt.Printf("Created HTTP request rule: %v\n", ondiskR) + fmt.Printf("Given HTTP request rule: %v\n", r) + t.Error("Created HTTP request rule not equal to given HTTP request rule") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestEditHTTPRequestRule + r = &models.HTTPRequestRule{ + Index: &id, + Type: "redirect", + RedirCode: &redirCode, + RedirValue: "http://www1.%[hdr(host)]%[capture.req.uri]", + RedirType: "scheme", + } + + err = clientTest.EditHTTPRequestRule(1, configuration.FrontendParentName, "test", r, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, ondiskR, err = clientTest.GetHTTPRequestRule(1, configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(ondiskR, r) { + fmt.Printf("Edited HTTP request rule: %v\n", ondiskR) + fmt.Printf("Given HTTP request rule: %v\n", r) + t.Error("Edited HTTP request rule not equal to given HTTP request rule") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestDeleteHTTPRequest + err = clientTest.DeleteHTTPRequestRule(47, configuration.FrontendParentName, "test", "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + if v, _ := clientTest.GetVersion(""); v != version { + t.Error("Version not incremented") + } + + _, _, err = clientTest.GetHTTPRequestRule(47, "frontend", "test", "") + if err == nil { + t.Error("DeleteHTTPRequestRule failed, HTTP Request Rule 47 still exists") + } + + err = clientTest.DeleteHTTPRequestRule(2, configuration.BackendParentName, "test_2", "", version) + if err == nil { + t.Error("Should throw error, non existent HTTP Request Rule") + version++ + } +} + +func TestSerializeHTTPRequestRule(t *testing.T) { + testCases := []struct { + input models.HTTPRequestRule + expectedResult string + }{ + { + input: models.HTTPRequestRule{ + Type: models.HTTPRequestRuleTypeTrackDashSc, + Cond: "if", + CondTest: "TRUE", + TrackScKey: "src", + TrackScTable: "tr0", + TrackScStickCounter: misc.Int64P(3), + }, + expectedResult: "track-sc3 src table tr0 if TRUE", + }, + { + input: models.HTTPRequestRule{ + Type: models.HTTPRequestRuleTypeTrackDashSc0, + Cond: "if", + CondTest: "TRUE", + TrackSc0Key: "src", + TrackSc0Table: "tr0", + }, + expectedResult: "track-sc0 src table tr0 if TRUE", + }, + { + input: models.HTTPRequestRule{ + Type: models.HTTPRequestRuleTypeTrackDashSc1, + Cond: "if", + CondTest: "TRUE", + TrackSc1Key: "src", + TrackSc1Table: "tr1", + }, + expectedResult: "track-sc1 src table tr1 if TRUE", + }, + { + input: models.HTTPRequestRule{ + Type: models.HTTPRequestRuleTypeTrackDashSc2, + Cond: "if", + CondTest: "TRUE", + TrackSc2Key: "src", + TrackSc2Table: "tr2", + }, + expectedResult: "track-sc2 src table tr2 if TRUE", + }, + } + + for _, testCase := range testCases { + t.Run(testCase.expectedResult, func(t *testing.T) { + tcpType, err := configuration.SerializeHTTPRequestRule(testCase.input) + if err != nil { + t.Error(err.Error()) + } + + actual := tcpType.String() + if actual != testCase.expectedResult { + t.Errorf("Expected %q, got: %q", testCase.expectedResult, actual) + } + }) + } +} diff --git a/test/http_response_rule_test.go b/test/http_response_rule_test.go new file mode 100644 index 00000000..59505505 --- /dev/null +++ b/test/http_response_rule_test.go @@ -0,0 +1,258 @@ +// 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. +// + +package test + +import ( + _ "embed" + "fmt" + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" + "github.com/haproxytech/client-native/v5/misc" + "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" +) + +func hTTPResponseRuleExpectation() map[string]models.HTTPResponseRules { + initStructuredExpected() + res := StructuredToHTTPResponseRuleMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%d", k, *v.Index) + res[key] = models.HTTPResponseRules{v} + } + } + return res +} + +func TestGetHTTPResponseRules(t *testing.T) { //nolint:gocognit,gocyclo + mrules := make(map[string]models.HTTPResponseRules) + v, hRules, err := clientTest.GetHTTPResponseRules(configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + mrules["frontend/test"] = hRules + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + _, hRules, err = clientTest.GetHTTPResponseRules(configuration.BackendParentName, "test_2", "") + if err != nil { + t.Error(err.Error()) + } + mrules["backend/test_2"] = hRules + + checkHTTPResponseRules(t, mrules) +} + +func checkHTTPResponseRules(t *testing.T, got map[string]models.HTTPResponseRules) { + exp := hTTPResponseRuleExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + +func TestGetHTTPResponseRule(t *testing.T) { + m := make(map[string]models.HTTPResponseRules) + v, r, err := clientTest.GetHTTPResponseRule(0, configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + m["frontend/test/0"] = models.HTTPResponseRules{r} + + _, err = r.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + _, _, err = clientTest.GetHTTPResponseRule(3, configuration.BackendParentName, "test2", "") + if err == nil { + t.Error("Should throw error, non existent HTTPResponse Rule") + } + + _, r, err = clientTest.GetHTTPResponseRule(0, configuration.FrontendParentName, "test_2", "") + if err != nil { + t.Error(err.Error()) + } + m["frontend/test_2/0"] = models.HTTPResponseRules{r} + + checkHTTPResponseRules(t, m) +} + +func TestCreateEditDeleteHTTPResponseRule(t *testing.T) { + id := int64(1) + // TestCreateHTTPResponseRule + r := &models.HTTPResponseRule{ + Index: &id, + Type: "set-log-level", + LogLevel: "alert", + } + + err := clientTest.CreateHTTPResponseRule(configuration.FrontendParentName, "test", r, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, ondiskR, err := clientTest.GetHTTPResponseRule(1, configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(ondiskR, r) { + fmt.Printf("Created HTTP response rule: %v\n", ondiskR) + fmt.Printf("Given HTTP response rule: %v\n", r) + t.Error("Created HTTP response rule not equal to given HTTP response rule") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestEditHTTPResponseRule + r = &models.HTTPResponseRule{ + Index: &id, + Type: "set-log-level", + LogLevel: "warning", + } + + err = clientTest.EditHTTPResponseRule(1, configuration.FrontendParentName, "test", r, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, ondiskR, err = clientTest.GetHTTPResponseRule(1, configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(ondiskR, r) { + fmt.Printf("Edited HTTP response rule: %v\n", ondiskR) + fmt.Printf("Given HTTP response rule: %v\n", r) + t.Error("Edited HTTP response rule not equal to given HTTP response rule") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestDeleteHTTPResponse + err = clientTest.DeleteHTTPResponseRule(35, configuration.FrontendParentName, "test", "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + if v, _ := clientTest.GetVersion(""); v != version { + t.Error("Version not incremented") + } + + _, _, err = clientTest.GetHTTPResponseRule(35, configuration.FrontendParentName, "test", "") + if err == nil { + t.Error("DeleteHTTPResponseRule failed, HTTPResponse Rule 35 still exists") + } + + err = clientTest.DeleteHTTPResponseRule(2, configuration.BackendParentName, "test_2", "", version) + if err == nil { + t.Error("Should throw error, non existent HTTPResponse Rule") + version++ + } +} + +func TestSerializeHTTPResponseRule(t *testing.T) { + testCases := []struct { + input models.HTTPResponseRule + expectedResult string + }{ + { + input: models.HTTPResponseRule{ + Type: models.HTTPResponseRuleTypeTrackDashSc, + Cond: "if", + CondTest: "TRUE", + TrackScKey: "src", + TrackScTable: "tr0", + TrackScStickCounter: misc.Int64P(3), + }, + expectedResult: "track-sc3 src table tr0 if TRUE", + }, + { + input: models.HTTPResponseRule{ + Type: models.HTTPResponseRuleTypeTrackDashSc0, + Cond: "if", + CondTest: "TRUE", + TrackSc0Key: "src", + TrackSc0Table: "tr0", + }, + expectedResult: "track-sc0 src table tr0 if TRUE", + }, + { + input: models.HTTPResponseRule{ + Type: models.HTTPResponseRuleTypeTrackDashSc1, + Cond: "if", + CondTest: "TRUE", + TrackSc1Key: "src", + TrackSc1Table: "tr1", + }, + expectedResult: "track-sc1 src table tr1 if TRUE", + }, + { + input: models.HTTPResponseRule{ + Type: models.HTTPResponseRuleTypeTrackDashSc2, + Cond: "if", + CondTest: "TRUE", + TrackSc2Key: "src", + TrackSc2Table: "tr2", + }, + expectedResult: "track-sc2 src table tr2 if TRUE", + }, + } + + for _, testCase := range testCases { + t.Run(testCase.expectedResult, func(t *testing.T) { + tcpType, err := configuration.SerializeHTTPResponseRule(testCase.input) + if err != nil { + t.Error(err.Error()) + } + + actual := tcpType.String() + if actual != testCase.expectedResult { + t.Errorf("Expected %q, got: %q", testCase.expectedResult, actual) + } + }) + } +} diff --git a/configuration/log_forward_test.go b/test/log_forward_test.go similarity index 71% rename from configuration/log_forward_test.go rename to test/log_forward_test.go index 2ab07aa6..edd729a2 100644 --- a/configuration/log_forward_test.go +++ b/test/log_forward_test.go @@ -13,31 +13,65 @@ // limitations under the License. // -package configuration +package test import ( + _ "embed" "testing" - "github.com/haproxytech/client-native/v5/misc" + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func logForwardExpectation() map[string]models.LogForwards { + initStructuredExpected() + res := StructuredToLogForwardMap() + // Add individual entries + for _, vs := range res { + for _, v := range vs { + key := v.Name + res[key] = models.LogForwards{v} + } + } + return res +} + func TestLogForwards(t *testing.T) { + m := make(map[string]models.LogForwards) v, logForwards, err := clientTest.GetLogForwards("") if err != nil { t.Error(err.Error()) } - if len(logForwards) != 1 { t.Errorf("%v logForwards returned, expected 1", len(logForwards)) } + for _, v := range logForwards { + m[v.Name] = models.LogForwards{v} + } if v != version { t.Errorf("version %v returned, expected %v", v, version) } - if logForwards[0].Name != "sylog-loadb" { - t.Errorf("expected only test, %v found", logForwards[0].Name) + checkLogForward(t, m) +} + +func checkLogForward(t *testing.T, got map[string]models.LogForwards) { + exp := logForwardExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } } } @@ -46,18 +80,14 @@ func TestGetLogForward(t *testing.T) { if err != nil { t.Error(err.Error()) } + m := make(map[string]models.LogForwards) + m["sylog-loadb"] = models.LogForwards{r} if v != version { t.Errorf("version %v returned, expected %v", v, version) } - if r.Name != "sylog-loadb" { - t.Errorf("expected sylog-loadb log forward, %v found", r.Name) - } - - if *r.Backlog != *misc.Int64P(10) { - t.Errorf("expected backlog 10, %v found", r.Backlog) - } + checkLogForward(t, m) _, err = r.MarshalBinary() if err != nil { @@ -128,12 +158,12 @@ func TestCreateEditDeleteLogForward(t *testing.T) { err = clientTest.DeleteLogForward("created_log_forward", "", 999999) if err != nil { - if confErr, ok := err.(*ConfError); ok { - if !confErr.Is(ErrVersionMismatch) { - t.Error("should throw ErrVersionMismatch error") + if confErr, ok := err.(*configuration.ConfError); ok { + if !confErr.Is(configuration.ErrVersionMismatch) { + t.Error("should throw configuration.ErrVersionMismatch error") } } else { - t.Error("should throw ErrVersionMismatch error") + t.Error("should throw configuration.ErrVersionMismatch error") } } _, _, err = clientTest.GetLogForward("created_log_forward", "") diff --git a/configuration/log_target_test.go b/test/log_target_test.go similarity index 51% rename from configuration/log_target_test.go rename to test/log_target_test.go index 072ec0a0..719e095d 100644 --- a/configuration/log_target_test.go +++ b/test/log_target_test.go @@ -13,69 +13,75 @@ // limitations under the License. // -package configuration +package test import ( "fmt" "reflect" "testing" + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func logTargetExpectation() map[string]models.LogTargets { + initStructuredExpected() + res := StructuredToLogTargetMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%d", k, *v.Index) + res[key] = models.LogTargets{v} + } + } + return res +} + func TestGetLogTargets(t *testing.T) { - v, lTargets, err := clientTest.GetLogTargets("frontend", "test", "") + mlt := make(map[string]models.LogTargets) + v, lTargets, err := clientTest.GetLogTargets(configuration.FrontendParentName, "test", "") if err != nil { t.Error(err.Error()) } - - if len(lTargets) != 3 { - t.Errorf("%v log targets returned, expected 3", len(lTargets)) - } - if v != version { t.Errorf("Version %v returned, expected %v", v, version) } + mlt["frontend/test"] = lTargets - for _, l := range lTargets { - switch *l.Index { - case 0: - if l.Global != true { - t.Errorf("%v: Global not true: %v", *l.Index, l.Global) - } - case 1: - if l.Nolog != true { - t.Errorf("%v: Nolog not true: %v", *l.Index, l.Nolog) - } - case 2: - if l.Address != "127.0.0.1:514" { - t.Errorf("%v: Address not 127.0.0.1:514: %v", *l.Index, l.Address) - } - if l.Facility != "local0" { - t.Errorf("%v: Facility not local0: %v", *l.Index, l.Facility) - } - if l.Level != "notice" { - t.Errorf("%v: Level not notice: %v", *l.Index, l.Level) - } - if l.Minlevel != "notice" { - t.Errorf("%v: Minlevel not notice: %v", *l.Index, l.Minlevel) - } - default: - t.Errorf("Expect only log 0, 1, or 2, %v found", *l.Index) - } - } - - _, lTargets, err = clientTest.GetLogTargets("backend", "test_2", "") + _, lTargets, err = clientTest.GetLogTargets(configuration.BackendParentName, "test_2", "") if err != nil { t.Error(err.Error()) } - if len(lTargets) > 0 { - t.Errorf("%v log targets returned, expected 0", len(lTargets)) + mlt["backend/test_2"] = lTargets + + _, lTargets, err = clientTest.GetLogTargets(configuration.GlobalParentName, "", "") + mlt[configuration.GlobalParentName] = lTargets + + checkLogTargets(t, mlt) +} + +func checkLogTargets(t *testing.T, got map[string]models.LogTargets) { + exp := logTargetExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } } } func TestGetLogTarget(t *testing.T) { - v, l, err := clientTest.GetLogTarget(2, "frontend", "test", "") + m := make(map[string]models.LogTargets) + v, l, err := clientTest.GetLogTarget(2, configuration.FrontendParentName, "test", "") if err != nil { t.Error(err.Error()) } @@ -83,55 +89,30 @@ func TestGetLogTarget(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } + m["frontend/test/2"] = models.LogTargets{l} - if *l.Index != 2 { - t.Errorf("Log Target ID not 2, %v found", *l.Index) - } - if l.Address != "127.0.0.1:514" { - t.Errorf("%v: Address not 127.0.0.1:514: %v", *l.Index, l.Address) - } - if l.Facility != "local0" { - t.Errorf("%v: Facility not local0: %v", *l.Index, l.Facility) - } - if l.Level != "notice" { - t.Errorf("%v: Level not notice: %v", *l.Index, l.Level) - } - if l.Minlevel != "notice" { - t.Errorf("%v: Minlevel not notice: %v", *l.Index, l.Minlevel) - } _, err = l.MarshalBinary() if err != nil { t.Error(err.Error()) } - v, l, err = clientTest.GetLogTarget(2, "log_forward", "sylog-loadb", "") + v, l, err = clientTest.GetLogTarget(2, configuration.LogForwardParentName, "sylog-loadb", "") if err != nil { t.Error(err.Error()) } - if *l.Index != 2 { - t.Errorf("Log Target ID not 2, %v found", *l.Index) - } - if l.Address != "127.0.0.1:10001" { - t.Errorf("%v: Address not 127.0.0.1:10001: %v", *l.Index, l.Address) - } - if l.Facility != "local0" { - t.Errorf("%v: Facility not local0: %v", *l.Index, l.Facility) - } - if l.SampleRange != "1" { - t.Errorf("%v: SampleRange not 1: %v", *l.Index, l.SampleRange) - } - if l.SampleSize != 4 { - t.Errorf("%v: SampleSize not 4: %v", *l.Index, l.SampleSize) - } + m["log_forward/sylog-loadb/2"] = models.LogTargets{l} + _, err = l.MarshalBinary() if err != nil { t.Error(err.Error()) } - _, _, err = clientTest.GetLogTarget(3, "backend", "test_2", "") + _, _, err = clientTest.GetLogTarget(3, configuration.BackendParentName, "test_2", "") if err == nil { t.Error("Should throw error, non existent Log Target") } + + checkLogTargets(t, m) } func TestCreateEditDeleteLogTarget(t *testing.T) { @@ -146,14 +127,14 @@ func TestCreateEditDeleteLogTarget(t *testing.T) { Level: "notice", } - err := clientTest.CreateLogTarget("frontend", "test", r, "", version) + err := clientTest.CreateLogTarget(configuration.FrontendParentName, "test", r, "", version) if err != nil { t.Error(err.Error()) } else { version++ } - v, ondiskR, err := clientTest.GetLogTarget(3, "frontend", "test", "") + v, ondiskR, err := clientTest.GetLogTarget(3, configuration.FrontendParentName, "test", "") if err != nil { t.Error(err.Error()) } @@ -176,14 +157,14 @@ func TestCreateEditDeleteLogTarget(t *testing.T) { Facility: "local1", } - err = clientTest.EditLogTarget(3, "frontend", "test", r, "", version) + err = clientTest.EditLogTarget(3, configuration.FrontendParentName, "test", r, "", version) if err != nil { t.Error(err.Error()) } else { version++ } - v, ondiskR, err = clientTest.GetLogTarget(3, "frontend", "test", "") + v, ondiskR, err = clientTest.GetLogTarget(3, configuration.FrontendParentName, "test", "") if err != nil { t.Error(err.Error()) } @@ -199,7 +180,7 @@ func TestCreateEditDeleteLogTarget(t *testing.T) { } // TestDeleteFilter - err = clientTest.DeleteLogTarget(3, "frontend", "test", "", version) + err = clientTest.DeleteLogTarget(3, configuration.FrontendParentName, "test", "", version) if err != nil { t.Error(err.Error()) } else { @@ -210,12 +191,12 @@ func TestCreateEditDeleteLogTarget(t *testing.T) { t.Error("Version not incremented") } - _, _, err = clientTest.GetLogTarget(3, "frontend", "test", "") + _, _, err = clientTest.GetLogTarget(3, configuration.FrontendParentName, "test", "") if err == nil { t.Error("DeleteLogTarget failed, Log Target 3 still exists") } - err = clientTest.DeleteLogTarget(2, "backend", "test_2", "", version) + err = clientTest.DeleteLogTarget(2, configuration.BackendParentName, "test_2", "", version) if err == nil { t.Error("Should throw error, non existent Log Target") version++ diff --git a/configuration/mailer_entry_test.go b/test/mailer_entry_test.go similarity index 72% rename from configuration/mailer_entry_test.go rename to test/mailer_entry_test.go index a790a6f7..c381b270 100644 --- a/configuration/mailer_entry_test.go +++ b/test/mailer_entry_test.go @@ -13,17 +13,33 @@ // limitations under the License. // -package configuration +package test import ( "fmt" "reflect" "testing" + "github.com/google/go-cmp/cmp" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func mailerEntriesExpectation() map[string]models.MailerEntries { + initStructuredExpected() + res := StructuredToMailerEntryMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%s", k, v.Name) + res[key] = models.MailerEntries{v} + } + } + return res +} + func TestGetMailerEntries(t *testing.T) { + m := make(map[string]models.MailerEntries) v, mailerEntries, err := clientTest.GetMailerEntries(testMailersName, "") if err != nil { t.Error(err) @@ -32,13 +48,31 @@ func TestGetMailerEntries(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } + m["mailers_sections/"+testMailersName] = mailerEntries + + checkMailersEntries(t, m) +} - if len(mailerEntries) != 2 { - t.Errorf("found %d mailer entries, expected %d", len(mailerEntries), 2) +func checkMailersEntries(t *testing.T, got map[string]models.MailerEntries) { + exp := mailerEntriesExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } } } func TestGetMailerEntry(t *testing.T) { + m := make(map[string]models.MailerEntries) + v, mailer, err := clientTest.GetMailerEntry("smtp1", testMailersName, "") if err != nil { t.Error(err) @@ -46,21 +80,20 @@ func TestGetMailerEntry(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } + m["mailers_sections/"+testMailersName+"/smtp1"] = models.MailerEntries{mailer} - if mailer.Name != "smtp1" { - t.Errorf("found mailer name %s, expected %s", mailer.Name, "smtp1") - } - if mailer.Address != "10.0.10.1" { - t.Errorf("found mailer address %s, expected %s", mailer.Address, "10.0.10.1") - } - if mailer.Port != 514 { - t.Errorf("found mailer port %d, expected %d", mailer.Port, 514) + _, err = mailer.MarshalBinary() + if err != nil { + t.Error(err) } - _, err = mailer.MarshalBinary() + _, mailer, err = clientTest.GetMailerEntry("smtp2", testMailersName, "") if err != nil { t.Error(err) } + m["mailers_sections/"+testMailersName+"/smtp2"] = models.MailerEntries{mailer} + + checkMailersEntries(t, m) _, _, err = clientTest.GetMailerEntry("nonexistent", testMailersName, "") if err == nil { diff --git a/configuration/mailers_section_test.go b/test/mailers_section_test.go similarity index 72% rename from configuration/mailers_section_test.go rename to test/mailers_section_test.go index 0fa23727..69872e76 100644 --- a/configuration/mailers_section_test.go +++ b/test/mailers_section_test.go @@ -13,20 +13,37 @@ // limitations under the License. // -package configuration +package test import ( "fmt" "reflect" "testing" + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" "github.com/haproxytech/client-native/v5/misc" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) const testMailersName = "localmailer1" +func mailersSectionExpectation() map[string]models.MailersSections { + initStructuredExpected() + res := StructuredToMailersSectionMap() + // Add individual entries + for _, vs := range res { + for _, v := range vs { + key := v.Name + res[key] = models.MailersSections{v} + } + } + return res +} + func TestGetMailersSections(t *testing.T) { + m := make(map[string]models.MailersSections) v, mailers, err := clientTest.GetMailersSections("") if err != nil { t.Error(err) @@ -39,35 +56,24 @@ func TestGetMailersSections(t *testing.T) { if len(mailers) != 1 { t.Errorf("mailers sections: found %d, expected 1", len(mailers)) } + m[mailers[0].Name] = models.MailersSections{mailers[0]} - if mailers[0].Name != testMailersName { - t.Errorf("mailers name: found '%s', expected '%s'", mailers[0].Name, testMailersName) - } + checkMailersSection(t, m) } func TestGetMailersSection(t *testing.T) { + m := make(map[string]models.MailersSections) + v, section, err := clientTest.GetMailersSection(testMailersName, "") if err != nil { t.Error(err) } + m[testMailersName] = models.MailersSections{section} if v != version { t.Errorf("found version %d, expected %d", v, version) } - - if section.Name != testMailersName { - t.Errorf("mailers name: found '%s', expected '%s'", section.Name, testMailersName) - } - - timeout := *misc.ParseTimeout("15s") - if *section.Timeout != timeout { - t.Errorf("mailers timeout: found %d, expected %d", *section.Timeout, timeout) - } - - _, err = section.MarshalBinary() - if err != nil { - t.Error(err) - } + checkMailersSection(t, m) _, _, err = clientTest.GetMailersSection("doesnotexist", "") if err == nil { @@ -75,6 +81,23 @@ func TestGetMailersSection(t *testing.T) { } } +func checkMailersSection(t *testing.T, got map[string]models.MailersSections) { + exp := mailersSectionExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + func TestCreateEditDeleteMailersSection(t *testing.T) { ms := &models.MailersSection{ Name: "newMailer", @@ -144,12 +167,12 @@ func TestCreateEditDeleteMailersSection(t *testing.T) { err = clientTest.DeleteMailersSection("newMailer", "", 999999) if err != nil { - if confErr, ok := err.(*ConfError); ok { - if !confErr.Is(ErrVersionMismatch) { - t.Error("Should throw ErrVersionMismatch error") + if confErr, ok := err.(*configuration.ConfError); ok { + if !confErr.Is(configuration.ErrVersionMismatch) { + t.Error("Should throw configuration.ErrVersionMismatch error") } } else { - t.Error("Should throw ErrVersionMismatch error") + t.Error("Should throw configuration.ErrVersionMismatch error") } } diff --git a/configuration/nameserver_test.go b/test/nameserver_test.go similarity index 77% rename from configuration/nameserver_test.go rename to test/nameserver_test.go index fd5be0b9..7d60f142 100644 --- a/configuration/nameserver_test.go +++ b/test/nameserver_test.go @@ -13,67 +13,58 @@ // limitations under the License. // -package configuration +package test import ( "fmt" "reflect" "testing" + "github.com/google/go-cmp/cmp" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func nameServerExpectation() map[string]models.Nameservers { + initStructuredExpected() + res := StructuredToNameserverMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%s", k, v.Name) + res[key] = models.Nameservers{v} + } + } + return res +} + func TestGetNameservers(t *testing.T) { + m := make(map[string]models.Nameservers) v, nameservers, err := clientTest.GetNameservers("test", "") if err != nil { t.Error(err.Error()) } - - if len(nameservers) != 1 { - t.Errorf("%v nameservers returned, expected 1", len(nameservers)) - } + m["resolvers/test"] = nameservers if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - - for _, l := range nameservers { - if l.Name != "dns1" { - t.Errorf("Expected only dns1, %v found", l.Name) - } - if *l.Address != "10.0.0.1" { - t.Errorf("%v: Address not %s: %v", "10.0.0.1", l.Name, *l.Address) - } - if *l.Port != 53 { - t.Errorf("%v: Port not %s: %v", "10.0.0.1", l.Name, *l.Port) - } - } + checkNameservers(t, m) } func TestGetNameserver(t *testing.T) { + m := make(map[string]models.Nameservers) + v, l, err := clientTest.GetNameserver("dns1", "test", "") if err != nil { t.Error(err.Error()) } + m["resolvers/test/dns1"] = models.Nameservers{l} if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - - if l.Name != "dns1" { - t.Errorf("Expected only happe nameserver, %v found", l.Name) - } - if *l.Address != "10.0.0.1" { - t.Errorf("%v: Address not 10.0.0.1: %v", l.Name, l.Address) - } - if *l.Port != 53 { - t.Errorf("%v: Port not 53: %v", l.Name, *l.Port) - } - - _, err = l.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } + checkNameservers(t, m) _, _, err = clientTest.GetNameserver("community", "test", "") if err == nil { @@ -81,6 +72,23 @@ func TestGetNameserver(t *testing.T) { } } +func checkNameservers(t *testing.T, got map[string]models.Nameservers) { + exp := nameServerExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + func TestCreateEditDeleteNameserver(t *testing.T) { _, _, err := clientTest.GetNameserver("dns1", "test", "") if err != nil { diff --git a/configuration/peer_entry_test.go b/test/peer_entry_test.go similarity index 78% rename from configuration/peer_entry_test.go rename to test/peer_entry_test.go index 9e3507b9..0a8a444f 100644 --- a/configuration/peer_entry_test.go +++ b/test/peer_entry_test.go @@ -13,14 +13,16 @@ // limitations under the License. // -package configuration +package test import ( "fmt" "reflect" "testing" + "github.com/google/go-cmp/cmp" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) const ( @@ -28,60 +30,47 @@ const ( testIP = "192.168.1.1" ) +func peerEntryExpectation() map[string]models.PeerEntries { + initStructuredExpected() + res := StructuredToPeerEntryMap() + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%s", k, v.Name) + res[key] = models.PeerEntries{v} + } + } + return res +} + func TestGetPeerEntries(t *testing.T) { + m := make(map[string]models.PeerEntries) v, peerEntries, err := clientTest.GetPeerEntries("mycluster", "") if err != nil { t.Error(err.Error()) } - if len(peerEntries) != 2 { - t.Errorf("%v peerEntries returned, expected 2", len(peerEntries)) - } + m["peers/mycluster"] = peerEntries if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - - for _, l := range peerEntries { - if l.Name != "hapee" && l.Name != "aggregator" { - t.Errorf("Expected only hapee and aggregator, %v found", l.Name) - } - if *l.Address != testIP && *l.Address != "HARDCODEDCLUSTERIP" { - t.Errorf("%v: Address not %s: %v", testIP, l.Name, *l.Address) - } - if *l.Port != testPort && *l.Port != 10023 { - t.Errorf("%v: Port not %s: %v", testIP, l.Name, *l.Port) - } - } + checkPeerEntries(t, m) } func TestGetPeerEntry(t *testing.T) { + m := make(map[string]models.PeerEntries) + v, l, err := clientTest.GetPeerEntry("hapee", "mycluster", "") if err != nil { t.Error(err.Error()) } + m["peers/mycluster/hapee"] = models.PeerEntries{l} if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - if l.Name != "hapee" { - t.Errorf("Expected only happe peerEntry, %v found", l.Name) - } - if *l.Address != "192.168.1.1" { - t.Errorf("%v: Address not 192.168.1.1: %v", l.Name, l.Address) - } - if *l.Port != 1023 { - t.Errorf("%v: Port not 1023: %v", l.Name, *l.Port) - } - if l.Shard != 1 { - t.Errorf("%v: Shard not 1: %v", l.Name, l.Shard) - } - - _, err = l.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } + checkPeerEntries(t, m) _, _, err = clientTest.GetPeerEntry("community", "mycluster", "") if err == nil { @@ -89,6 +78,23 @@ func TestGetPeerEntry(t *testing.T) { } } +func checkPeerEntries(t *testing.T, got map[string]models.PeerEntries) { + exp := peerEntryExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + func TestCreateEditDeletePeerEntry(t *testing.T) { _, _, err := clientTest.GetPeerEntry("hapee", "mycluster", "") if err != nil { diff --git a/configuration/peer_section_test.go b/test/peer_section_test.go similarity index 60% rename from configuration/peer_section_test.go rename to test/peer_section_test.go index 0be4eb0a..ebad6439 100644 --- a/configuration/peer_section_test.go +++ b/test/peer_section_test.go @@ -13,17 +13,35 @@ // limitations under the License. // -package configuration +package test import ( "fmt" "reflect" "testing" + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func peerSectionExpectation() map[string]models.PeerSections { + initStructuredExpected() + res := StructuredToPeerSectionMap() + // Add individual entries + for _, vs := range res { + for _, v := range vs { + key := v.Name + res[key] = models.PeerSections{v} + } + } + return res +} + func TestGetPeerSections(t *testing.T) { + m := make(map[string]models.PeerSections) + v, peerSections, err := clientTest.GetPeerSections("") if err != nil { t.Error(err.Error()) @@ -37,12 +55,13 @@ func TestGetPeerSections(t *testing.T) { t.Errorf("Version %v returned, expected %v", v, version) } - if peerSections[0].Name != "mycluster" { - t.Errorf("Expected only mycluster, %v found", peerSections[0].Name) - } + m[""] = peerSections + + checkPeerSections(t, m) } func TestGetPeerSection(t *testing.T) { + m := make(map[string]models.PeerSections) v, l, err := clientTest.GetPeerSection("mycluster", "") if err != nil { t.Error(err.Error()) @@ -51,57 +70,8 @@ func TestGetPeerSection(t *testing.T) { if v != version { t.Errorf("%v: Version not %v: %v", l.Name, v, version) } - - if l.Name != "mycluster" { - t.Errorf("%v: Name not: %v", l.Name, l.Name) - } - - if !l.Enabled { - t.Errorf("%v: Enabled not true", l.Name) - } - - if l.DefaultServer.Fall == nil { - t.Errorf("%v: DefaultServer.Fall is nil", l.Name) - } else if *l.DefaultServer.Fall != 2000 { - t.Errorf("%v: DefaultServer.Fall not 2000: %v", l.Name, *l.DefaultServer.Fall) - } - if l.DefaultServer.Rise == nil { - t.Errorf("%v: DefaultServer.Rise is nil", l.Name) - } else if *l.DefaultServer.Rise != 4000 { - t.Errorf("%v: DefaultServer.Rise not 4000: %v", l.Name, *l.DefaultServer.Rise) - } - if l.DefaultServer.Inter == nil { - t.Errorf("%v: DefaultServer.Inter is nil", l.Name) - } else if *l.DefaultServer.Inter != 5000 { - t.Errorf("%v: DefaultServer.Inter not 5000: %v", l.Name, *l.DefaultServer.Inter) - } - if l.DefaultServer.HealthCheckPort == nil { - t.Errorf("%v: DefaultServer.HealthCheckPort is nil", l.Name) - } else if *l.DefaultServer.HealthCheckPort != 8888 { - t.Errorf("%v: DefaultServer.HealthCheckPort not 8888: %v", l.Name, *l.DefaultServer.HealthCheckPort) - } - if l.DefaultServer.Slowstart == nil { - t.Errorf("%v: DefaultServer.Slowstart is nil", l.Name) - } else if *l.DefaultServer.Slowstart != 6000 { - t.Errorf("%v: DefaultServer.Slowstart not 6000: %v", l.Name, *l.DefaultServer.Slowstart) - } - - if !l.DefaultBind.V4v6 { - t.Errorf("%v: DefaultBind.V4v6 not true", l.Name) - } - if !l.DefaultBind.Ssl { - t.Errorf("%v: DefaultBind.Ssl not true", l.Name) - } - if l.DefaultBind.SslCertificate != "/etc/haproxy/site.pem" { - t.Errorf("%v: DefaultBind.SslCertificate not etc/haproxy/site.pem: %v", l.Name, l.DefaultBind.SslCertificate) - } - if l.DefaultBind.Alpn != "h2,http/1.1" { - t.Errorf("%v: DefaultBind.Alpn not h2,http/1.1: %v", l.Name, l.DefaultBind.Alpn) - } - - if l.Shards != 3 { - t.Errorf("%v: Shards not 3: %v", l.Name, l.Shards) - } + m["mycluster"] = models.PeerSections{l} + checkPeerSections(t, m) _, err = l.MarshalBinary() if err != nil { @@ -114,6 +84,23 @@ func TestGetPeerSection(t *testing.T) { } } +func checkPeerSections(t *testing.T, got map[string]models.PeerSections) { + exp := peerSectionExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + func TestCreateEditDeletePeerSection(t *testing.T) { tOut := int64(5) f := &models.PeerSection{ @@ -175,12 +162,12 @@ func TestCreateEditDeletePeerSection(t *testing.T) { err = clientTest.DeletePeerSection("testcluster", "", 999999) if err != nil { - if confErr, ok := err.(*ConfError); ok { - if !confErr.Is(ErrVersionMismatch) { - t.Error("Should throw ErrVersionMismatch error") + if confErr, ok := err.(*configuration.ConfError); ok { + if !confErr.Is(configuration.ErrVersionMismatch) { + t.Error("Should throw configuration.ErrVersionMismatch error") } } else { - t.Error("Should throw ErrVersionMismatch error") + t.Error("Should throw configuration.ErrVersionMismatch error") } } _, _, err = clientTest.GetPeerSection("testcluster", "") diff --git a/configuration/program_test.go b/test/program_test.go similarity index 73% rename from configuration/program_test.go rename to test/program_test.go index d04cff62..d1dd3126 100644 --- a/configuration/program_test.go +++ b/test/program_test.go @@ -12,11 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -package configuration +package test import ( "testing" + "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -24,25 +25,57 @@ import ( "github.com/haproxytech/client-native/v5/models" ) +func programExpectation() map[string]models.Programs { + initStructuredExpected() + res := StructuredToProgramMap() + // Add individual entries + for _, vs := range res { + for _, v := range vs { + key := v.Name + res[key] = models.Programs{v} + } + } + return res +} + func TestGetPrograms(t *testing.T) { + m := make(map[string]models.Programs) v, programs, err := clientTest.GetPrograms("") require.NoError(t, err) require.Len(t, programs, 2) require.Equal(t, version, v) + m[""] = programs + checkPrograms(t, m) } func TestGetProgram(t *testing.T) { + m := make(map[string]models.Programs) v, program, err := clientTest.GetProgram("test", "") require.NoError(t, err) require.NotNil(t, program) require.Equal(t, version, v) + m["test"] = models.Programs{program} - assert.Equal(t, `echo "Hello, World!"`, *program.Command) - assert.Equal(t, "hapee-lb", program.User) - assert.Equal(t, "hapee", program.Group) - assert.Equal(t, models.ProgramStartOnReloadEnabled, program.StartOnReload) + checkPrograms(t, m) +} + +func checkPrograms(t *testing.T, got map[string]models.Programs) { + exp := programExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } } func TestCreateEditDeleteProgram(t *testing.T) { diff --git a/configuration/resolver_test.go b/test/resolver_test.go similarity index 71% rename from configuration/resolver_test.go rename to test/resolver_test.go index 31ac1ad6..c73b168a 100644 --- a/configuration/resolver_test.go +++ b/test/resolver_test.go @@ -13,37 +13,50 @@ // limitations under the License. // -package configuration +package test import ( "fmt" "reflect" "testing" + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" "github.com/haproxytech/client-native/v5/misc" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func resolverExpectation() map[string]models.Resolvers { + initStructuredExpected() + res := StructuredToResolverMap() + // Add individual entries + for _, vs := range res { + for _, v := range vs { + key := v.Name + res[key] = models.Resolvers{v} + } + } + return res +} + func TestGetResolvers(t *testing.T) { + m := make(map[string]models.Resolvers) + v, resolvers, err := clientTest.GetResolvers("") if err != nil { t.Error(err.Error()) } - if len(resolvers) != 1 { - t.Errorf("%v resolvers returned, expected 1", len(resolvers)) - } - if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - - if resolvers[0].Name != "test" { - t.Errorf("Expected only test, %v found", resolvers[0].Name) - } + m[""] = resolvers + checkResolvers(t, m) } func TestGetResolver(t *testing.T) { + m := make(map[string]models.Resolvers) v, l, err := clientTest.GetResolver("test", "") if err != nil { t.Error(err.Error()) @@ -52,15 +65,8 @@ func TestGetResolver(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - - if l.Name != "test" { - t.Errorf("Expected test resolver, %v found", l.Name) - } - - _, err = l.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } + m["test"] = models.Resolvers{l} + checkResolvers(t, m) _, _, err = clientTest.GetResolver("doesnotexist", "") if err == nil { @@ -68,6 +74,23 @@ func TestGetResolver(t *testing.T) { } } +func checkResolvers(t *testing.T, got map[string]models.Resolvers) { + exp := resolverExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + func TestCreateEditDeleteResolver(t *testing.T) { f := &models.Resolver{ Name: "created_resolver", @@ -124,12 +147,12 @@ func TestCreateEditDeleteResolver(t *testing.T) { err = clientTest.DeleteResolver("created_resolver", "", 999999) if err != nil { - if confErr, ok := err.(*ConfError); ok { - if !confErr.Is(ErrVersionMismatch) { - t.Error("Should throw ErrVersionMismatch error") + if confErr, ok := err.(*configuration.ConfError); ok { + if !confErr.Is(configuration.ErrVersionMismatch) { + t.Error("Should throw configuration.ErrVersionMismatch error") } } else { - t.Error("Should throw ErrVersionMismatch error") + t.Error("Should throw configuration.ErrVersionMismatch error") } } _, _, err = clientTest.GetResolver("created_resolver", "") diff --git a/configuration/ring_test.go b/test/ring_test.go similarity index 73% rename from configuration/ring_test.go rename to test/ring_test.go index 8f8ba78a..86f9b8f0 100644 --- a/configuration/ring_test.go +++ b/test/ring_test.go @@ -13,35 +13,47 @@ // limitations under the License. // -package configuration +package test import ( "testing" - "github.com/haproxytech/client-native/v5/misc" + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func ringExpectation() map[string]models.Rings { + initStructuredExpected() + res := StructuredToRingMap() + // Add individual entries + for _, vs := range res { + for _, v := range vs { + key := v.Name + res[key] = models.Rings{v} + } + } + return res +} + func TestGetRings(t *testing.T) { + m := make(map[string]models.Rings) v, rings, err := clientTest.GetRings("") if err != nil { t.Error(err.Error()) } - if len(rings) != 1 { - t.Errorf("%v rings returned, expected 1", len(rings)) - } - if v != version { t.Errorf("version %v returned, expected %v", v, version) } - - if rings[0].Name != "myring" { - t.Errorf("expected only test, %v found", rings[0].Name) - } + m[""] = rings + checkRings(t, m) } func TestGetRing(t *testing.T) { + m := make(map[string]models.Rings) + v, r, err := clientTest.GetRing("myring", "") if err != nil { t.Error(err.Error()) @@ -50,19 +62,8 @@ func TestGetRing(t *testing.T) { if v != version { t.Errorf("version %v returned, expected %v", v, version) } - - if r.Name != "myring" { - t.Errorf("expected myring ring, %v found", r.Name) - } - - if *r.Maxlen != *misc.Int64P(1200) { - t.Errorf("expected maxlen 1200, %v found", r.Maxlen) - } - - _, err = r.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } + m["myring"] = models.Rings{r} + checkRings(t, m) _, _, err = clientTest.GetRing("doesnotexist", "") if err == nil { @@ -70,6 +71,24 @@ func TestGetRing(t *testing.T) { } } +func checkRings(t *testing.T, got map[string]models.Rings) { + exp := ringExpectation() + + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + func TestCreateEditDeleteRing(t *testing.T) { maxlen := int64(1300) size := int64(32765) @@ -144,12 +163,12 @@ func TestCreateEditDeleteRing(t *testing.T) { err = clientTest.DeleteRing("created_ring", "", 999999) if err != nil { - if confErr, ok := err.(*ConfError); ok { - if !confErr.Is(ErrVersionMismatch) { - t.Error("should throw ErrVersionMismatch error") + if confErr, ok := err.(*configuration.ConfError); ok { + if !confErr.Is(configuration.ErrVersionMismatch) { + t.Error("should throw configuration.ErrVersionMismatch error") } } else { - t.Error("should throw ErrVersionMismatch error") + t.Error("should throw configuration.ErrVersionMismatch error") } } _, _, err = clientTest.GetRing("created_ring", "") diff --git a/configuration/server_switching_rule_test.go b/test/server_switching_rule_test.go similarity index 74% rename from configuration/server_switching_rule_test.go rename to test/server_switching_rule_test.go index b5db3fb1..5bf3a1ca 100644 --- a/configuration/server_switching_rule_test.go +++ b/test/server_switching_rule_test.go @@ -13,67 +13,71 @@ // limitations under the License. // -package configuration +package test import ( "fmt" "reflect" "testing" + "github.com/google/go-cmp/cmp" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func serverSwitchingRuleExpectation() map[string]models.ServerSwitchingRules { + initStructuredExpected() + res := StructuredToServerSwitchingRuleMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%d", k, *v.Index) + res[key] = models.ServerSwitchingRules{v} + } + } + return res +} + func TestGetServerSwitchingRules(t *testing.T) { + mssr := make(map[string]models.ServerSwitchingRules) v, srvRules, err := clientTest.GetServerSwitchingRules("test", "") if err != nil { t.Error(err.Error()) } - - if len(srvRules) != 2 { - t.Errorf("%v server switching rules returned, expected 2", len(srvRules)) - } + mssr["backend/test"] = srvRules if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - for _, sr := range srvRules { - switch *sr.Index { - case 0: - if sr.TargetServer != "webserv" { - t.Errorf("%v: TargetServer not webserv: %v", *sr.Index, sr.TargetServer) - } - if sr.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *sr.Index, sr.Cond) - } - if sr.CondTest != "TRUE" { - t.Errorf("%v: CondTest not TRUE: %v", *sr.Index, sr.CondTest) - } - case 1: - if sr.TargetServer != "webserv2" { - t.Errorf("%v: TargetServer not webserv2: %v", *sr.Index, sr.TargetServer) - } - if sr.Cond != "unless" { - t.Errorf("%v: Cond not if: %v", *sr.Index, sr.Cond) - } - if sr.CondTest != "TRUE" { - t.Errorf("%v: CondTest not TRUE: %v", *sr.Index, sr.CondTest) - } - default: - t.Errorf("Expect only server switching rule 0 or 1, %v found", *sr.Index) - } - } - _, srvRules, err = clientTest.GetServerSwitchingRules("test_2", "") if err != nil { t.Error(err.Error()) } - if len(srvRules) > 0 { - t.Errorf("%v server switching rules returned, expected 0", len(srvRules)) + mssr["backend/test_2"] = srvRules + + checkServerSwitchingRules(t, mssr) +} + +func checkServerSwitchingRules(t *testing.T, got map[string]models.ServerSwitchingRules) { + exp := serverSwitchingRuleExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } } } func TestGetServerSwitchingRule(t *testing.T) { + m := make(map[string]models.ServerSwitchingRules) v, sr, err := clientTest.GetServerSwitchingRule(0, "test", "") if err != nil { t.Error(err.Error()) @@ -82,16 +86,9 @@ func TestGetServerSwitchingRule(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } + m["backend/test/0"] = models.ServerSwitchingRules{sr} - if sr.TargetServer != "webserv" { - t.Errorf("%v: TargetServer not webserv: %v", sr.Index, sr.TargetServer) - } - if sr.Cond != "if" { - t.Errorf("%v: Cond not if: %v", sr.Index, sr.Cond) - } - if sr.CondTest != "TRUE" { - t.Errorf("%v: CondTest not TRUE: %v", sr.Index, sr.CondTest) - } + checkServerSwitchingRules(t, m) _, err = sr.MarshalBinary() if err != nil { diff --git a/configuration/server_template_test.go b/test/server_template_test.go similarity index 63% rename from configuration/server_template_test.go rename to test/server_template_test.go index 6283f3eb..d560f8bb 100644 --- a/configuration/server_template_test.go +++ b/test/server_template_test.go @@ -1,36 +1,62 @@ -package configuration +package test import ( "fmt" "reflect" "testing" + "github.com/google/go-cmp/cmp" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) -func TestGetServerTemplates(t *testing.T) { //nolint:gocognit,gocyclo +func serverTemplateExpectation() map[string]models.ServerTemplates { + initStructuredExpected() + res := StructuredToServerTemplateMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%s", k, v.Prefix) + res[key] = models.ServerTemplates{v} + } + } + return res +} +func TestGetServerTemplates(t *testing.T) { //nolint:gocognit,gocyclo + mt := make(map[string]models.ServerTemplates) v, templates, err := clientTest.GetServerTemplates("test", "") if err != nil { t.Error(err.Error()) } - - if len(templates) != 4 { - t.Errorf("%v server templates returned, expected 4", len(templates)) - } + mt["backend/test"] = templates if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - for _, template := range templates { - if template.Check != "enabled" { - t.Errorf("%v: Check not enabled: %v", template.Prefix, template.Check) + checkServerTemplates(t, mt) +} + +func checkServerTemplates(t *testing.T, got map[string]models.ServerTemplates) { + exp := serverTemplateExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Prefix == w.Prefix { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } } } } func TestGetServerTemplate(t *testing.T) { + m := make(map[string]models.ServerTemplates) v, template, err := clientTest.GetServerTemplate("srv", "test", "") if err != nil { t.Error(err.Error()) @@ -38,32 +64,17 @@ func TestGetServerTemplate(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - if template.Prefix != "srv" { - t.Errorf("Expected only srv, %v found", template.Prefix) - } - if template.NumOrRange != "1-3" { - t.Errorf("Expected 1-3, %v found", template.NumOrRange) - } - if template.Fqdn != "google.com" { - t.Errorf("Expected google.com, %v found", template.Fqdn) - } - if *template.Port != 80 { - t.Errorf(" Expected 80, %v found", template.Port) - } - if template.Check != "enabled" { - t.Errorf("Expected check to be enabled") - } - _, err = template.MarshalBinary() - if err != nil { - t.Error(err.Error()) - } + m["backend/test/srv"] = models.ServerTemplates{template} _, _, err = clientTest.GetServerTemplate("test2", "example", "") if err == nil { t.Error("Should throw error, non existent server template") } + checkServerTemplates(t, m) } func TestGetServerTemplateSecond(t *testing.T) { + m := make(map[string]models.ServerTemplates) + v, template, err := clientTest.GetServerTemplate("site", "test", "") if err != nil { t.Error(err.Error()) @@ -71,24 +82,8 @@ func TestGetServerTemplateSecond(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - if template.Prefix != "site" { - t.Errorf("Expected only site, %v found", template.Prefix) - } - if template.NumOrRange != "1-10" { - t.Errorf("Expected 1-10, %v found", template.NumOrRange) - } - if template.Fqdn != "google.com" { - t.Errorf("Expected google.com, %v found", template.Fqdn) - } - if *template.Port != 8080 { - t.Errorf("Expected 8080, %v found", *template.Port) - } - if template.Check != "enabled" { - t.Errorf("Expected check to be enabled") - } - if template.Backup != "enabled" { - t.Errorf("Expected backup to be enabled") - } + m["backend/test/site"] = models.ServerTemplates{template} + _, err = template.MarshalBinary() if err != nil { t.Error(err.Error()) @@ -96,6 +91,8 @@ func TestGetServerTemplateSecond(t *testing.T) { } func TestGetServerTemplateThird(t *testing.T) { + m := make(map[string]models.ServerTemplates) + v, template, err := clientTest.GetServerTemplate("website", "test", "") if err != nil { t.Error(err.Error()) @@ -103,31 +100,19 @@ func TestGetServerTemplateThird(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - if template.Prefix != "website" { - t.Errorf("Expected only website, %v found", template.Prefix) - } - if template.NumOrRange != "10-100" { - t.Errorf("Expected 10-100, %v found", template.NumOrRange) - } - if template.Fqdn != "google.com" { - t.Errorf("Expected google.com, %v found", template.Fqdn) - } - if *template.Port != 443 { - t.Errorf("Expected 443, %v found", *template.Port) - } - if template.Check != "enabled" { - t.Errorf("Expected check to be enabled") - } - if template.Backup != "disabled" { - t.Errorf("Expected backup to be disabled") - } + m["backend/test/website"] = models.ServerTemplates{template} + _, err = template.MarshalBinary() if err != nil { t.Error(err.Error()) } + + checkServerTemplates(t, m) } func TestGetServerTemplateFourth(t *testing.T) { + m := make(map[string]models.ServerTemplates) + v, template, err := clientTest.GetServerTemplate("test", "test", "") if err != nil { t.Error(err.Error()) @@ -135,28 +120,13 @@ func TestGetServerTemplateFourth(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - if template.Prefix != "test" { - t.Errorf("Expected only website, %v found", template.Prefix) - } - if template.NumOrRange != "5" { - t.Errorf("Expected 5, %v found", template.NumOrRange) - } - if template.Fqdn != "test.com" { - t.Errorf("Expected test.com, %v found", template.Fqdn) - } - if *template.Port != 0 { - t.Errorf("Expected 0, %v found", *template.Port) - } - if template.Check != "enabled" { - t.Errorf("Expected check to be enabled") - } - if template.Backup != "enabled" { - t.Errorf("Expected backup to be enabled") - } + m["backend/test/test"] = models.ServerTemplates{template} + _, err = template.MarshalBinary() if err != nil { t.Error(err.Error()) } + checkServerTemplates(t, m) } func TestCreateEditDeleteServerTemplate(t *testing.T) { diff --git a/test/server_test.go b/test/server_test.go new file mode 100644 index 00000000..8926228a --- /dev/null +++ b/test/server_test.go @@ -0,0 +1,322 @@ +// 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. +// + +package test + +import ( + "fmt" + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" + "github.com/haproxytech/client-native/v5/misc" + "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" +) + +func serverExpectation() map[string]models.Servers { + initStructuredExpected() + res := StructuredToServerMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%s", k, v.Name) + res[key] = models.Servers{v} + } + } + return res +} + +func TestGetServers(t *testing.T) { //nolint:gocognit,gocyclo + ms := make(map[string]models.Servers) + v, servers, err := clientTest.GetServers(configuration.BackendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + ms["backend/test"] = servers + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + _, servers, err = clientTest.GetServers(configuration.BackendParentName, "test_2", "") + if err != nil { + t.Error(err.Error()) + } + ms["backend/test_2"] = servers + + checkServers(t, ms) +} + +func checkServers(t *testing.T, got map[string]models.Servers) { + exp := serverExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Name == w.Name { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + +func TestGetServer(t *testing.T) { + m := make(map[string]models.Servers) + + v, s, err := clientTest.GetServer("webserv", configuration.BackendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + m["backend/test/webserv"] = models.Servers{s} + + _, err = s.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + _, _, err = clientTest.GetServer("webserv", configuration.BackendParentName, "test_2", "") + if err == nil { + t.Error("Should throw error, non existent server") + } + + checkServers(t, m) +} + +func TestGetRingServer(t *testing.T) { + m := make(map[string]models.Servers) + v, s, err := clientTest.GetServer("mysyslogsrv", configuration.RingParentName, "myring", "") + if err != nil { + t.Error(err.Error()) + } + m["ring/myring/mysyslogsrv"] = models.Servers{s} + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + v, s, err = clientTest.GetServer("s1", configuration.RingParentName, "myring", "") + if err != nil { + t.Error(err.Error()) + } + m["ring/myring/s1"] = models.Servers{s} + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + checkServers(t, m) + + _, _, err = clientTest.GetServer("non-existent", configuration.RingParentName, "myring", "") + if err == nil { + t.Error("Should throw error, non existent server") + } +} + +func TestCreateEditDeleteServer(t *testing.T) { + // TestCreateServer + port := int64(4300) + inter := int64(5000) + slowStart := int64(6000) + s := &models.Server{ + Name: "created", + Address: "192.168.2.1", + Port: &port, + ServerParams: models.ServerParams{ + Backup: "enabled", + Check: "enabled", + Maintenance: "enabled", + Ssl: "enabled", + AgentCheck: "enabled", + SslCertificate: "dummy.crt", + TLSTickets: "enabled", + Verify: "none", + Inter: &inter, + OnMarkedDown: "shutdown-sessions", + OnError: "mark-down", + OnMarkedUp: "shutdown-backup-sessions", + Slowstart: &slowStart, + ProxyV2Options: []string{"ssl", "unique-id"}, + Curves: "brainpoolP384r1", + Sigalgs: "RSA+SHA256", + ClientSigalgs: "ECDSA+SHA256", + LogBufsize: misc.Int64P(11), + SetProxyV2TlvFmt: &models.ServerParamsSetProxyV2TlvFmt{ + ID: misc.StringP("0x50"), + Value: misc.StringP("%[fc_pp_tlv(0x20)]"), + }, + }, + } + + err := clientTest.CreateServer(configuration.BackendParentName, "test", s, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, server, err := clientTest.GetServer("created", configuration.BackendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(server, s) { + fmt.Printf("Created server: %v\n", server) + fmt.Printf("Given server: %v\n", s) + t.Error("Created server not equal to given server") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + err = clientTest.CreateServer(configuration.BackendParentName, "test", s, "", version) + if err == nil { + t.Error("Should throw error server already exists") + version++ + } + + // TestEditServer + port = int64(5300) + slowStart = int64(3000) + s = &models.Server{ + Name: "created", + Address: "192.168.3.1", + Port: &port, + ServerParams: models.ServerParams{ + AgentCheck: "disabled", + Ssl: "enabled", + SslCertificate: "dummy.crt", + SslCafile: "dummy.ca", + TLSTickets: "disabled", + Verify: "required", + Slowstart: &slowStart, + }, + } + + err = clientTest.EditServer("created", configuration.BackendParentName, "test", s, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, server, err = clientTest.GetServer("created", configuration.BackendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(server, s) { + fmt.Printf("Edited server: %v\n", server) + fmt.Printf("Given server: %v\n", s) + t.Error("Edited server not equal to given server") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestDeleteServer + err = clientTest.DeleteServer("created", configuration.BackendParentName, "test", "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + if v, _ := clientTest.GetVersion(""); v != version { + t.Error("Version not incremented") + } + + _, _, err = clientTest.GetServer("created", configuration.BackendParentName, "test", "") + if err == nil { + t.Error("DeleteServer failed, server test still exists") + } + + err = clientTest.DeleteServer("created", configuration.BackendParentName, "test_2", "", version) + if err == nil { + t.Error("Should throw error, non existent server") + version++ + } +} + +func Test_parseAddress(t *testing.T) { + type args struct { + address string + } + tests := []struct { + name string + args args + wantIpOrAddress string + wantPort *int64 + }{ + { + name: "IPv6 with brackets", + args: args{address: "[fd00:6:48:c85:deb:f:62:4]:80"}, + wantIpOrAddress: "fd00:6:48:c85:deb:f:62:4", + wantPort: misc.Int64P(80), + }, + { + name: "IPv6 without brackets", + args: args{address: "fd00:6:48:c85:deb:f:62:4:443"}, + wantIpOrAddress: "fd00:6:48:c85:deb:f:62:4", + wantPort: misc.Int64P(443), + }, + { + name: "IPv6 without brackets, without port", + args: args{address: "fd00:6:48:c85:deb:f:62:a123"}, + wantIpOrAddress: "fd00:6:48:c85:deb:f:62:a123", + wantPort: nil, + }, + { + name: "IPv4 with port", + args: args{address: "10.1.1.2:8080"}, + wantIpOrAddress: "10.1.1.2", + wantPort: misc.Int64P(8080), + }, + { + name: "IPv4 without port", + args: args{address: "10.1.1.2"}, + wantIpOrAddress: "10.1.1.2", + wantPort: nil, + }, + { + name: "Socket address", + args: args{address: "/var/run/test_socket"}, + wantIpOrAddress: "/var/run/test_socket", + wantPort: nil, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + gotIpOrAddress, gotPort := configuration.ParseAddress(tt.args.address) + if gotIpOrAddress != tt.wantIpOrAddress { + t.Errorf("ParseAddress() gotIpOrAddress = %v, want %v", gotIpOrAddress, tt.wantIpOrAddress) + } + if gotPort != nil && tt.wantPort != nil && *gotPort != *tt.wantPort { + t.Errorf("ParseAddress() gotPort = %v, want %v", gotPort, tt.wantPort) + } + }) + } +} diff --git a/configuration/service_test.go b/test/service_test.go similarity index 84% rename from configuration/service_test.go rename to test/service_test.go index c5ede44f..005f8f3c 100644 --- a/configuration/service_test.go +++ b/test/service_test.go @@ -13,7 +13,7 @@ // limitations under the License. // -package configuration +package test import ( "fmt" @@ -21,6 +21,7 @@ import ( "github.com/stretchr/testify/suite" + "github.com/haproxytech/client-native/v5/configuration" "github.com/haproxytech/client-native/v5/misc" "github.com/haproxytech/client-native/v5/models" ) @@ -39,13 +40,13 @@ func TestService(t *testing.T) { type ServiceTestSuit struct { suite.Suite - client Configuration + client configuration.Configuration transactionID string } func (s *ServiceTestSuit) testCreate() { serviceName := misc.RandomString(10) - service, err := s.client.NewService(serviceName, ScalingParams{}) + service, err := s.client.NewService(serviceName, configuration.ScalingParams{}) s.NotNil(service) s.Nil(err) s.client.DeleteService(serviceName) @@ -78,8 +79,8 @@ func (s *ServiceTestSuit) TestService() { type ServiceInitiationSuite struct { suite.Suite - client Configuration - service *Service + client configuration.Configuration + service *configuration.Service serviceName string transactionID string } @@ -89,9 +90,9 @@ func (s *ServiceInitiationSuite) SetupSuite() { } func (s *ServiceInitiationSuite) BeforeTest(suiteName, testName string) { - service, err := s.client.NewService(s.serviceName, ScalingParams{ + service, err := s.client.NewService(s.serviceName, configuration.ScalingParams{ BaseSlots: baseSlots, - SlotsGrowthType: ServiceGrowthTypeLinear, + SlotsGrowthType: configuration.ServiceGrowthTypeLinear, SlotsIncrement: slotsIncrement, }) s.NotNil(service) @@ -117,13 +118,13 @@ func (s *ServiceInitiationSuite) TestInitAndDelete() { } func (s *ServiceInitiationSuite) TestFailCreatingIfExists() { - _, err := s.client.NewService(s.serviceName, ScalingParams{}) + _, err := s.client.NewService(s.serviceName, configuration.ScalingParams{}) s.NotNil(err) } func (s *ServiceInitiationSuite) TestRecreatingAfterDeletion() { clientTest.DeleteService(s.serviceName) - service, err := s.client.NewService(s.serviceName, ScalingParams{}) + service, err := s.client.NewService(s.serviceName, configuration.ScalingParams{}) s.NotNil(service) s.Nil(err) } @@ -158,7 +159,7 @@ func (s *ServiceInitiationSuite) TestLoadExistingBackend() { s.Nil(err) cServers, err := s.service.GetServers() s.Nil(err) - s.Equal(baseSlots, len(s.service.nodes)) + s.Equal(baseSlots, len(s.service.GetNodes())) for i, server := range cServers { if i < len(servers) { @@ -180,7 +181,7 @@ func (s *ServiceInitiationSuite) createExistingService(servers models.Servers) e return err } for _, server := range servers { - err := s.client.CreateServer("backend", s.serviceName, server, s.transactionID, 0) + err := s.client.CreateServer(configuration.BackendParentName, s.serviceName, server, s.transactionID, 0) if err != nil { return err } @@ -197,7 +198,7 @@ func (s *ServiceInitiationSuite) createExistingService(servers models.Servers) e for i := len(servers); i < baseSlots; i++ { maintServer.Name = fmt.Sprintf("s%d", i+1) - err := s.client.CreateServer("backend", s.serviceName, maintServer, s.transactionID, 0) + err := s.client.CreateServer(configuration.BackendParentName, s.serviceName, maintServer, s.transactionID, 0) if err != nil { return err } @@ -207,10 +208,10 @@ func (s *ServiceInitiationSuite) createExistingService(servers models.Servers) e type ServiceUpdateSuit struct { suite.Suite - client Configuration + client configuration.Configuration serviceName string transactionID string - service *Service + service *configuration.Service } func (s *ServiceUpdateSuit) SetupSuite() { @@ -218,9 +219,9 @@ func (s *ServiceUpdateSuit) SetupSuite() { } func (s *ServiceUpdateSuit) BeforeTest(suiteName, testName string) { - service, err := s.client.NewService(s.serviceName, ScalingParams{ + service, err := s.client.NewService(s.serviceName, configuration.ScalingParams{ BaseSlots: baseSlots, - SlotsGrowthType: ServiceGrowthTypeLinear, + SlotsGrowthType: configuration.ServiceGrowthTypeLinear, SlotsIncrement: slotsIncrement, }) s.NotNil(service) @@ -238,7 +239,7 @@ func (s *ServiceUpdateSuit) AfterTest(suiteName, testName string) { } func (s *ServiceUpdateSuit) TestFirstUpdate() { - servers := []ServiceServer{ + servers := []configuration.ServiceServer{ {Address: "127.1.1.1", Port: 81}, {Address: "127.1.1.2", Port: 82}, {Address: "127.1.1.3", Port: 83}, @@ -250,7 +251,7 @@ func (s *ServiceUpdateSuit) TestFirstUpdate() { s.validateUpdateResult(servers) } -func (s *ServiceUpdateSuit) validateUpdateResult(expected []ServiceServer) { +func (s *ServiceUpdateSuit) validateUpdateResult(expected []configuration.ServiceServer) { servers, err := s.service.GetServers() s.Nil(err) for i, server := range servers { @@ -267,7 +268,7 @@ func (s *ServiceUpdateSuit) validateUpdateResult(expected []ServiceServer) { } func (s *ServiceUpdateSuit) TestSecondUpdateWithDeletedServer() { - servers := []ServiceServer{ + servers := []configuration.ServiceServer{ {Address: "127.1.1.1", Port: 81}, {Address: "127.1.1.2", Port: 82}, {Address: "127.1.1.3", Port: 83}, @@ -276,7 +277,7 @@ func (s *ServiceUpdateSuit) TestSecondUpdateWithDeletedServer() { r, err := s.service.Update(servers) s.True(r) s.Nil(err) - servers = []ServiceServer{ + servers = []configuration.ServiceServer{ {Address: "127.1.1.1", Port: 81}, {Address: "127.1.1.3", Port: 83}, {Address: "127.1.1.4", Port: 84}, @@ -288,7 +289,7 @@ func (s *ServiceUpdateSuit) TestSecondUpdateWithDeletedServer() { // in the middle of enabled servers. // In this case server 127.1.1.2 got removed and the last enabled server from the remaining ones // gets moved into its slot, in this case 127.1.1.4 - expected := []ServiceServer{ + expected := []configuration.ServiceServer{ {Address: "127.1.1.1", Port: 81}, {Address: "127.1.1.4", Port: 84}, {Address: "127.1.1.3", Port: 83}, @@ -297,7 +298,7 @@ func (s *ServiceUpdateSuit) TestSecondUpdateWithDeletedServer() { } func (s *ServiceUpdateSuit) TestSecondUpdateWithNewAndRemovedServers() { - servers := []ServiceServer{ + servers := []configuration.ServiceServer{ {Address: "127.1.1.1", Port: 81}, {Address: "127.1.1.2", Port: 82}, {Address: "127.1.1.3", Port: 83}, @@ -306,7 +307,7 @@ func (s *ServiceUpdateSuit) TestSecondUpdateWithNewAndRemovedServers() { r, err := s.service.Update(servers) s.True(r) s.Nil(err) - servers = []ServiceServer{ + servers = []configuration.ServiceServer{ {Address: "127.1.1.1", Port: 81}, {Address: "127.1.1.4", Port: 84}, {Address: "127.1.1.5", Port: 85}, @@ -321,7 +322,7 @@ func (s *ServiceUpdateSuit) TestSecondUpdateWithNewAndRemovedServers() { // as server 127.1.1.2 reapears at the end of the server list with the same port. // The first new server will be placed in place of server 127.1.1.3 which is 127.1.1.5. // The remaining new servers will be added to the end. - expected := []ServiceServer{ + expected := []configuration.ServiceServer{ {Address: "127.1.1.1", Port: 81}, {Address: "127.1.1.2", Port: 82}, {Address: "127.1.1.5", Port: 85}, @@ -333,7 +334,7 @@ func (s *ServiceUpdateSuit) TestSecondUpdateWithNewAndRemovedServers() { } func (s *ServiceUpdateSuit) TestSecondUpdateWithNoChanges() { - servers := []ServiceServer{ + servers := []configuration.ServiceServer{ {Address: "127.1.1.1", Port: 81}, {Address: "127.1.1.2", Port: 82}, {Address: "127.1.1.3", Port: 83}, @@ -349,9 +350,9 @@ func (s *ServiceUpdateSuit) TestSecondUpdateWithNoChanges() { func (s *ServiceUpdateSuit) TestUpdateScalingParams() { newBaseSlots := 30 - err := s.service.UpdateScalingParams(ScalingParams{ + err := s.service.UpdateScalingParams(configuration.ScalingParams{ BaseSlots: newBaseSlots, - SlotsGrowthType: ServiceGrowthTypeLinear, + SlotsGrowthType: configuration.ServiceGrowthTypeLinear, SlotsIncrement: slotsIncrement, }) s.Nil(err) @@ -372,10 +373,10 @@ func (s *ServiceUpdateSuit) TestLinearUpscaling() { s.validateUpdateResult(expected) } -func (s *ServiceUpdateSuit) generateServers(count int) []ServiceServer { - servers := make([]ServiceServer, 0) +func (s *ServiceUpdateSuit) generateServers(count int) []configuration.ServiceServer { + servers := make([]configuration.ServiceServer, 0) for i := 0; i < count; i++ { - servers = append(servers, ServiceServer{ + servers = append(servers, configuration.ServiceServer{ Address: fmt.Sprintf("127.1.1.%d", i), Port: 80 + i, }) @@ -386,9 +387,9 @@ func (s *ServiceUpdateSuit) generateServers(count int) []ServiceServer { func (s *ServiceUpdateSuit) TestExponentialUpscaling() { expectedSlotsCount := baseSlots * 2 // Switch from linear to exponential scaling - err := s.service.UpdateScalingParams(ScalingParams{ + err := s.service.UpdateScalingParams(configuration.ScalingParams{ BaseSlots: baseSlots, - SlotsGrowthType: ServiceGrowthTypeExponential, + SlotsGrowthType: configuration.ServiceGrowthTypeExponential, SlotsIncrement: slotsIncrement, }) s.Nil(err) @@ -426,9 +427,9 @@ func (s *ServiceUpdateSuit) scaleServiceAndValidate(expectedSlots, serverCount i func (s *ServiceUpdateSuit) TestExponentialDownscaling() { // Switch from linear to exponential scaling - err := s.service.UpdateScalingParams(ScalingParams{ + err := s.service.UpdateScalingParams(configuration.ScalingParams{ BaseSlots: baseSlots, - SlotsGrowthType: ServiceGrowthTypeExponential, + SlotsGrowthType: configuration.ServiceGrowthTypeExponential, SlotsIncrement: slotsIncrement, }) s.Nil(err) diff --git a/configuration/site_test.go b/test/site_test.go similarity index 99% rename from configuration/site_test.go rename to test/site_test.go index 9db7b0fd..a65d10a4 100644 --- a/configuration/site_test.go +++ b/test/site_test.go @@ -13,7 +13,7 @@ // limitations under the License. // -package configuration +package test import ( "fmt" diff --git a/configuration/stick_rule_test.go b/test/stick_rule_test.go similarity index 57% rename from configuration/stick_rule_test.go rename to test/stick_rule_test.go index 9e3ce87f..0d9031ce 100644 --- a/configuration/stick_rule_test.go +++ b/test/stick_rule_test.go @@ -13,110 +13,72 @@ // limitations under the License. // -package configuration +package test import ( "fmt" "reflect" "testing" + "github.com/google/go-cmp/cmp" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +func stickRuleExpectation() map[string]models.StickRules { + initStructuredExpected() + res := StructuredToStickRuleMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%d", k, *v.Index) + res[key] = models.StickRules{v} + } + } + return res +} + func TestGetStickRules(t *testing.T) { //nolint:gocognit,gocyclo + mrules := make(map[string]models.StickRules) v, sRules, err := clientTest.GetStickRules("test", "") if err != nil { t.Error(err.Error()) } - - if len(sRules) != 6 { - t.Errorf("%v stick rules returned, expected 6", len(sRules)) - } + mrules["backend/test"] = sRules if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - for _, sr := range sRules { - switch *sr.Index { - case 0: - if sr.Type != "store-request" { - t.Errorf("%v: Type not store-request: %v", *sr.Index, sr.Type) - } - if sr.Pattern != "src" { - t.Errorf("%v: Pattern not src: %v", *sr.Index, sr.Pattern) - } - if sr.Table != "test" { - t.Errorf("%v: Table not test: %v", *sr.Index, sr.Table) - } - case 1: - if sr.Type != "match" { - t.Errorf("%v: Type not match: %v", *sr.Index, sr.Type) - } - if sr.Pattern != "src" { - t.Errorf("%v: Pattern not src: %v", *sr.Index, sr.Pattern) - } - if sr.Table != "test" { - t.Errorf("%v: Table not test: %v", *sr.Index, sr.Table) - } - case 2: - if sr.Type != "on" { - t.Errorf("%v: Type not on: %v", *sr.Index, sr.Type) - } - if sr.Pattern != "src" { - t.Errorf("%v: Pattern not src: %v", *sr.Index, sr.Pattern) - } - if sr.Table != "test" { - t.Errorf("%v: Table not test: %v", *sr.Index, sr.Table) - } - case 3: - if sr.Type != "store-response" { - t.Errorf("%v: Type not matchandstore: %v", *sr.Index, sr.Type) - } - if sr.Pattern != "src" { - t.Errorf("%v: Pattern not src: %v", *sr.Index, sr.Pattern) - } - case 4: - if sr.Type != "store-response" { - t.Errorf("%v: Type not matchandstore: %v", *sr.Index, sr.Type) - } - if sr.Pattern != "src_port" { - t.Errorf("%v: Pattern not src: %v", *sr.Index, sr.Pattern) - } - if sr.Table != "test_port" { - t.Errorf("%v: Table not test: %v", *sr.Index, sr.Table) - } - case 5: - if sr.Type != "store-response" { - t.Errorf("%v: Type not matchandstore: %v", *sr.Index, sr.Type) - } - if sr.Pattern != "src" { - t.Errorf("%v: Pattern not src: %v", *sr.Index, sr.Pattern) - } - if sr.Table != "test" { - t.Errorf("%v: Table not test: %v", *sr.Index, sr.Table) - } - if sr.Cond != "if" { - t.Errorf("%v: Cond not if: %v", *sr.Index, sr.Cond) - } - if sr.CondTest != "TRUE" { - t.Errorf("%v: Cond not if: %v", *sr.Index, sr.CondTest) - } - default: - t.Errorf("Expect only stick rule < 5, %v found", *sr.Index) - } - } - _, sRules, err = clientTest.GetStickRules("test_2", "") if err != nil { t.Error(err.Error()) } - if len(sRules) > 0 { - t.Errorf("%v stick rules returned, expected 0", len(sRules)) + mrules["backend/test_2"] = sRules + + checkStickRules(t, mrules) +} + +func checkStickRules(t *testing.T, got map[string]models.StickRules) { + exp := stickRuleExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } } } func TestGetStickRule(t *testing.T) { + m := make(map[string]models.StickRules) + v, sr, err := clientTest.GetStickRule(0, "test", "") if err != nil { t.Error(err.Error()) @@ -125,16 +87,8 @@ func TestGetStickRule(t *testing.T) { if v != version { t.Errorf("Version %v returned, expected %v", v, version) } - - if sr.Type != "store-request" { - t.Errorf("%v: Type not store-request: %v", *sr.Index, sr.Type) - } - if sr.Pattern != "src" { - t.Errorf("%v: Pattern not src: %v", *sr.Index, sr.Pattern) - } - if sr.Table != "test" { - t.Errorf("%v: Table not test: %v", *sr.Index, sr.Table) - } + m["backend/test/0"] = models.StickRules{sr} + checkStickRules(t, m) _, err = sr.MarshalBinary() if err != nil { diff --git a/configuration/table_test.go b/test/table_test.go similarity index 99% rename from configuration/table_test.go rename to test/table_test.go index a472cc9f..bbd0658b 100644 --- a/configuration/table_test.go +++ b/test/table_test.go @@ -13,7 +13,7 @@ // limitations under the License. // -package configuration +package test import ( "fmt" diff --git a/configuration/tcp_check_test.go b/test/tcp_check_test.go similarity index 78% rename from configuration/tcp_check_test.go rename to test/tcp_check_test.go index 22066e3f..6db7cdf1 100644 --- a/configuration/tcp_check_test.go +++ b/test/tcp_check_test.go @@ -13,15 +13,33 @@ // limitations under the License. // -package configuration +package test import ( + "fmt" "io/ioutil" "testing" + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" ) +// The one from configuration_test.go +func tcpCheckExpectation() map[string]models.TCPChecks { + initStructuredExpected() + res := StructuredToTCPCheckMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%d", k, *v.Index) + res[key] = models.TCPChecks{v} + } + } + return res +} + func generateTCPCheckConfig(config string) (string, error) { f, err := ioutil.TempFile("/tmp", "tcp_check") if err != nil { @@ -120,7 +138,7 @@ backend test return } - _, checks, err := c.GetTCPChecks("backend", "test", "") + _, checks, err := c.GetTCPChecks(configuration.BackendParentName, "test", "") if err != nil { t.Error(err.Error()) } @@ -131,17 +149,17 @@ backend test counter := Counter{0} - _, check, err := c.GetTCPCheck(0, "backend", "test", "") + _, check, err := c.GetTCPCheck(0, configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionConnect { t.Errorf("Check action %v returned, expected %v", check.Action, models.TCPCheckActionConnect) } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionComment { t.Errorf("Check action %v returned, expected %v", check.Action, models.TCPCheckActionComment) } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionSend { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionSend) } @@ -149,7 +167,7 @@ backend test t.Errorf("tcp-check action data is invalid") } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionSend { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionSend) } @@ -157,7 +175,7 @@ backend test t.Errorf("tcp-check action data is invalid") } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionSend { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionSend) } @@ -165,12 +183,12 @@ backend test t.Errorf("tcp-check action data is invalid") } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionExpect { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionExpect) } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionConnect { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionConnect) } @@ -181,7 +199,7 @@ backend test t.Errorf("tcp-check action data is invalid") } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionSend { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionSend) } @@ -189,7 +207,7 @@ backend test t.Errorf("tcp-check action data is invalid") } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionSend { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionSend) } @@ -197,7 +215,7 @@ backend test t.Errorf("tcp-check action data is invalid") } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionSend { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionSend) } @@ -205,7 +223,7 @@ backend test t.Errorf("tcp-check action data is invalid") } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionExpect { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionExpect) } @@ -216,7 +234,7 @@ backend test t.Errorf("tcp-check expect pattern %v returned, expected %v", check.Pattern, "(2..|3..)") } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionSendDashBinary { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionSendDashBinary) } @@ -227,12 +245,12 @@ backend test t.Errorf("tcp-check send-binary comment %v returned, expected %v", check.CheckComment, "send-binary-comment") } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionExpect { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionExpect) } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionSendDashBinaryDashLf { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionSendDashBinaryDashLf) } @@ -240,24 +258,24 @@ backend test t.Errorf("tcp-check action data is invalid") } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionExpect { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionExpect) } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionSetDashVar { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionSetDashVar) } if check.VarScope != "req" { } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionUnsetDashVar { t.Errorf("tcp-check action data is invalid") } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionSendDashLf { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionSendDashLf) } @@ -265,7 +283,7 @@ backend test t.Errorf("tcp-check %v - fmt data is invalid", models.TCPCheckActionSendDashLf) } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionSendDashLf { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionSendDashLf) } @@ -276,7 +294,7 @@ backend test t.Errorf("tcp-check action comment data is invalid") } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionSetDashVarDashFmt { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionSetDashVarDashFmt) } @@ -289,7 +307,7 @@ backend test if check.VarFmt != `"%H"` { t.Errorf("tcp-check set-var-fmt format returned %v, expected %v", check.VarFmt, `"%H"`) } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionSetDashVarDashFmt { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionSetDashVarDashFmt) } @@ -303,7 +321,7 @@ backend test t.Errorf("tcp-check set-var-fmt fmt returned %v, expected %v", check.VarFmt, `"addr=%[src]:%[src_port]"`) } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionConnect { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionConnect) } @@ -335,7 +353,7 @@ backend test t.Errorf("tcp-check connect linger missing") } - _, check, err = c.GetTCPCheck(counter.increment(), "backend", "test", "") + _, check, err = c.GetTCPCheck(counter.increment(), configuration.BackendParentName, "test", "") if check.Action != models.TCPCheckActionExpect { t.Errorf("tcp-check action %v returned, expected %v", check.Action, models.TCPCheckActionExpect) } @@ -372,3 +390,20 @@ backend test }) } } + +func checkTCPChecks(t *testing.T, got map[string]models.TCPChecks) { + exp := tcpCheckExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} diff --git a/test/tcp_request_rule_test.go b/test/tcp_request_rule_test.go new file mode 100644 index 00000000..93f802cc --- /dev/null +++ b/test/tcp_request_rule_test.go @@ -0,0 +1,412 @@ +// 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. +// + +package test + +import ( + "fmt" + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/configuration" + "github.com/haproxytech/client-native/v5/misc" + "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" +) + +func tcpRequestRuleExpectation() map[string]models.TCPRequestRules { + initStructuredExpected() + res := StructuredToTCPRequestRuleMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%d", k, *v.Index) + res[key] = models.TCPRequestRules{v} + } + } + return res +} + +func TestGetTCPRequestRules(t *testing.T) { //nolint:gocognit,gocyclo + mrules := make(map[string]models.TCPRequestRules) + v, tRules, err := clientTest.GetTCPRequestRules(configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + mrules["frontend/test"] = tRules + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + _, tRules, err = clientTest.GetTCPRequestRules(configuration.BackendParentName, "test_2", "") + if err != nil { + t.Error(err.Error()) + } + mrules["backend/test_2"] = tRules + + checkTCPRequestRules(t, mrules) +} + +func TestGetTCPRequestRule(t *testing.T) { + m := make(map[string]models.TCPRequestRules) + + v, r, err := clientTest.GetTCPRequestRule(0, configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + m["frontend/test/0"] = models.TCPRequestRules{r} + + checkTCPRequestRules(t, m) + + _, err = r.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + _, _, err = clientTest.GetTCPRequestRule(3, configuration.BackendParentName, "test_2", "") + if err == nil { + t.Error("Should throw error, non existent TCP Request Rule") + } +} + +func checkTCPRequestRules(t *testing.T, got map[string]models.TCPRequestRules) { + exp := tcpRequestRuleExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + +func TestCreateEditDeleteTCPRequestRule(t *testing.T) { + id := int64(4) + tOut := int64(1000) + // TestCreateTCPRequestRule + r := &models.TCPRequestRule{ + Index: &id, + Type: "inspect-delay", + Timeout: &tOut, + } + + err := clientTest.CreateTCPRequestRule(configuration.FrontendParentName, "test", r, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, ondiskR, err := clientTest.GetTCPRequestRule(4, configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(ondiskR, r) { + fmt.Printf("Created TCP request rule: %v\n", ondiskR) + fmt.Printf("Given TCP request rule: %v\n", r) + t.Error("Created TCP request rule not equal to given TCP request rule") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestEditTCPRequestRule + r = &models.TCPRequestRule{ + Index: &id, + Type: "connection", + Action: "accept", + Cond: "if", + CondTest: "FALSE", + } + + err = clientTest.EditTCPRequestRule(4, configuration.FrontendParentName, "test", r, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, ondiskR, err = clientTest.GetTCPRequestRule(4, configuration.FrontendParentName, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(ondiskR, r) { + fmt.Printf("Edited TCP request rule: %v\n", ondiskR) + fmt.Printf("Given TCP request rule: %v\n", r) + t.Error("Edited TCP request rule not equal to given TCP request rule") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestDeleteTCPRequest + err = clientTest.DeleteTCPRequestRule(33, configuration.FrontendParentName, "test", "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + if v, _ := clientTest.GetVersion(""); v != version { + t.Error("Version not incremented") + } + + _, _, err = clientTest.GetTCPRequestRule(33, configuration.FrontendParentName, "test", "") + if err == nil { + t.Error("DeleteTCPRequestRule failed, TCP Request Rule 33 still exists") + } + + err = clientTest.DeleteTCPRequestRule(27, configuration.BackendParentName, "test_2", "", version) + if err == nil { + t.Error("Should throw error, non existent TCP Request Rule") + version++ + } +} + +func TestSerializeTCPRequestRule(t *testing.T) { + testCases := []struct { + input models.TCPRequestRule + expectedResult string + }{ + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeConnection, + Action: models.TCPRequestRuleActionSilentDashDrop, + Cond: "if", + CondTest: "FALSE", + }, + expectedResult: "connection silent-drop if FALSE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeContent, + Action: models.TCPRequestRuleActionSilentDashDrop, + Cond: "if", + CondTest: "FALSE", + }, + expectedResult: "content silent-drop if FALSE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeSession, + Action: models.TCPRequestRuleActionSilentDashDrop, + Cond: "if", + CondTest: "FALSE", + }, + expectedResult: "session silent-drop if FALSE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeConnection, + Action: models.TCPRequestRuleActionExpectDashProxy, + Cond: "if", + CondTest: "{ src 1.2.3.4 5.6.7.8 }", + }, + expectedResult: "connection expect-proxy layer4 if { src 1.2.3.4 5.6.7.8 }", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeConnection, + Action: models.TCPRequestRuleActionTrackDashSc, + Cond: "if", + CondTest: "TRUE", + TrackKey: "src", + TrackTable: "tr0", + TrackStickCounter: misc.Int64P(3), + }, + expectedResult: "connection track-sc3 src table tr0 if TRUE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeConnection, + Action: models.TCPRequestRuleActionTrackDashSc0, + Cond: "if", + CondTest: "TRUE", + TrackKey: "src", + TrackTable: "tr0", + }, + expectedResult: "connection track-sc0 src table tr0 if TRUE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeConnection, + Action: models.TCPRequestRuleActionTrackDashSc1, + Cond: "if", + CondTest: "TRUE", + TrackKey: "src", + TrackTable: "tr1", + }, + expectedResult: "connection track-sc1 src table tr1 if TRUE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeConnection, + Action: models.TCPRequestRuleActionTrackDashSc2, + Cond: "if", + CondTest: "TRUE", + TrackKey: "src", + TrackTable: "tr2", + }, + expectedResult: "connection track-sc2 src table tr2 if TRUE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeContent, + Action: models.TCPRequestRuleActionTrackDashSc, + Cond: "if", + CondTest: "TRUE", + TrackKey: "src", + TrackTable: "tr0", + TrackStickCounter: misc.Int64P(3), + }, + expectedResult: "content track-sc3 src table tr0 if TRUE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeContent, + Action: models.TCPRequestRuleActionTrackDashSc0, + Cond: "if", + CondTest: "TRUE", + TrackKey: "src", + TrackTable: "tr0", + }, + expectedResult: "content track-sc0 src table tr0 if TRUE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeContent, + Action: models.TCPRequestRuleActionTrackDashSc1, + Cond: "if", + CondTest: "TRUE", + TrackKey: "src", + TrackTable: "tr1", + }, + expectedResult: "content track-sc1 src table tr1 if TRUE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeContent, + Action: models.TCPRequestRuleActionTrackDashSc2, + Cond: "if", + CondTest: "TRUE", + TrackKey: "src", + TrackTable: "tr2", + }, + expectedResult: "content track-sc2 src table tr2 if TRUE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeSession, + Action: models.TCPRequestRuleActionTrackDashSc, + Cond: "if", + CondTest: "TRUE", + TrackKey: "src", + TrackTable: "tr0", + TrackStickCounter: misc.Int64P(3), + }, + expectedResult: "session track-sc3 src table tr0 if TRUE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeSession, + Action: models.TCPRequestRuleActionTrackDashSc0, + Cond: "if", + CondTest: "TRUE", + TrackKey: "src", + TrackTable: "tr0", + }, + expectedResult: "session track-sc0 src table tr0 if TRUE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeSession, + Action: models.TCPRequestRuleActionTrackDashSc1, + Cond: "if", + CondTest: "TRUE", + TrackKey: "src", + TrackTable: "tr1", + }, + expectedResult: "session track-sc1 src table tr1 if TRUE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeSession, + Action: models.TCPRequestRuleActionTrackDashSc2, + Cond: "if", + CondTest: "TRUE", + TrackKey: "src", + TrackTable: "tr2", + }, + expectedResult: "session track-sc2 src table tr2 if TRUE", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeSession, + Action: models.TCPRequestRuleActionAttachDashSrv, + ServerName: "srv8", + Expr: "haproxy.org", + }, + expectedResult: "session attach-srv srv8 name haproxy.org", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeSession, + Action: models.TCPRequestRuleActionAttachDashSrv, + ServerName: "srv8", + }, + expectedResult: "session attach-srv srv8", + }, + { + input: models.TCPRequestRule{ + Type: models.TCPRequestRuleTypeSession, + Action: models.TCPRequestRuleActionAttachDashSrv, + ServerName: "srv8", + Cond: "unless", + CondTest: "limit_exceeded", + }, + expectedResult: "session attach-srv srv8 unless limit_exceeded", + }, + } + + for _, testCase := range testCases { + t.Run(testCase.expectedResult, func(t *testing.T) { + tcpType, err := configuration.SerializeTCPRequestRule(testCase.input) + if err != nil { + t.Error(err.Error()) + } + + actual := tcpType.String() + if actual != testCase.expectedResult { + t.Errorf("Expected %q, got: %q", testCase.expectedResult, actual) + } + }) + } +} diff --git a/test/tcp_response_rule_test.go b/test/tcp_response_rule_test.go new file mode 100644 index 00000000..97f127f9 --- /dev/null +++ b/test/tcp_response_rule_test.go @@ -0,0 +1,190 @@ +// 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. +// + +package test + +import ( + "fmt" + "reflect" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/haproxytech/client-native/v5/models" + "github.com/stretchr/testify/require" +) + +func tcpResponseRuleExpectation() map[string]models.TCPResponseRules { + initStructuredExpected() + res := StructuredToTCPResponseRuleMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%d", k, *v.Index) + res[key] = models.TCPResponseRules{v} + } + } + return res +} + +func TestGetTCPResponseRules(t *testing.T) { //nolint:gocognit + mrules := make(map[string]models.TCPResponseRules) + v, tRules, err := clientTest.GetTCPResponseRules("test", "") + if err != nil { + t.Error(err.Error()) + } + mrules["backend/test"] = tRules + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + _, tRules, err = clientTest.GetTCPResponseRules("test_2", "") + if err != nil { + t.Error(err.Error()) + } + mrules["backend/test_2"] = tRules + + checkTCPResponseRules(t, mrules) +} + +func checkTCPResponseRules(t *testing.T, got map[string]models.TCPResponseRules) { + exp := tcpResponseRuleExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if *g.Index == *w.Index { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} + +func TestGetTCPResponseRule(t *testing.T) { + m := make(map[string]models.TCPResponseRules) + + v, r, err := clientTest.GetTCPResponseRule(0, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + m["backend/test/0"] = models.TCPResponseRules{r} + + checkTCPResponseRules(t, m) + + _, err = r.MarshalBinary() + if err != nil { + t.Error(err.Error()) + } + + _, _, err = clientTest.GetTCPResponseRule(3, "test_2", "") + if err == nil { + t.Error("Should throw error, non existent TCP Response Rule") + } +} + +func TestCreateEditDeleteTCPResponseRule(t *testing.T) { + id := int64(2) + tOut := int64(1000) + // TestCreateTCPResponseRule + r := &models.TCPResponseRule{ + Index: &id, + Type: "inspect-delay", + Timeout: &tOut, + } + + err := clientTest.CreateTCPResponseRule("test", r, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, ondiskR, err := clientTest.GetTCPResponseRule(2, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(ondiskR, r) { + fmt.Printf("Created TCP response rule: %v\n", ondiskR) + fmt.Printf("Given TCP response rule: %v\n", r) + t.Error("Created TCP response rule not equal to given TCP response rule") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestEditTCPResponseRule + r = &models.TCPResponseRule{ + Index: &id, + Type: "content", + Action: "accept", + Cond: "if", + CondTest: "FALSE", + } + + err = clientTest.EditTCPResponseRule(2, "test", r, "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + v, ondiskR, err = clientTest.GetTCPResponseRule(2, "test", "") + if err != nil { + t.Error(err.Error()) + } + + if !reflect.DeepEqual(ondiskR, r) { + fmt.Printf("Edited TCP response rule: %v\n", ondiskR) + fmt.Printf("Given TCP response rule: %v\n", r) + t.Error("Edited TCP response rule not equal to given TCP response rule") + } + + if v != version { + t.Errorf("Version %v returned, expected %v", v, version) + } + + // TestDeleteTCPResponse + err = clientTest.DeleteTCPResponseRule(18, "test", "", version) + if err != nil { + t.Error(err.Error()) + } else { + version++ + } + + if v, _ := clientTest.GetVersion(""); v != version { + t.Error("Version not incremented") + } + + _, _, err = clientTest.GetTCPResponseRule(18, "test", "") + if err == nil { + t.Error("DeleteTCPResponseRule failed, TCP Response Rule 17 still exists") + } + + err = clientTest.DeleteTCPResponseRule(18, "test_2", "", version) + if err == nil { + t.Error("Should throw error, non existent TCP Response Rule") + version++ + } +} diff --git a/configuration/user_test.go b/test/user_test.go similarity index 73% rename from configuration/user_test.go rename to test/user_test.go index 7e23a465..e59f63fd 100644 --- a/configuration/user_test.go +++ b/test/user_test.go @@ -13,20 +13,35 @@ // limitations under the License. // -package configuration +package test import ( - "io/ioutil" + "fmt" + "os" "testing" + "github.com/google/go-cmp/cmp" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/haproxytech/client-native/v5/models" ) +func userExpectation() map[string]models.Users { + initStructuredExpected() + res := StructuredToUserMap() + // Add individual entries + for k, vs := range res { + for _, v := range vs { + key := fmt.Sprintf("%s/%s", k, v.Username) + res[key] = models.Users{v} + } + } + return res +} + func generateUserConfig(config string) (string, error) { - f, err := ioutil.TempFile("/tmp", "user") + f, err := os.CreateTemp("/tmp", "user") if err != nil { return "", err } @@ -104,6 +119,7 @@ userlist delete_test t.Errorf("prepareClient error = %v, wantErr %v", err, tt.wantErr) return } + m := make(map[string]models.Users) // fetch tests users _, users, err := c.GetUsers("first", "") @@ -116,6 +132,9 @@ userlist delete_test if len(users) != 2 { t.Errorf("Expected 2 users in the userlist, found %v", len(users)) } + for _, v := range users { + m[fmt.Sprintf("userlist/first/%s", v.Username)] = models.Users{v} + } _, users, err = c.GetUsers("second", "") if err != nil { @@ -127,6 +146,10 @@ userlist delete_test if len(users) != 3 { t.Errorf("Expected 3 users in the userlist, found %v", len(users)) } + for _, v := range users { + m[fmt.Sprintf("userlist/second/%s", v.Username)] = models.Users{v} + } + checkUsers(t, m) _, users, err = c.GetUsers("empty", "") if err != nil { @@ -149,24 +172,14 @@ userlist delete_test // fetch test, single user - userlist first _, user, err := c.GetUser("tiger", "first", "") + clear(m) if err != nil { t.Error(err.Error()) } if user == nil { t.Errorf("Expected an user instead of nil") } - if user.Username != "tiger" { - t.Errorf("Username %v returned, expected %v", user.Username, "tiger") - } - if *user.SecurePassword == false { - t.Errorf("Non secure password returned, expected secure") - } - if user.Password != "$6$k6y3o.eP$JlKBx9za9667qe4xHSwRv6J.C0/D7cV91" { - t.Errorf("Password %v returned, expected %v", user.Password, "$6$k6y3o.eP$JlKBx9za9667qe4xHSwRv6J.C0/D7cV91") - } - if user.Groups != "" { - t.Errorf("Groups %v returned, expected %v", user.Groups, "") - } + m["userlist/first/tiger"] = models.Users{user} _, user, err = c.GetUser("scott", "first", "") if err != nil { @@ -175,18 +188,7 @@ userlist delete_test if user == nil { t.Errorf("Expected an user instead of nil") } - if user.Username != "scott" { - t.Errorf("Username %v returned, expected %v", user.Username, "scott") - } - if *user.SecurePassword == true { - t.Errorf("Secure password returned, expected non secure") - } - if user.Password != "elgato" { - t.Errorf("Password %v returned, expected %v", user.Password, "elgato") - } - if user.Groups != "" { - t.Errorf("Groups %v returned, expected %v", user.Groups, "") - } + m["userlist/first/scott"] = models.Users{user} _, user, err = c.GetUser("dummy", "first", "") if user != nil { @@ -206,18 +208,7 @@ userlist delete_test if user == nil { t.Errorf("Expected an user instead of nil") } - if user.Username != "neo" { - t.Errorf("Username %v returned, expected %v", user.Username, "neo") - } - if *user.SecurePassword == false { - t.Errorf("Non secure password returned, expected secure") - } - if user.Password != "$6$k6y3o.eP$JlKBxxHSwRv6J.C0/D7cV91" { - t.Errorf("Password %v returned, expected %v", user.Password, "$6$k6y3o.eP$JlKBxxHSwRv6J.C0/D7cV91") - } - if user.Groups != "one" { - t.Errorf("Groups %v returned, expected %v", user.Groups, "one") - } + m["userlist/second/neo"] = models.Users{user} _, user, err = c.GetUser("thomas", "second", "") if err != nil { @@ -226,18 +217,7 @@ userlist delete_test if user == nil { t.Errorf("Expected an user instead of nil") } - if user.Username != "thomas" { - t.Errorf("Username %v returned, expected %v", user.Username, "thomas") - } - if *user.SecurePassword == true { - t.Errorf("Secure password returned, expected non secure") - } - if user.Password != "white-rabbit" { - t.Errorf("Password %v returned, expected %v", user.Password, "white-rabbit") - } - if user.Groups != "one,two" { - t.Errorf("Groups %v returned, expected %v", user.Groups, "one,two") - } + m["userlist/second/thomas"] = models.Users{user} _, user, err = c.GetUser("anderson", "second", "") if err != nil { @@ -246,18 +226,7 @@ userlist delete_test if user == nil { t.Errorf("Expected an user instead of nil") } - if user.Username != "anderson" { - t.Errorf("Username %v returned, expected %v", user.Username, "anderson") - } - if *user.SecurePassword == true { - t.Errorf("Secure password returned, expected non secure") - } - if user.Password != "hello" { - t.Errorf("Password %v returned, expected %v", user.Password, "hello") - } - if user.Groups != "two" { - t.Errorf("Groups %v returned, expected %v", user.Groups, "two") - } + m["userlist/second/anderson"] = models.Users{user} _, user, err = c.GetUser("third", "second", "") if user != nil { @@ -277,6 +246,8 @@ userlist delete_test t.Errorf("Expected 0 users in the userlist, found %v", len(users)) } + checkUsers(t, m) + // test add securePassword := false add := models.User{ @@ -322,3 +293,20 @@ userlist delete_test }) } } + +func checkUsers(t *testing.T, got map[string]models.Users) { + exp := userExpectation() + for k, v := range got { + want, ok := exp[k] + require.True(t, ok, "k=%s", k) + require.Equal(t, len(want), len(v), "k=%s", k) + for _, g := range v { + for _, w := range want { + if g.Username == w.Username { + require.True(t, g.Equal(*w), "k=%s - diff %v", k, cmp.Diff(*g, *w)) + break + } + } + } + } +} diff --git a/configuration/userlist_test.go b/test/userlist_test.go similarity index 99% rename from configuration/userlist_test.go rename to test/userlist_test.go index 6e9786de..000e359c 100644 --- a/configuration/userlist_test.go +++ b/test/userlist_test.go @@ -13,7 +13,7 @@ // limitations under the License. // -package configuration +package test import ( "io/ioutil" diff --git a/configuration/version_test.go b/test/version_test.go similarity index 99% rename from configuration/version_test.go rename to test/version_test.go index c819c307..05bf1e41 100644 --- a/configuration/version_test.go +++ b/test/version_test.go @@ -13,7 +13,7 @@ // limitations under the License. // -package configuration +package test import ( "io/ioutil"