1
16
17 package tests
18
19 import (
20 "testing"
21
22 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23 "k8s.io/apimachinery/pkg/types"
24
25 v1 "sigs.k8s.io/gateway-api/apis/v1"
26 "sigs.k8s.io/gateway-api/conformance/utils/http"
27 "sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
28 "sigs.k8s.io/gateway-api/conformance/utils/suite"
29 )
30
31 func init() {
32 ConformanceTests = append(ConformanceTests, HTTPRouteHostnameIntersection)
33 }
34
35 var HTTPRouteHostnameIntersection = suite.ConformanceTest{
36 ShortName: "HTTPRouteHostnameIntersection",
37 Description: "HTTPRoutes should attach to listeners only if they have intersecting hostnames, and should accept requests only for the intersecting hostnames",
38 Features: []suite.SupportedFeature{
39 suite.SupportGateway,
40 suite.SupportHTTPRoute,
41 },
42 Manifests: []string{"tests/httproute-hostname-intersection.yaml"},
43 Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
44 ns := "gateway-conformance-infra"
45 gwNN := types.NamespacedName{Name: "httproute-hostname-intersection", Namespace: ns}
46
47
48
49 kubernetes.NamespacesMustBeReady(t, suite.Client, suite.TimeoutConfig, []string{ns})
50
51 t.Run("HTTPRoutes that do intersect with listener hostnames", func(t *testing.T) {
52 routes := []types.NamespacedName{
53 {Namespace: ns, Name: "specific-host-matches-listener-specific-host"},
54 {Namespace: ns, Name: "specific-host-matches-listener-wildcard-host"},
55 {Namespace: ns, Name: "wildcard-host-matches-listener-specific-host"},
56 {Namespace: ns, Name: "wildcard-host-matches-listener-wildcard-host"},
57 }
58 gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN), routes...)
59 for _, routeNN := range routes {
60 kubernetes.HTTPRouteMustHaveResolvedRefsConditionsTrue(t, suite.Client, suite.TimeoutConfig, routeNN, gwNN)
61 }
62
63 var testCases []http.ExpectedResponse
64
65
66 testCases = append(testCases,
67 http.ExpectedResponse{
68 Request: http.Request{Host: "very.specific.com", Path: "/s1"},
69 Backend: "infra-backend-v1",
70 Namespace: ns,
71 },
72
73
74 http.ExpectedResponse{
75 Request: http.Request{Host: "very.specific.com:1234", Path: "/s1"},
76 Backend: "infra-backend-v1",
77 Namespace: ns,
78 },
79 http.ExpectedResponse{
80 Request: http.Request{Host: "non.matching.com", Path: "/s1"},
81 Response: http.Response{StatusCode: 404},
82 },
83 http.ExpectedResponse{
84 Request: http.Request{Host: "foo.nonmatchingwildcard.io", Path: "/s1"},
85 Response: http.Response{StatusCode: 404},
86 },
87 http.ExpectedResponse{
88 Request: http.Request{Host: "foo.wildcard.io", Path: "/s1"},
89 Response: http.Response{StatusCode: 404},
90 },
91 http.ExpectedResponse{
92 Request: http.Request{Host: "very.specific.com", Path: "/non-matching-prefix"},
93 Response: http.Response{StatusCode: 404},
94 },
95 )
96
97
98 testCases = append(testCases,
99 http.ExpectedResponse{
100 Request: http.Request{Host: "foo.wildcard.io", Path: "/s2"},
101 Backend: "infra-backend-v2",
102 Namespace: ns,
103 },
104 http.ExpectedResponse{
105 Request: http.Request{Host: "bar.wildcard.io", Path: "/s2"},
106 Backend: "infra-backend-v2",
107 Namespace: ns,
108 },
109 http.ExpectedResponse{
110 Request: http.Request{Host: "foo.bar.wildcard.io", Path: "/s2"},
111 Backend: "infra-backend-v2",
112 Namespace: ns,
113 },
114 http.ExpectedResponse{
115 Request: http.Request{Host: "non.matching.com", Path: "/s2"},
116 Response: http.Response{StatusCode: 404},
117 },
118 http.ExpectedResponse{
119 Request: http.Request{Host: "wildcard.io", Path: "/s2"},
120 Response: http.Response{StatusCode: 404},
121 },
122
123 http.ExpectedResponse{
124 Request: http.Request{Host: "very.specific.com", Path: "/s2"},
125 Response: http.Response{StatusCode: 404},
126 },
127 http.ExpectedResponse{
128 Request: http.Request{Host: "foo.wildcard.io", Path: "/non-matching-prefix"},
129 Response: http.Response{StatusCode: 404},
130 },
131 )
132
133
134 testCases = append(testCases,
135 http.ExpectedResponse{
136 Request: http.Request{Host: "very.specific.com", Path: "/s3"},
137 Backend: "infra-backend-v3",
138 Namespace: ns,
139 },
140 http.ExpectedResponse{
141 Request: http.Request{Host: "non.matching.com", Path: "/s3"},
142 Response: http.Response{StatusCode: 404},
143 },
144 http.ExpectedResponse{
145 Request: http.Request{Host: "foo.specific.com", Path: "/s3"},
146 Response: http.Response{StatusCode: 404},
147 },
148 http.ExpectedResponse{
149 Request: http.Request{Host: "foo.wildcard.io", Path: "/s3"},
150 Response: http.Response{StatusCode: 404},
151 },
152 http.ExpectedResponse{
153 Request: http.Request{Host: "very.specific.com", Path: "/non-matching-prefix"},
154 Response: http.Response{StatusCode: 404},
155 },
156 )
157
158
159 testCases = append(testCases,
160 http.ExpectedResponse{
161 Request: http.Request{Host: "foo.anotherwildcard.io", Path: "/s4"},
162 Backend: "infra-backend-v1",
163 Namespace: ns,
164 },
165 http.ExpectedResponse{
166 Request: http.Request{Host: "bar.anotherwildcard.io", Path: "/s4"},
167 Backend: "infra-backend-v1",
168 Namespace: ns,
169 },
170 http.ExpectedResponse{
171 Request: http.Request{Host: "foo.bar.anotherwildcard.io", Path: "/s4"},
172 Backend: "infra-backend-v1",
173 Namespace: ns,
174 },
175 http.ExpectedResponse{
176 Request: http.Request{Host: "anotherwildcard.io", Path: "/s4"},
177 Response: http.Response{StatusCode: 404},
178 },
179
180 http.ExpectedResponse{
181 Request: http.Request{Host: "foo.wildcard.io", Path: "/s4"},
182 Response: http.Response{StatusCode: 404},
183 },
184 http.ExpectedResponse{
185 Request: http.Request{Host: "very.specific.com", Path: "/s4"},
186 Response: http.Response{StatusCode: 404},
187 },
188 http.ExpectedResponse{
189 Request: http.Request{Host: "foo.anotherwildcard.io", Path: "/non-matching-prefix"},
190 Response: http.Response{StatusCode: 404},
191 },
192 )
193
194 for i := range testCases {
195
196
197 tc := testCases[i]
198 t.Run(tc.GetTestCaseName(i), func(t *testing.T) {
199 t.Parallel()
200 http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc)
201 })
202 }
203 })
204
205 t.Run("HTTPRoutes that do not intersect with listener hostnames", func(t *testing.T) {
206 gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeAccepted(t, suite.Client, suite.TimeoutConfig, suite.ControllerName, kubernetes.NewGatewayRef(gwNN))
207 routeNN := types.NamespacedName{Namespace: ns, Name: "no-intersecting-hosts"}
208
209 parents := []v1.RouteParentStatus{{
210 ParentRef: parentRefTo(gwNN),
211 ControllerName: v1.GatewayController(suite.ControllerName),
212 Conditions: []metav1.Condition{
213 {
214 Type: string(v1.RouteConditionAccepted),
215 Status: metav1.ConditionFalse,
216 Reason: string(v1.RouteReasonNoMatchingListenerHostname),
217 },
218 },
219 }}
220
221 kubernetes.HTTPRouteMustHaveParents(t, suite.Client, suite.TimeoutConfig, routeNN, parents, true)
222
223 testCases := []http.ExpectedResponse{
224 {
225 Request: http.Request{Host: "specific.but.wrong.com", Path: "/s5"},
226 Response: http.Response{StatusCode: 404},
227 },
228 {
229 Request: http.Request{Host: "wildcard.io", Path: "/s5"},
230 Response: http.Response{StatusCode: 404},
231 },
232 }
233
234 for i := range testCases {
235
236
237 tc := testCases[i]
238 t.Run(tc.GetTestCaseName(i), func(t *testing.T) {
239 t.Parallel()
240 http.MakeRequestAndExpectEventuallyConsistentResponse(t, suite.RoundTripper, suite.TimeoutConfig, gwAddr, tc)
241 })
242 }
243 })
244 },
245 }
246
247 func parentRefTo(gateway types.NamespacedName) v1.ParentReference {
248 var (
249 group = v1.Group(v1.GroupName)
250 kind = v1.Kind("Gateway")
251 namespace = v1.Namespace(gateway.Namespace)
252 name = v1.ObjectName(gateway.Name)
253 )
254
255 return v1.ParentReference{
256 Group: &group,
257 Kind: &kind,
258 Namespace: &namespace,
259 Name: name,
260 }
261 }
262
View as plain text