Skip to content

Commit

Permalink
* inject headerModifier to the luaData (#223)
Browse files Browse the repository at this point in the history
* fix lua script and test case
* use ptr instead of struct
* add requestHeaderModifier to testcase debugging toolkit

Signed-off-by: Megrez Lu <[email protected]>
  • Loading branch information
lujiajing1126 authored Jul 22, 2024
1 parent e7652cb commit 6fae708
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 42 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,5 @@ test/e2e/generated/bindata.go
.vscode

.DS_Store

lua_configuration/networking.istio.io/**/testdata/*.lua
22 changes: 12 additions & 10 deletions lua_configuration/convert_test_case_to_lua_object.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,11 +100,12 @@ func objectToTable(path string) error {
Annotations: testCase.Original.GetAnnotations(),
Spec: testCase.Original.Object["spec"],
},
Matches: step.TrafficRoutingStrategy.Matches,
CanaryWeight: *weight,
StableWeight: 100 - *weight,
CanaryService: canaryService,
StableService: stableService,
Matches: step.TrafficRoutingStrategy.Matches,
CanaryWeight: *weight,
StableWeight: 100 - *weight,
CanaryService: canaryService,
StableService: stableService,
RequestHeaderModifier: step.TrafficRoutingStrategy.RequestHeaderModifier,
}
uList[fmt.Sprintf("step_%d", i)] = data
}
Expand All @@ -128,11 +129,12 @@ func objectToTable(path string) error {
Annotations: testCase.Original.GetAnnotations(),
Spec: testCase.Original.Object["spec"],
},
Matches: matches,
CanaryWeight: *weight,
StableWeight: 100 - *weight,
CanaryService: canaryService,
StableService: stableService,
Matches: matches,
CanaryWeight: *weight,
StableWeight: 100 - *weight,
CanaryService: canaryService,
StableService: stableService,
RequestHeaderModifier: trafficRouting.Spec.Strategy.RequestHeaderModifier,
}
uList["steps_0"] = data
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ rollout:
- type: RegularExpression
name: name
value: ".*demo"
requestHeaderModifier:
set:
- name: "header-foo"
value: "bar"
- matches:
- headers:
- type: Exact
Expand Down Expand Up @@ -66,6 +70,10 @@ expected:
exact: pc
name:
regex: .*demo
headers:
request:
set:
header-foo: bar
route:
- destination:
host: svc-demo-canary
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ trafficRouting:
- type: RegularExpression
name: name
value: ".*demo"
requestHeaderModifier:
set:
- name: "header-foo"
value: "bar"
objectRef:
- service: svc-demo
customNetworkRefs:
Expand Down Expand Up @@ -51,6 +55,10 @@ expected:
exact: pc
name:
regex: .*demo
headers:
request:
set:
header-foo: bar
route:
- destination:
host: svc-demo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ trafficRouting:
- type: RegularExpression
name: name
value: ".*demo"
requestHeaderModifier:
set:
- name: "header-foo"
value: "bar"
objectRef:
- service: svc-demo
customNetworkRefs:
Expand Down Expand Up @@ -50,6 +54,10 @@ expected:
- headers:
name:
regex: .*demo
headers:
request:
set:
header-foo: bar
route:
- destination:
host: svc-demo
Expand All @@ -58,6 +66,10 @@ expected:
- headers:
user-agent:
exact: pc
headers:
request:
set:
header-foo: bar
route:
- destination:
host: svc-demo
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ function CalculateWeight(route, stableWeight, n)
end

-- generate routes with matches, insert a rule before other rules, only support http headers, cookies etc.
function GenerateRoutesWithMatches(spec, matches, stableService, canaryService)
function GenerateRoutesWithMatches(spec, matches, stableService, canaryService, requestHeaderModifier)
for _, match in ipairs(matches) do
local route = {}
route["match"] = {}
Expand Down Expand Up @@ -81,6 +81,23 @@ function GenerateRoutesWithMatches(spec, matches, stableService, canaryService)
end
end
table.insert(route["match"], vsMatch)
if requestHeaderModifier then
route["headers"] = {}
route["headers"]["request"] = {}
for action, headers in pairs(requestHeaderModifier) do
if action == "set" or action == "add" then
route["headers"]["request"][action] = {}
for _, header in ipairs(headers) do
route["headers"]["request"][action][header["name"]] = header["value"]
end
elseif action == "remove" then
route["headers"]["request"]["remove"] = {}
for _, rHeader in ipairs(headers) do
table.insert(route["headers"]["request"]["remove"], rHeader)
end
end
end
end
route.route = {
{
destination = {}
Expand Down Expand Up @@ -130,7 +147,7 @@ end

if (obj.matches and next(obj.matches) ~= nil)
then
GenerateRoutesWithMatches(spec, obj.matches, obj.stableService, obj.canaryService)
GenerateRoutesWithMatches(spec, obj.matches, obj.stableService, obj.canaryService, obj.requestHeaderModifier)
else
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "http")
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "tcp")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import (
"k8s.io/klog/v2"
utilpointer "k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client"
gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
)

const (
Expand All @@ -47,12 +48,13 @@ const (
)

type LuaData struct {
Data Data
CanaryWeight int32
StableWeight int32
Matches []v1beta1.HttpRouteMatch
CanaryService string
StableService string
Data Data
CanaryWeight int32
StableWeight int32
Matches []v1beta1.HttpRouteMatch
CanaryService string
StableService string
RequestHeaderModifier *gatewayv1beta1.HTTPRequestHeaderFilter
}
type Data struct {
Spec interface{} `json:"spec,omitempty"`
Expand Down Expand Up @@ -268,13 +270,15 @@ func (r *customController) executeLuaForCanary(spec Data, strategy *v1beta1.Traf
// so we need to pass weight=-1 to indicate the case where weight is nil.
weight = utilpointer.Int32(-1)
}

data := &LuaData{
Data: spec,
CanaryWeight: *weight,
StableWeight: 100 - *weight,
Matches: matches,
CanaryService: r.conf.CanaryService,
StableService: r.conf.StableService,
Data: spec,
CanaryWeight: *weight,
StableWeight: 100 - *weight,
Matches: matches,
CanaryService: r.conf.CanaryService,
StableService: r.conf.StableService,
RequestHeaderModifier: strategy.RequestHeaderModifier,
}

unObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(data)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,78 @@ func TestEnsureRoutes(t *testing.T) {
return done, hasError
},
},
{
name: "Do header-based traffic routing and set header for VirtualService",
getRoutes: func() *v1beta1.TrafficRoutingStrategy {
headerTypeExact := gatewayv1beta1.HeaderMatchExact
return &v1beta1.TrafficRoutingStrategy{
Matches: []v1beta1.HttpRouteMatch{
{
Headers: []gatewayv1beta1.HTTPHeaderMatch{
{
Type: &headerTypeExact,
Name: "user_id",
Value: "123456",
},
},
},
},
RequestHeaderModifier: &gatewayv1beta1.HTTPRequestHeaderFilter{
Set: []gatewayv1beta1.HTTPHeader{
{
Name: "x-env-flag",
Value: "canary",
},
},
},
}
},
getUnstructureds: func() []*unstructured.Unstructured {
objects := make([]*unstructured.Unstructured, 0)
u := &unstructured.Unstructured{}
_ = u.UnmarshalJSON([]byte(virtualServiceDemo))
u.SetAPIVersion("networking.istio.io/v1alpha3")
objects = append(objects, u)

return objects
},
getConfig: func() Config {
return Config{
Key: "rollout-demo",
StableService: "echoserver",
CanaryService: "echoserver-canary",
TrafficConf: []v1beta1.ObjectRef{
{
APIVersion: "networking.istio.io/v1alpha3",
Kind: "VirtualService",
Name: "echoserver",
},
},
}
},
expectUnstructureds: func() []*unstructured.Unstructured {
objects := make([]*unstructured.Unstructured, 0)
u := &unstructured.Unstructured{}
_ = u.UnmarshalJSON([]byte(virtualServiceDemo))
annotations := map[string]string{
OriginalSpecAnnotation: `{"spec":{"hosts":["echoserver.example.com"],"http":[{"route":[{"destination":{"host":"echoserver"}}]}]},"annotations":{"virtual":"test"}}`,
"virtual": "test",
}
u.SetAnnotations(annotations)
specStr := `{"hosts":["echoserver.example.com"],"http":[{"headers":{"request":{"set":{"x-env-flag":"canary"}}},"match":[{"headers":{"user_id":{"exact":"123456"}}}],"route":[{"destination":{"host":"echoserver-canary"}}]},{"route":[{"destination":{"host":"echoserver"}}]}]}`
var spec interface{}
_ = json.Unmarshal([]byte(specStr), &spec)
u.Object["spec"] = spec
objects = append(objects, u)

return objects
},
expectState: func() (bool, bool) {
done := false
hasError := false
return done, hasError
},
},
{
name: "test2, do traffic routing but failed to execute lua",
getRoutes: func() *v1beta1.TrafficRoutingStrategy {
Expand Down Expand Up @@ -638,11 +710,12 @@ func TestLuaScript(t *testing.T) {
Annotations: testCase.Original.GetAnnotations(),
Spec: testCase.Original.Object["spec"],
},
Matches: step.TrafficRoutingStrategy.Matches,
CanaryWeight: *weight,
StableWeight: 100 - *weight,
CanaryService: canaryService,
StableService: stableService,
Matches: step.TrafficRoutingStrategy.Matches,
CanaryWeight: *weight,
StableWeight: 100 - *weight,
CanaryService: canaryService,
StableService: stableService,
RequestHeaderModifier: step.TrafficRoutingStrategy.RequestHeaderModifier,
}
nSpec, err := executeLua(data, script)
if err != nil {
Expand Down Expand Up @@ -678,11 +751,12 @@ func TestLuaScript(t *testing.T) {
Annotations: testCase.Original.GetAnnotations(),
Spec: testCase.Original.Object["spec"],
},
Matches: matches,
CanaryWeight: *weight,
StableWeight: 100 - *weight,
CanaryService: canaryService,
StableService: stableService,
Matches: matches,
CanaryWeight: *weight,
StableWeight: 100 - *weight,
CanaryService: canaryService,
StableService: stableService,
RequestHeaderModifier: trafficRouting.Spec.Strategy.RequestHeaderModifier,
}
nSpec, err := executeLua(data, script)
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ function CalculateWeight(route, stableWeight, n)
end

-- generate routes with matches, insert a rule before other rules
function GenerateMatchedRoutes(spec, matches, stableService, canaryService, stableWeight, canaryWeight, protocol)
function GenerateMatchedRoutes(spec, matches, stableService, canaryService, stableWeight, canaryWeight, requestHeaderModifier, protocol)
local hasRule, stableServiceSubsets = FindStableServiceSubsets(spec, stableService, protocol)
if (not hasRule) then
return
Expand Down Expand Up @@ -136,6 +136,23 @@ function GenerateMatchedRoutes(spec, matches, stableService, canaryService, stab
end
end
table.insert(route["match"], vsMatch)
if requestHeaderModifier then
route["headers"] = {}
route["headers"]["request"] = {}
for action, headers in pairs(requestHeaderModifier) do
if action == "set" or action == "add" then
route["headers"]["request"][action] = {}
for _, header in ipairs(headers) do
route["headers"]["request"][action][header["name"]] = header["value"]
end
elseif action == "remove" then
route["headers"]["request"]["remove"] = {}
for _, rHeader in ipairs(headers) do
table.insert(route["headers"]["request"]["remove"], rHeader)
end
end
end
end
route.route = {
{
destination = {}
Expand Down Expand Up @@ -187,7 +204,7 @@ function GenerateMatchedRoutes(spec, matches, stableService, canaryService, stab
end

-- generate routes without matches, change every rule
function GenerateRoutes(spec, stableService, canaryService, stableWeight, canaryWeight, protocol)
function GenerateRoutes(spec, stableService, canaryService, stableWeight, canaryWeight, requestHeaderModifier, protocol)
local matchedRules = FindMatchedRules(spec, stableService, protocol)
for _, rule in ipairs(matchedRules) do
local canary
Expand Down Expand Up @@ -218,12 +235,12 @@ function GenerateRoutes(spec, stableService, canaryService, stableWeight, canary
end

if (obj.matches) then
GenerateMatchedRoutes(spec, obj.matches, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "http")
GenerateMatchedRoutes(spec, obj.matches, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "tcp")
GenerateMatchedRoutes(spec, obj.matches, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "tls")
GenerateMatchedRoutes(spec, obj.matches, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, obj.requestHeaderModifier, "http")
GenerateMatchedRoutes(spec, obj.matches, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, obj.requestHeaderModifier,"tcp")
GenerateMatchedRoutes(spec, obj.matches, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, obj.requestHeaderModifier,"tls")
else
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "http")
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "tcp")
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "tls")
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, obj.requestHeaderModifier, "http")
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, obj.requestHeaderModifier, "tcp")
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, obj.requestHeaderModifier, "tls")
end
return obj.data

0 comments on commit 6fae708

Please sign in to comment.