diff --git a/pkg/trafficrouting/network/gateway/gateway.go b/pkg/trafficrouting/network/gateway/gateway.go index 827beb7b..4477c59b 100644 --- a/pkg/trafficrouting/network/gateway/gateway.go +++ b/pkg/trafficrouting/network/gateway/gateway.go @@ -135,13 +135,13 @@ func (r *gatewayController) buildDesiredHTTPRoute(rules []gatewayv1alpha2.HTTPRo // according to the Gateway API definition, weight and headers cannot be supported at the same time. // A/B Testing, according to headers. current only support one match } else if len(matches) > 0 { - return r.buildCanaryHeaderHttpRoutes(rules, matches[0].Headers) + return r.buildCanaryHeaderHttpRoutes(rules, matches) } // canary release, according to percentage of traffic routing return r.buildCanaryWeightHttpRoutes(rules, weight) } -func (r *gatewayController) buildCanaryHeaderHttpRoutes(rules []gatewayv1alpha2.HTTPRouteRule, headers []gatewayv1alpha2.HTTPHeaderMatch) []gatewayv1alpha2.HTTPRouteRule { +func (r *gatewayController) buildCanaryHeaderHttpRoutes(rules []gatewayv1alpha2.HTTPRouteRule, matchs []rolloutv1alpha1.HttpRouteMatch) []gatewayv1alpha2.HTTPRouteRule { var desired []gatewayv1alpha2.HTTPRouteRule var canarys []gatewayv1alpha2.HTTPRouteRule for i := range rules { @@ -160,8 +160,10 @@ func (r *gatewayController) buildCanaryHeaderHttpRoutes(rules []gatewayv1alpha2. canaryRule.BackendRefs = []gatewayv1alpha2.HTTPBackendRef{*canaryRef} // set canary headers in httpRoute for j := range canaryRule.Matches { - match := &canaryRule.Matches[j] - match.Headers = append(match.Headers, headers...) + for k := range matchs { + match := &canaryRule.Matches[j] + match.Headers = append(match.Headers, matchs[k].Headers...) + } } canarys = append(canarys, *canaryRule) } diff --git a/pkg/trafficrouting/network/gateway/gateway_test.go b/pkg/trafficrouting/network/gateway/gateway_test.go index 0eeeaeb5..34df0453 100644 --- a/pkg/trafficrouting/network/gateway/gateway_test.go +++ b/pkg/trafficrouting/network/gateway/gateway_test.go @@ -155,6 +155,18 @@ func TestBuildDesiredHTTPRoute(t *testing.T) { Value: "true", }, }, + }, { + Headers: []gatewayv1alpha2.HTTPHeaderMatch{ + { + Name: "user_id", + Value: "234*", + Type: &iType, + }, + { + Name: "canary", + Value: "true", + }, + }, }, } }, diff --git a/pkg/trafficrouting/network/gateway/lua_configuration/trafficrouting_ingress/aliyun-alb.lua b/pkg/trafficrouting/network/gateway/lua_configuration/trafficrouting_ingress/aliyun-alb.lua new file mode 100644 index 00000000..4ec44126 --- /dev/null +++ b/pkg/trafficrouting/network/gateway/lua_configuration/trafficrouting_ingress/aliyun-alb.lua @@ -0,0 +1,36 @@ +annotations = {} +if ( obj.annotations ) +then + annotations = obj.annotations +end +annotations["alb.ingress.kubernetes.io/canary"] = "true" +annotations["alb.ingress.kubernetes.io/canary-by-cookie"] = nil +annotations["alb.ingress.kubernetes.io/canary-by-header"] = nil +annotations["alb.ingress.kubernetes.io/canary-by-header-pattern"] = nil +annotations["alb.ingress.kubernetes.io/canary-by-header-value"] = nil +annotations["alb.ingress.kubernetes.io/canary-weight"] = nil +annotations["alb.ingress.kubernetes.io/order"] = "1" +if ( obj.weight ~= "-1" ) +then + annotations["alb.ingress.kubernetes.io/canary-weight"] = obj.weight +end +if ( not obj.matches ) +then + return annotations +end +for _,match in ipairs(obj.matches) do + local header = match.headers[1] + if ( header.name == "canary-by-cookie" ) + then + annotations["alb.ingress.kubernetes.io/canary-by-cookie"] = header.value + else + annotations["alb.ingress.kubernetes.io/canary-by-header"] = header.name + if ( header.type == "RegularExpression" ) + then + annotations["alb.ingress.kubernetes.io/canary-by-header-pattern"] = header.value + else + annotations["alb.ingress.kubernetes.io/canary-by-header-value"] = header.value + end + end +end +return annotations diff --git a/pkg/trafficrouting/network/gateway/lua_configuration/trafficrouting_ingress/higress.lua b/pkg/trafficrouting/network/gateway/lua_configuration/trafficrouting_ingress/higress.lua new file mode 100644 index 00000000..7ce0210e --- /dev/null +++ b/pkg/trafficrouting/network/gateway/lua_configuration/trafficrouting_ingress/higress.lua @@ -0,0 +1,46 @@ +annotations = {} +-- obj.annotations is ingress annotations, it is recommended not to remove the part of the lua script, it must be kept +if ( obj.annotations ) +then + annotations = obj.annotations +end +-- indicates the ingress is nginx canary api +annotations["nginx.ingress.kubernetes.io/canary"] = "true" +-- First, set all canary api to nil +annotations["nginx.ingress.kubernetes.io/canary-by-cookie"] = nil +annotations["nginx.ingress.kubernetes.io/canary-by-header"] = nil +annotations["nginx.ingress.kubernetes.io/canary-by-header-pattern"] = nil +annotations["nginx.ingress.kubernetes.io/canary-by-header-value"] = nil +annotations["nginx.ingress.kubernetes.io/canary-weight"] = nil +-- if rollout.spec.strategy.canary.steps.weight is nil, obj.weight will be -1, +-- then we need remove the canary-weight annotation +if ( obj.weight ~= "-1" ) +then + annotations["nginx.ingress.kubernetes.io/canary-weight"] = obj.weight +end +-- if don't contains headers, immediate return annotations +if ( not obj.matches ) +then + return annotations +end +-- headers & cookie apis +-- traverse matches +for _,match in ipairs(obj.matches) do + local header = match.headers[1] + -- cookie + if ( header.name == "canary-by-cookie" ) + then + annotations["nginx.ingress.kubernetes.io/canary-by-cookie"] = header.value + else + annotations["nginx.ingress.kubernetes.io/canary-by-header"] = header.name + -- if regular expression + if ( header.type == "RegularExpression" ) + then + annotations["nginx.ingress.kubernetes.io/canary-by-header-pattern"] = header.value + else + annotations["nginx.ingress.kubernetes.io/canary-by-header-value"] = header.value + end + end +end +-- must be return annotations +return annotations \ No newline at end of file diff --git a/pkg/trafficrouting/network/gateway/lua_configuration/trafficrouting_ingress/nginx.lua b/pkg/trafficrouting/network/gateway/lua_configuration/trafficrouting_ingress/nginx.lua new file mode 100644 index 00000000..16ec4c6a --- /dev/null +++ b/pkg/trafficrouting/network/gateway/lua_configuration/trafficrouting_ingress/nginx.lua @@ -0,0 +1,46 @@ +annotations = {} +-- obj.annotations is ingress annotations, it is recommended not to remove the part of the lua script, it must be kept +if ( obj.annotations ) +then + annotations = obj.annotations +end +-- indicates the ingress is nginx canary api +annotations["nginx.ingress.kubernetes.io/canary"] = "true" +-- First, set all canary api to nil +annotations["nginx.ingress.kubernetes.io/canary-by-cookie"] = nil +annotations["nginx.ingress.kubernetes.io/canary-by-header"] = nil +annotations["nginx.ingress.kubernetes.io/canary-by-header-pattern"] = nil +annotations["nginx.ingress.kubernetes.io/canary-by-header-value"] = nil +annotations["nginx.ingress.kubernetes.io/canary-weight"] = nil +-- if rollout.spec.strategy.canary.steps.weight is nil, obj.weight will be -1, +-- then we need remove the canary-weight annotation +if ( obj.weight ~= "-1" ) +then + annotations["nginx.ingress.kubernetes.io/canary-weight"] = obj.weight +end +-- if don't contains headers, immediate return annotations +if ( not obj.matches ) +then + return annotations +end +-- headers & cookie apis +-- traverse matches +for _,match in ipairs(obj.matches) do + local header = match.headers[1] + -- cookie + if ( header.name == "canary-by-cookie" ) + then + annotations["nginx.ingress.kubernetes.io/canary-by-cookie"] = header.value + else + annotations["nginx.ingress.kubernetes.io/canary-by-header"] = header.name + -- if regular expression + if ( header.type == "RegularExpression" ) + then + annotations["nginx.ingress.kubernetes.io/canary-by-header-pattern"] = header.value + else + annotations["nginx.ingress.kubernetes.io/canary-by-header-value"] = header.value + end + end +end +-- must be return annotations +return annotations