Skip to content

Commit 962d22f

Browse files
add mesh conformance for httproute-queryparmas-match (#3834)
1 parent 3fa0912 commit 962d22f

File tree

3 files changed

+228
-0
lines changed

3 files changed

+228
-0
lines changed
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
Copyright 2025 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package meshtests
18+
19+
import (
20+
"testing"
21+
22+
"sigs.k8s.io/gateway-api/conformance/utils/echo"
23+
"sigs.k8s.io/gateway-api/conformance/utils/http"
24+
"sigs.k8s.io/gateway-api/conformance/utils/suite"
25+
"sigs.k8s.io/gateway-api/pkg/features"
26+
)
27+
28+
func init() {
29+
MeshConformanceTests = append(MeshConformanceTests, MeshHTTPRouteQueryParamMatching)
30+
}
31+
32+
var MeshHTTPRouteQueryParamMatching = suite.ConformanceTest{
33+
ShortName: "MeshHTTPRouteQueryParamMatching",
34+
Description: "A single HTTPRoute with query param matching for different backends",
35+
Manifests: []string{"tests/mesh/httproute-query-param-matching.yaml"},
36+
Features: []features.FeatureName{
37+
features.SupportMesh,
38+
features.SupportHTTPRoute,
39+
features.SupportMeshHTTPRouteQueryParamMatching,
40+
},
41+
Test: func(t *testing.T, s *suite.ConformanceTestSuite) {
42+
ns := "gateway-conformance-mesh"
43+
client := echo.ConnectToApp(t, s, echo.MeshAppEchoV1)
44+
45+
testCases := []http.ExpectedResponse{{
46+
Request: http.Request{Path: "/?animal=whale"},
47+
Backend: "echo-v1",
48+
Namespace: ns,
49+
}, {
50+
Request: http.Request{Path: "/?animal=dolphin"},
51+
Backend: "echo-v2",
52+
Namespace: ns,
53+
}, {
54+
Request: http.Request{Path: "/?animal=whale&otherparam=irrelevant"},
55+
Backend: "echo-v1",
56+
Namespace: ns,
57+
}, {
58+
Request: http.Request{Path: "/?animal=dolphin&color=yellow"},
59+
Backend: "echo-v2",
60+
Namespace: ns,
61+
}, {
62+
Request: http.Request{Path: "/?color=blue"},
63+
Response: http.Response{StatusCode: 404},
64+
}, {
65+
Request: http.Request{Path: "/?animal=dog"},
66+
Response: http.Response{StatusCode: 404},
67+
}, {
68+
Request: http.Request{Path: "/?animal=whaledolphin"},
69+
Response: http.Response{StatusCode: 404},
70+
}, {
71+
Request: http.Request{Path: "/"},
72+
Response: http.Response{StatusCode: 404},
73+
}}
74+
75+
// Combinations of query param matching with other core matches.
76+
testCases = append(testCases, []http.ExpectedResponse{
77+
{
78+
Request: http.Request{Path: "/path1?animal=whale"},
79+
Backend: "echo-v1",
80+
Namespace: ns,
81+
},
82+
{
83+
Request: http.Request{Headers: map[string]string{"version": "one"}, Path: "/?animal=whale"},
84+
Backend: "echo-v2",
85+
Namespace: ns,
86+
},
87+
}...)
88+
89+
// Ensure that combinations of matches which are OR'd together match
90+
// even if only one of them is used in the request.
91+
testCases = append(testCases, []http.ExpectedResponse{
92+
{
93+
Request: http.Request{Path: "/path3?animal=shark"},
94+
Backend: "echo-v1",
95+
Namespace: ns,
96+
},
97+
{
98+
Request: http.Request{Headers: map[string]string{"version": "three"}, Path: "/path4?animal=kraken"},
99+
Backend: "echo-v1",
100+
Namespace: ns,
101+
},
102+
}...)
103+
104+
// Ensure that combinations of match types which are ANDed together do not match
105+
// when only a subset of match types is used in the request.
106+
testCases = append(testCases, []http.ExpectedResponse{
107+
{
108+
Request: http.Request{Path: "/?animal=shark"},
109+
Response: http.Response{StatusCode: 404},
110+
},
111+
{
112+
Request: http.Request{Path: "/path4?animal=kraken"},
113+
Response: http.Response{StatusCode: 404},
114+
},
115+
}...)
116+
117+
// For requests that satisfy multiple matches, ensure precedence order
118+
// defined by the Gateway API spec is maintained.
119+
testCases = append(testCases, []http.ExpectedResponse{
120+
{
121+
Request: http.Request{Path: "/path5?animal=hydra"},
122+
Backend: "echo-v1",
123+
Namespace: ns,
124+
},
125+
}...)
126+
127+
for i := range testCases {
128+
tc := testCases[i]
129+
t.Run(tc.GetTestCaseName(i), func(t *testing.T) {
130+
t.Parallel()
131+
client.MakeRequestAndExpectEventuallyConsistentResponse(t, tc, s.TimeoutConfig)
132+
})
133+
}
134+
},
135+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
apiVersion: gateway.networking.k8s.io/v1
2+
kind: HTTPRoute
3+
metadata:
4+
name: mesh-query-param-matching
5+
namespace: gateway-conformance-mesh
6+
spec:
7+
parentRefs:
8+
- group: ""
9+
kind: Service
10+
name: echo
11+
port: 80
12+
rules:
13+
- matches:
14+
- queryParams:
15+
- name: animal
16+
value: whale
17+
backendRefs:
18+
- name: echo-v1
19+
port: 8080
20+
- matches:
21+
- queryParams:
22+
- name: animal
23+
value: dolphin
24+
backendRefs:
25+
- name: echo-v2
26+
port: 8080
27+
28+
# Combinations with core match types.
29+
- matches:
30+
- path:
31+
type: PathPrefix
32+
value: /path1
33+
queryParams:
34+
- name: animal
35+
value: whale
36+
backendRefs:
37+
- name: echo-v1
38+
port: 8080
39+
- matches:
40+
- headers:
41+
- name: version
42+
value: one
43+
queryParams:
44+
- name: animal
45+
value: whale
46+
backendRefs:
47+
- name: echo-v2
48+
port: 8080
49+
50+
# Match of the form (cond1 AND cond2) OR (cond3 AND cond4 AND cond5)
51+
- matches:
52+
- path:
53+
type: PathPrefix
54+
value: /path3
55+
queryParams:
56+
- name: animal
57+
value: shark
58+
- path:
59+
type: PathPrefix
60+
value: /path4
61+
headers:
62+
- name: version
63+
value: three
64+
queryParams:
65+
- name: animal
66+
value: kraken
67+
backendRefs:
68+
- name: echo-v1
69+
port: 8080
70+
71+
# Matches for checking precedence.
72+
- matches:
73+
- path:
74+
type: PathPrefix
75+
value: /path5
76+
backendRefs:
77+
- name: echo-v1
78+
port: 8080
79+
- matches:
80+
- queryParams:
81+
- name: animal
82+
value: hydra
83+
backendRefs:
84+
- name: echo-v2
85+
port: 8080

pkg/features/mesh.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,8 @@ const (
5858
SupportMeshHTTPRouteRedirectPath FeatureName = "MeshHTTPRouteRedirectPath"
5959
// This option indicates support for HTTPRoute backend request header modification
6060
SupportMeshHTTPRouteBackendRequestHeaderModification FeatureName = "MeshHTTPRouteBackendRequestHeaderModification"
61+
// This option indicates mesh support for HTTPRoute query param matching (extended conformance).
62+
SupportMeshHTTPRouteQueryParamMatching FeatureName = "MeshHTTPRouteQueryParamMatching"
6163
)
6264

6365
var (
@@ -101,6 +103,11 @@ var (
101103
Name: SupportMeshHTTPRouteBackendRequestHeaderModification,
102104
Channel: FeatureChannelStandard,
103105
}
106+
// MeshHTTPRouteRedirectPath contains metadata for the MeshHTTPRouteRedirectPath feature.
107+
MeshHTTPRouteQueryParamMatching = Feature{
108+
Name: SupportMeshHTTPRouteQueryParamMatching,
109+
Channel: FeatureChannelStandard,
110+
}
104111
)
105112

106113
// MeshExtendedFeatures includes all the supported features for the service mesh at
@@ -112,4 +119,5 @@ var MeshExtendedFeatures = sets.New(
112119
MeshHTTPRouteSchemeRedirect,
113120
MeshHTTPRouteRedirectPath,
114121
MeshHTTPRouteBackendRequestHeaderModification,
122+
MeshHTTPRouteQueryParamMatching,
115123
)

0 commit comments

Comments
 (0)