* inject headerModifier to the luaData (#223)
* fix lua script and test case * use ptr instead of struct * add requestHeaderModifier to testcase debugging toolkit Signed-off-by: Megrez Lu <lujiajing1126@gmail.com>
This commit is contained in:
parent
e7652cbc7c
commit
6fae7085e5
|
|
@ -29,3 +29,5 @@ test/e2e/generated/bindata.go
|
||||||
.vscode
|
.vscode
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
lua_configuration/networking.istio.io/**/testdata/*.lua
|
||||||
|
|
|
||||||
|
|
@ -100,11 +100,12 @@ func objectToTable(path string) error {
|
||||||
Annotations: testCase.Original.GetAnnotations(),
|
Annotations: testCase.Original.GetAnnotations(),
|
||||||
Spec: testCase.Original.Object["spec"],
|
Spec: testCase.Original.Object["spec"],
|
||||||
},
|
},
|
||||||
Matches: step.TrafficRoutingStrategy.Matches,
|
Matches: step.TrafficRoutingStrategy.Matches,
|
||||||
CanaryWeight: *weight,
|
CanaryWeight: *weight,
|
||||||
StableWeight: 100 - *weight,
|
StableWeight: 100 - *weight,
|
||||||
CanaryService: canaryService,
|
CanaryService: canaryService,
|
||||||
StableService: stableService,
|
StableService: stableService,
|
||||||
|
RequestHeaderModifier: step.TrafficRoutingStrategy.RequestHeaderModifier,
|
||||||
}
|
}
|
||||||
uList[fmt.Sprintf("step_%d", i)] = data
|
uList[fmt.Sprintf("step_%d", i)] = data
|
||||||
}
|
}
|
||||||
|
|
@ -128,11 +129,12 @@ func objectToTable(path string) error {
|
||||||
Annotations: testCase.Original.GetAnnotations(),
|
Annotations: testCase.Original.GetAnnotations(),
|
||||||
Spec: testCase.Original.Object["spec"],
|
Spec: testCase.Original.Object["spec"],
|
||||||
},
|
},
|
||||||
Matches: matches,
|
Matches: matches,
|
||||||
CanaryWeight: *weight,
|
CanaryWeight: *weight,
|
||||||
StableWeight: 100 - *weight,
|
StableWeight: 100 - *weight,
|
||||||
CanaryService: canaryService,
|
CanaryService: canaryService,
|
||||||
StableService: stableService,
|
StableService: stableService,
|
||||||
|
RequestHeaderModifier: trafficRouting.Spec.Strategy.RequestHeaderModifier,
|
||||||
}
|
}
|
||||||
uList["steps_0"] = data
|
uList["steps_0"] = data
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,10 @@ rollout:
|
||||||
- type: RegularExpression
|
- type: RegularExpression
|
||||||
name: name
|
name: name
|
||||||
value: ".*demo"
|
value: ".*demo"
|
||||||
|
requestHeaderModifier:
|
||||||
|
set:
|
||||||
|
- name: "header-foo"
|
||||||
|
value: "bar"
|
||||||
- matches:
|
- matches:
|
||||||
- headers:
|
- headers:
|
||||||
- type: Exact
|
- type: Exact
|
||||||
|
|
@ -66,6 +70,10 @@ expected:
|
||||||
exact: pc
|
exact: pc
|
||||||
name:
|
name:
|
||||||
regex: .*demo
|
regex: .*demo
|
||||||
|
headers:
|
||||||
|
request:
|
||||||
|
set:
|
||||||
|
header-foo: bar
|
||||||
route:
|
route:
|
||||||
- destination:
|
- destination:
|
||||||
host: svc-demo-canary
|
host: svc-demo-canary
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,10 @@ trafficRouting:
|
||||||
- type: RegularExpression
|
- type: RegularExpression
|
||||||
name: name
|
name: name
|
||||||
value: ".*demo"
|
value: ".*demo"
|
||||||
|
requestHeaderModifier:
|
||||||
|
set:
|
||||||
|
- name: "header-foo"
|
||||||
|
value: "bar"
|
||||||
objectRef:
|
objectRef:
|
||||||
- service: svc-demo
|
- service: svc-demo
|
||||||
customNetworkRefs:
|
customNetworkRefs:
|
||||||
|
|
@ -51,6 +55,10 @@ expected:
|
||||||
exact: pc
|
exact: pc
|
||||||
name:
|
name:
|
||||||
regex: .*demo
|
regex: .*demo
|
||||||
|
headers:
|
||||||
|
request:
|
||||||
|
set:
|
||||||
|
header-foo: bar
|
||||||
route:
|
route:
|
||||||
- destination:
|
- destination:
|
||||||
host: svc-demo
|
host: svc-demo
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,10 @@ trafficRouting:
|
||||||
- type: RegularExpression
|
- type: RegularExpression
|
||||||
name: name
|
name: name
|
||||||
value: ".*demo"
|
value: ".*demo"
|
||||||
|
requestHeaderModifier:
|
||||||
|
set:
|
||||||
|
- name: "header-foo"
|
||||||
|
value: "bar"
|
||||||
objectRef:
|
objectRef:
|
||||||
- service: svc-demo
|
- service: svc-demo
|
||||||
customNetworkRefs:
|
customNetworkRefs:
|
||||||
|
|
@ -50,6 +54,10 @@ expected:
|
||||||
- headers:
|
- headers:
|
||||||
name:
|
name:
|
||||||
regex: .*demo
|
regex: .*demo
|
||||||
|
headers:
|
||||||
|
request:
|
||||||
|
set:
|
||||||
|
header-foo: bar
|
||||||
route:
|
route:
|
||||||
- destination:
|
- destination:
|
||||||
host: svc-demo
|
host: svc-demo
|
||||||
|
|
@ -58,6 +66,10 @@ expected:
|
||||||
- headers:
|
- headers:
|
||||||
user-agent:
|
user-agent:
|
||||||
exact: pc
|
exact: pc
|
||||||
|
headers:
|
||||||
|
request:
|
||||||
|
set:
|
||||||
|
header-foo: bar
|
||||||
route:
|
route:
|
||||||
- destination:
|
- destination:
|
||||||
host: svc-demo
|
host: svc-demo
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,7 @@ function CalculateWeight(route, stableWeight, n)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- generate routes with matches, insert a rule before other rules, only support http headers, cookies etc.
|
-- 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
|
for _, match in ipairs(matches) do
|
||||||
local route = {}
|
local route = {}
|
||||||
route["match"] = {}
|
route["match"] = {}
|
||||||
|
|
@ -81,6 +81,23 @@ function GenerateRoutesWithMatches(spec, matches, stableService, canaryService)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.insert(route["match"], vsMatch)
|
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 = {
|
route.route = {
|
||||||
{
|
{
|
||||||
destination = {}
|
destination = {}
|
||||||
|
|
@ -130,7 +147,7 @@ end
|
||||||
|
|
||||||
if (obj.matches and next(obj.matches) ~= nil)
|
if (obj.matches and next(obj.matches) ~= nil)
|
||||||
then
|
then
|
||||||
GenerateRoutesWithMatches(spec, obj.matches, obj.stableService, obj.canaryService)
|
GenerateRoutesWithMatches(spec, obj.matches, obj.stableService, obj.canaryService, obj.requestHeaderModifier)
|
||||||
else
|
else
|
||||||
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "http")
|
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, "tcp")
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,7 @@ import (
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
utilpointer "k8s.io/utils/pointer"
|
utilpointer "k8s.io/utils/pointer"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
|
gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
|
@ -47,12 +48,13 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type LuaData struct {
|
type LuaData struct {
|
||||||
Data Data
|
Data Data
|
||||||
CanaryWeight int32
|
CanaryWeight int32
|
||||||
StableWeight int32
|
StableWeight int32
|
||||||
Matches []v1beta1.HttpRouteMatch
|
Matches []v1beta1.HttpRouteMatch
|
||||||
CanaryService string
|
CanaryService string
|
||||||
StableService string
|
StableService string
|
||||||
|
RequestHeaderModifier *gatewayv1beta1.HTTPRequestHeaderFilter
|
||||||
}
|
}
|
||||||
type Data struct {
|
type Data struct {
|
||||||
Spec interface{} `json:"spec,omitempty"`
|
Spec interface{} `json:"spec,omitempty"`
|
||||||
|
|
@ -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.
|
// so we need to pass weight=-1 to indicate the case where weight is nil.
|
||||||
weight = utilpointer.Int32(-1)
|
weight = utilpointer.Int32(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
data := &LuaData{
|
data := &LuaData{
|
||||||
Data: spec,
|
Data: spec,
|
||||||
CanaryWeight: *weight,
|
CanaryWeight: *weight,
|
||||||
StableWeight: 100 - *weight,
|
StableWeight: 100 - *weight,
|
||||||
Matches: matches,
|
Matches: matches,
|
||||||
CanaryService: r.conf.CanaryService,
|
CanaryService: r.conf.CanaryService,
|
||||||
StableService: r.conf.StableService,
|
StableService: r.conf.StableService,
|
||||||
|
RequestHeaderModifier: strategy.RequestHeaderModifier,
|
||||||
}
|
}
|
||||||
|
|
||||||
unObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(data)
|
unObj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(data)
|
||||||
|
|
|
||||||
|
|
@ -414,6 +414,78 @@ func TestEnsureRoutes(t *testing.T) {
|
||||||
return done, hasError
|
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",
|
name: "test2, do traffic routing but failed to execute lua",
|
||||||
getRoutes: func() *v1beta1.TrafficRoutingStrategy {
|
getRoutes: func() *v1beta1.TrafficRoutingStrategy {
|
||||||
|
|
@ -638,11 +710,12 @@ func TestLuaScript(t *testing.T) {
|
||||||
Annotations: testCase.Original.GetAnnotations(),
|
Annotations: testCase.Original.GetAnnotations(),
|
||||||
Spec: testCase.Original.Object["spec"],
|
Spec: testCase.Original.Object["spec"],
|
||||||
},
|
},
|
||||||
Matches: step.TrafficRoutingStrategy.Matches,
|
Matches: step.TrafficRoutingStrategy.Matches,
|
||||||
CanaryWeight: *weight,
|
CanaryWeight: *weight,
|
||||||
StableWeight: 100 - *weight,
|
StableWeight: 100 - *weight,
|
||||||
CanaryService: canaryService,
|
CanaryService: canaryService,
|
||||||
StableService: stableService,
|
StableService: stableService,
|
||||||
|
RequestHeaderModifier: step.TrafficRoutingStrategy.RequestHeaderModifier,
|
||||||
}
|
}
|
||||||
nSpec, err := executeLua(data, script)
|
nSpec, err := executeLua(data, script)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -678,11 +751,12 @@ func TestLuaScript(t *testing.T) {
|
||||||
Annotations: testCase.Original.GetAnnotations(),
|
Annotations: testCase.Original.GetAnnotations(),
|
||||||
Spec: testCase.Original.Object["spec"],
|
Spec: testCase.Original.Object["spec"],
|
||||||
},
|
},
|
||||||
Matches: matches,
|
Matches: matches,
|
||||||
CanaryWeight: *weight,
|
CanaryWeight: *weight,
|
||||||
StableWeight: 100 - *weight,
|
StableWeight: 100 - *weight,
|
||||||
CanaryService: canaryService,
|
CanaryService: canaryService,
|
||||||
StableService: stableService,
|
StableService: stableService,
|
||||||
|
RequestHeaderModifier: trafficRouting.Spec.Strategy.RequestHeaderModifier,
|
||||||
}
|
}
|
||||||
nSpec, err := executeLua(data, script)
|
nSpec, err := executeLua(data, script)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -94,7 +94,7 @@ function CalculateWeight(route, stableWeight, n)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- generate routes with matches, insert a rule before other rules
|
-- 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)
|
local hasRule, stableServiceSubsets = FindStableServiceSubsets(spec, stableService, protocol)
|
||||||
if (not hasRule) then
|
if (not hasRule) then
|
||||||
return
|
return
|
||||||
|
|
@ -136,6 +136,23 @@ function GenerateMatchedRoutes(spec, matches, stableService, canaryService, stab
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
table.insert(route["match"], vsMatch)
|
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 = {
|
route.route = {
|
||||||
{
|
{
|
||||||
destination = {}
|
destination = {}
|
||||||
|
|
@ -187,7 +204,7 @@ function GenerateMatchedRoutes(spec, matches, stableService, canaryService, stab
|
||||||
end
|
end
|
||||||
|
|
||||||
-- generate routes without matches, change every rule
|
-- 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)
|
local matchedRules = FindMatchedRules(spec, stableService, protocol)
|
||||||
for _, rule in ipairs(matchedRules) do
|
for _, rule in ipairs(matchedRules) do
|
||||||
local canary
|
local canary
|
||||||
|
|
@ -218,12 +235,12 @@ function GenerateRoutes(spec, stableService, canaryService, stableWeight, canary
|
||||||
end
|
end
|
||||||
|
|
||||||
if (obj.matches) then
|
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, obj.requestHeaderModifier, "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, obj.requestHeaderModifier,"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,"tls")
|
||||||
else
|
else
|
||||||
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "http")
|
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, obj.requestHeaderModifier, "http")
|
||||||
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "tcp")
|
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, obj.requestHeaderModifier, "tcp")
|
||||||
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, "tls")
|
GenerateRoutes(spec, obj.stableService, obj.canaryService, obj.stableWeight, obj.canaryWeight, obj.requestHeaderModifier, "tls")
|
||||||
end
|
end
|
||||||
return obj.data
|
return obj.data
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue