diff --git a/configuration/configuration.go b/configuration/configuration.go index b9091f8d..35232bb2 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -1158,7 +1158,7 @@ func (s *SectionParser) monitorFail() interface{} { return nil } -func (s *SectionParser) compression() interface{} { +func (s *SectionParser) compression() interface{} { //nolint:gocognit compressionFound := false compression := &models.Compression{} @@ -1172,6 +1172,24 @@ func (s *SectionParser) compression() interface{} { } } + data, err = s.get("compression algo-req", false) + if err == nil { + d, ok := data.(*types.StringC) + if ok && d != nil { + compressionFound = true + compression.AlgoReq = d.Value + } + } + + data, err = s.get("compression algo-res", false) + if err == nil { + d, ok := data.(*types.StringSliceC) + if ok && d != nil && len(d.Value) > 0 { + compressionFound = true + compression.AlgosRes = d.Value + } + } + data, err = s.get("compression type", false) if err == nil { d, ok := data.(*types.StringSliceC) @@ -1181,6 +1199,24 @@ func (s *SectionParser) compression() interface{} { } } + data, err = s.get("compression type-req", false) + if err == nil { + d, ok := data.(*types.StringSliceC) + if ok && d != nil && len(d.Value) > 0 { + compressionFound = true + compression.TypesReq = d.Value + } + } + + data, err = s.get("compression type-res", false) + if err == nil { + d, ok := data.(*types.StringSliceC) + if ok && d != nil && len(d.Value) > 0 { + compressionFound = true + compression.TypesRes = d.Value + } + } + data, err = s.get("compression offload", false) if err == nil { d, ok := data.(*types.Enabled) @@ -2618,17 +2654,33 @@ func (s *SectionObject) statsOptions(field reflect.Value) error { return s.set("stats", ss) } -func (s *SectionObject) compression(field reflect.Value) error { +func (s *SectionObject) compression(field reflect.Value) error { //nolint:gocognit var err error if valueIsNil(field) { err = s.set("compression algo", nil) if err != nil { return err } + err = s.set("compression algo-req", nil) + if err != nil { + return err + } + err = s.set("compression algo-res", nil) + if err != nil { + return err + } err = s.set("compression type", nil) if err != nil { return err } + err = s.set("compression type-req", nil) + if err != nil { + return err + } + err = s.set("compression type-res", nil) + if err != nil { + return err + } err = s.set("compression offload", nil) if err != nil { return err @@ -2656,12 +2708,36 @@ func (s *SectionObject) compression(field reflect.Value) error { return err } } + if len(compression.AlgoReq) > 0 { + err = s.set("compression algo-req", &types.StringC{Value: compression.AlgoReq}) + if err != nil { + return err + } + } + if len(compression.AlgosRes) > 0 { + err = s.set("compression algo-res", &types.StringSliceC{Value: compression.AlgosRes}) + if err != nil { + return err + } + } if len(compression.Types) > 0 { err = s.set("compression type", &types.StringSliceC{Value: compression.Types}) if err != nil { return err } } + if len(compression.TypesReq) > 0 { + err = s.set("compression type-req", &types.StringSliceC{Value: compression.TypesReq}) + if err != nil { + return err + } + } + if len(compression.TypesRes) > 0 { + err = s.set("compression type-res", &types.StringSliceC{Value: compression.TypesRes}) + if err != nil { + return err + } + } if compression.Offload { err = s.set("compression offload", &types.Enabled{}) if err != nil { diff --git a/go.mod b/go.mod index 04b71f92..3c7e9ba8 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/google/renameio v1.0.1 github.com/google/uuid v1.6.0 - github.com/haproxytech/config-parser/v5 v5.1.1-0.20240220100901-1145ec548975 + github.com/haproxytech/config-parser/v5 v5.1.1-0.20240221073837-5b782186def2 github.com/json-iterator/go v1.1.12 github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 github.com/mitchellh/mapstructure v1.5.0 diff --git a/go.sum b/go.sum index 5f9c1257..976f11b1 100644 --- a/go.sum +++ b/go.sum @@ -34,8 +34,8 @@ github.com/google/renameio v1.0.1 h1:Lh/jXZmvZxb0BBeSY5VKEfidcbcbenKjZFzM/q0fSeU github.com/google/renameio v1.0.1/go.mod h1:t/HQoYBZSsWSNK35C6CO/TpPLDVWvxOHboWUAweKUpk= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/haproxytech/config-parser/v5 v5.1.1-0.20240220100901-1145ec548975 h1:CL/3SEvayajAyRHHOmKLsqiwZ8SVwAstCbKEvuxNknI= -github.com/haproxytech/config-parser/v5 v5.1.1-0.20240220100901-1145ec548975/go.mod h1:iy8nBB1eopwYbyeh3FQpjxZUxfcIDyTV9bW0F1t+cVA= +github.com/haproxytech/config-parser/v5 v5.1.1-0.20240221073837-5b782186def2 h1:YXI/15X8xJPrnyO8brmiNaFhOD17Ib9nszHRrlEtuIw= +github.com/haproxytech/config-parser/v5 v5.1.1-0.20240221073837-5b782186def2/go.mod h1:iy8nBB1eopwYbyeh3FQpjxZUxfcIDyTV9bW0F1t+cVA= github.com/haproxytech/go-logger v1.1.0 h1:HgGtYaI1ApkvbQdsm7f9AzQQoxTB7w37criTflh7IQE= github.com/haproxytech/go-logger v1.1.0/go.mod h1:OekUd8HCb7ubxMplzHUPBTHNxZmddOWfOjWclZsqIeM= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= diff --git a/models/compression.go b/models/compression.go index 011fa4be..46e6c7aa 100644 --- a/models/compression.go +++ b/models/compression.go @@ -35,10 +35,17 @@ import ( // // swagger:model compression type Compression struct { + // algo req + // Enum: [identity gzip deflate raw-deflate] + // +kubebuilder:validation:Enum=identity;gzip;deflate;raw-deflate; + AlgoReq string `json:"algo-req,omitempty"` // algorithms Algorithms []string `json:"algorithms,omitempty"` + // algos res + AlgosRes []string `json:"algos-res,omitempty"` + // direction // Enum: [request response both] // +kubebuilder:validation:Enum=request;response;both; @@ -49,16 +56,30 @@ type Compression struct { // types Types []string `json:"types,omitempty"` + + // types req + TypesReq []string `json:"types-req,omitempty"` + + // types res + TypesRes []string `json:"types-res,omitempty"` } // Validate validates this compression func (m *Compression) Validate(formats strfmt.Registry) error { var res []error + if err := m.validateAlgoReq(formats); err != nil { + res = append(res, err) + } + if err := m.validateAlgorithms(formats); err != nil { res = append(res, err) } + if err := m.validateAlgosRes(formats); err != nil { + res = append(res, err) + } + if err := m.validateDirection(formats); err != nil { res = append(res, err) } @@ -69,6 +90,54 @@ func (m *Compression) Validate(formats strfmt.Registry) error { return nil } +var compressionTypeAlgoReqPropEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["identity","gzip","deflate","raw-deflate"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + compressionTypeAlgoReqPropEnum = append(compressionTypeAlgoReqPropEnum, v) + } +} + +const ( + + // CompressionAlgoReqIdentity captures enum value "identity" + CompressionAlgoReqIdentity string = "identity" + + // CompressionAlgoReqGzip captures enum value "gzip" + CompressionAlgoReqGzip string = "gzip" + + // CompressionAlgoReqDeflate captures enum value "deflate" + CompressionAlgoReqDeflate string = "deflate" + + // CompressionAlgoReqRawDashDeflate captures enum value "raw-deflate" + CompressionAlgoReqRawDashDeflate string = "raw-deflate" +) + +// prop value enum +func (m *Compression) validateAlgoReqEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, compressionTypeAlgoReqPropEnum, true); err != nil { + return err + } + return nil +} + +func (m *Compression) validateAlgoReq(formats strfmt.Registry) error { + if swag.IsZero(m.AlgoReq) { // not required + return nil + } + + // value enum + if err := m.validateAlgoReqEnum("algo-req", "body", m.AlgoReq); err != nil { + return err + } + + return nil +} + var compressionAlgorithmsItemsEnum []interface{} func init() { @@ -105,6 +174,42 @@ func (m *Compression) validateAlgorithms(formats strfmt.Registry) error { return nil } +var compressionAlgosResItemsEnum []interface{} + +func init() { + var res []string + if err := json.Unmarshal([]byte(`["identity","gzip","deflate","raw-deflate"]`), &res); err != nil { + panic(err) + } + for _, v := range res { + compressionAlgosResItemsEnum = append(compressionAlgosResItemsEnum, v) + } +} + +func (m *Compression) validateAlgosResItemsEnum(path, location string, value string) error { + if err := validate.EnumCase(path, location, value, compressionAlgosResItemsEnum, true); err != nil { + return err + } + return nil +} + +func (m *Compression) validateAlgosRes(formats strfmt.Registry) error { + if swag.IsZero(m.AlgosRes) { // not required + return nil + } + + for i := 0; i < len(m.AlgosRes); i++ { + + // value enum + if err := m.validateAlgosResItemsEnum("algos-res"+"."+strconv.Itoa(i), "body", m.AlgosRes[i]); err != nil { + return err + } + + } + + return nil +} + var compressionTypeDirectionPropEnum []interface{} func init() { diff --git a/models/compression_compare.go b/models/compression_compare.go index a89ce5b8..1b2a45c5 100644 --- a/models/compression_compare.go +++ b/models/compression_compare.go @@ -33,10 +33,18 @@ package models func (s Compression) Equal(t Compression, opts ...Options) bool { opt := getOptions(opts...) + if s.AlgoReq != t.AlgoReq { + return false + } + if !equalComparableSlice(s.Algorithms, t.Algorithms, opt) { return false } + if !equalComparableSlice(s.AlgosRes, t.AlgosRes, opt) { + return false + } + if s.Direction != t.Direction { return false } @@ -49,6 +57,14 @@ func (s Compression) Equal(t Compression, opts ...Options) bool { return false } + if !equalComparableSlice(s.TypesReq, t.TypesReq, opt) { + return false + } + + if !equalComparableSlice(s.TypesRes, t.TypesRes, opt) { + return false + } + return true } @@ -69,10 +85,18 @@ func (s Compression) Diff(t Compression, opts ...Options) map[string][]interface opt := getOptions(opts...) diff := make(map[string][]interface{}) + if s.AlgoReq != t.AlgoReq { + diff["AlgoReq"] = []interface{}{s.AlgoReq, t.AlgoReq} + } + if !equalComparableSlice(s.Algorithms, t.Algorithms, opt) { diff["Algorithms"] = []interface{}{s.Algorithms, t.Algorithms} } + if !equalComparableSlice(s.AlgosRes, t.AlgosRes, opt) { + diff["AlgosRes"] = []interface{}{s.AlgosRes, t.AlgosRes} + } + if s.Direction != t.Direction { diff["Direction"] = []interface{}{s.Direction, t.Direction} } @@ -85,5 +109,13 @@ func (s Compression) Diff(t Compression, opts ...Options) map[string][]interface diff["Types"] = []interface{}{s.Types, t.Types} } + if !equalComparableSlice(s.TypesReq, t.TypesReq, opt) { + diff["TypesReq"] = []interface{}{s.TypesReq, t.TypesReq} + } + + if !equalComparableSlice(s.TypesRes, t.TypesRes, opt) { + diff["TypesRes"] = []interface{}{s.TypesRes, t.TypesRes} + } + return diff } diff --git a/models/compression_compare_test.go b/models/compression_compare_test.go index 7f2258d5..d80f5711 100644 --- a/models/compression_compare_test.go +++ b/models/compression_compare_test.go @@ -171,7 +171,7 @@ func TestCompressionDiffFalse(t *testing.T) { for _, sample := range samples { result := sample.a.Diff(sample.b) - if len(result) != 4 { + if len(result) != 8 { json := jsoniter.ConfigCompatibleWithStandardLibrary a, err := json.Marshal(&sample.a) if err != nil { @@ -181,7 +181,7 @@ func TestCompressionDiffFalse(t *testing.T) { if err != nil { t.Errorf(err.Error()) } - t.Errorf("Expected Compression to be different in 4 cases, but it is not (%d) %s %s", len(result), a, b) + t.Errorf("Expected Compression to be different in 8 cases, but it is not (%d) %s %s", len(result), a, b) } } } diff --git a/specification/build/haproxy_spec.yaml b/specification/build/haproxy_spec.yaml index aaad07ad..675c351b 100644 --- a/specification/build/haproxy_spec.yaml +++ b/specification/build/haproxy_spec.yaml @@ -9852,6 +9852,14 @@ definitions: x-go-name: ReturnHeader compression: properties: + algo-req: + enum: + - identity + - gzip + - deflate + - raw-deflate + type: string + x-omitempty: true algorithms: items: enum: @@ -9862,6 +9870,16 @@ definitions: type: string type: array x-omitempty: true + algos-res: + items: + enum: + - identity + - gzip + - deflate + - raw-deflate + type: string + type: array + x-omitempty: true direction: enum: - request @@ -9876,6 +9894,16 @@ definitions: type: string type: array x-omitempty: true + types-req: + items: + type: string + type: array + x-omitempty: true + types-res: + items: + type: string + type: array + x-omitempty: true type: object source: properties: diff --git a/specification/models/configuration/misc.yaml b/specification/models/configuration/misc.yaml index b2144f33..ddd0374b 100644 --- a/specification/models/configuration/misc.yaml +++ b/specification/models/configuration/misc.yaml @@ -314,6 +314,26 @@ compression: type: string enum: [request, response, both] x-omitempty: true + types-req: + type: array + x-omitempty: true + items: + type: string + types-res: + type: array + x-omitempty: true + items: + type: string + algo-req: + type: string + x-omitempty: true + enum: [identity, gzip, deflate, raw-deflate] + algos-res: + type: array + x-omitempty: true + items: + type: string + enum: [identity, gzip, deflate, raw-deflate] stats_http_request: type: object required: diff --git a/test/backend_test.go b/test/backend_test.go index 8d4b8106..f851d9dd 100644 --- a/test/backend_test.go +++ b/test/backend_test.go @@ -161,6 +161,18 @@ func TestCreateEditDeleteBackend(t *testing.T) { Compression: &models.Compression{ Offload: true, Direction: "both", + TypesReq: []string{ + "text/html", + "text/plain", + }, + TypesRes: []string{ + "text/plain", + }, + AlgoReq: "deflate", + AlgosRes: []string{ + "deflate", + "gzip", + }, }, LogHealthChecks: "enabled", Checkcache: "enabled", diff --git a/test/configuration_test.go b/test/configuration_test.go index 99614fbd..c0d6ac83 100644 --- a/test/configuration_test.go +++ b/test/configuration_test.go @@ -543,6 +543,10 @@ frontend test compression algo identity gzip compression type text/plain compression offload + compression algo-req raw-deflate + compression algo-res raw-deflate identity + compression type-req text/plain application/json + compression type-res text/plain clitcpka-cnt 10 clitcpka-idle 10s clitcpka-intvl 10 @@ -695,6 +699,10 @@ backend test no option h1-case-adjust-bogus-server compression type application/json text/plain compression direction both + compression algo-req raw-deflate + compression algo-res raw-deflate identity + compression type-req text/plain application/json + compression type-res text/plain srvtcpka-cnt 10 srvtcpka-idle 10s srvtcpka-intvl 10 diff --git a/test/expected/structured.json b/test/expected/structured.json index ef293a0a..a8b836e8 100644 --- a/test/expected/structured.json +++ b/test/expected/structured.json @@ -394,7 +394,19 @@ "application/json", "text/plain" ], - "direction": "both" + "direction": "both", + "types-req": [ + "text/plain", + "application/json" + ], + "types-res": [ + "text/plain" + ], + "algo-req": "raw-deflate", + "algos-res": [ + "raw-deflate", + "identity" + ] }, "cookie": { "httponly": true, @@ -1317,6 +1329,18 @@ "offload": true, "types": [ "text/plain" + ], + "types-req": [ + "text/plain", + "application/json" + ], + "types-res": [ + "text/plain" + ], + "algo-req": "raw-deflate", + "algos-res": [ + "raw-deflate", + "identity" ] }, "contstats": "enabled", diff --git a/test/frontend_test.go b/test/frontend_test.go index 7d888693..da5b41cd 100644 --- a/test/frontend_test.go +++ b/test/frontend_test.go @@ -201,6 +201,18 @@ func TestCreateEditDeleteFrontend(t *testing.T) { }, Compression: &models.Compression{ Offload: true, + TypesReq: []string{ + "text/html", + "text/plain", + }, + TypesRes: []string{ + "text/plain", + }, + AlgoReq: "deflate", + AlgosRes: []string{ + "deflate", + "gzip", + }, }, ClitcpkaCnt: &clitcpkaCnt, ClitcpkaIdle: &clitcpkaTimeout,