Skip to content

Commit b5f5cd3

Browse files
mikemorrisskrissnathancolemanrobscott
authored
Add conformance tests for ReferencePolicy (#1081)
* conformance: add test for reference policy * conformance: add test for missing ReferencePolicy preventing route attachment * conformance: add tests for improperly configured ReferencePolicy * conformance: update ReferencePolicy tests to expect eventually consistent response conformance: removed unused imports from httproute-reference-policy test * conformance: update ReferencePolicy tests to expect an Accepted: False route parent status condition * conformance: add ExtendedSupport field to ConformanceTest struct, bump to Go 1.18 for slice.Contains * conformance: opt in to ReferencePolicy tests in conformance_test.go * conformance: fixup slices module dep usage * conformance: reimplement opt-in as SupportedFeature slice on ConformanceTestSuite and ConformanceTest * fixup: remove unusued slices dep import * fixup: fix routeNN for HTTPRouteInvalidReferencePolicy * conformance(reference-policy): don't require namespace for HTTPRouteMustHaveParents check for routes in same namesapce as gateway * Update conformance/utils/suite/suite.go Co-authored-by: Steve Kriss <[email protected]> * conformance: add conditionsMatch helper func * conformance: add GatewayStatusMustHaveListeners and listenersMatch helper funcs * conformance: update InvalidReferencePolicy test to check for ResolvedRefs RefNotPermitted status * fixup: remove unused imports for HTTPRouteInvalidReferencePolicy * conformance: rename HTTPRouteMissingReferencePolicy test to HTTPRouteInvalidCrossNamespaceBackendRef update test to check for ReslovedRefs RefNotPermitted condition on Route * conformance: rename HTTPRouteInvalidCrossNamespace test to HTTPRouteInvalidCrossNamespaceParentRef * conformance: add Exemptions field to ConformanceTest struct and associated handling * conformance: add ExemptReferencePolicy exemption to HTTPRouteInvalidCrossNamespaceBackendRef test * fixup: HTTPRouteInvalidCrossNamespaceBackendRef boilerplate * conformance: skip Listener ResolvedRefs check, add TODO notes * Update conformance/tests/httproute-invalid-cross-namespace-backend-ref.go Co-authored-by: Nathan Coleman <[email protected]> * Update conformance/utils/kubernetes/helpers.go Co-authored-by: Steve Kriss <[email protected]> * Update conformance/utils/kubernetes/helpers.go * conformance: fixup ExemptReferencePolicy description * Update conformance/tests/httproute-invalid-cross-namespace-backend-ref.go * Update conformance/tests/httproute-invalid-reference-policy.go Co-authored-by: Rob Scott <[email protected]> Co-authored-by: Steve Kriss <[email protected]> Co-authored-by: Nathan Coleman <[email protected]> Co-authored-by: Rob Scott <[email protected]>
1 parent 642bf7f commit b5f5cd3

14 files changed

+478
-29
lines changed

Dockerfile

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
1414

15-
FROM golang:1.17 AS build-env
15+
FROM golang:1.18 AS build-env
1616
RUN mkdir -p /go/src/sig.k8s.io/gateway-api
1717
WORKDIR /go/src/sig.k8s.io/gateway-api
1818
COPY . .

conformance/conformance_test.go

+3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ func TestConformance(t *testing.T) {
4848
GatewayClassName: *flags.GatewayClassName,
4949
Debug: *flags.ShowDebug,
5050
CleanupBaseResources: *flags.CleanupBaseResources,
51+
SupportedFeatures: []suite.SupportedFeature{
52+
suite.SupportReferencePolicy,
53+
},
5154
})
5255
cSuite.Setup(t)
5356
cSuite.Run(t, tests.ConformanceTests)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/*
2+
Copyright 2022 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 tests
18+
19+
import (
20+
"testing"
21+
22+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23+
"k8s.io/apimachinery/pkg/types"
24+
25+
"sigs.k8s.io/gateway-api/apis/v1alpha2"
26+
"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
27+
"sigs.k8s.io/gateway-api/conformance/utils/suite"
28+
)
29+
30+
func init() {
31+
ConformanceTests = append(ConformanceTests, HTTPRouteInvalidCrossNamespaceBackendRef)
32+
}
33+
34+
var HTTPRouteInvalidCrossNamespaceBackendRef = suite.ConformanceTest{
35+
ShortName: "HTTPRouteInvalidCrossNamespaceBackendRef",
36+
Description: "A single HTTPRoute in the gateway-conformance-infra namespace should set a ResolvedRefs status False with reason RefNotPermitted when attempting to bind to a Gateway in the same namespace if the route has a BackendRef Service in the gateway-conformance-web-backend namespace and a ReferencePolicy granting permission to route to that Service does not exist",
37+
Exemptions: []suite.ExemptFeature{
38+
suite.ExemptReferencePolicy,
39+
},
40+
Manifests: []string{"tests/httproute-invalid-cross-namespace-backend-ref.yaml"},
41+
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
42+
routeNN := types.NamespacedName{Name: "invalid-cross-namespace-backend-ref", Namespace: "gateway-conformance-infra"}
43+
gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"}
44+
45+
ns := v1alpha2.Namespace(gwNN.Namespace)
46+
kind := v1alpha2.Kind("Gateway")
47+
48+
// TODO(mikemorris): Add check for Accepted condition once
49+
// https://github.com/kubernetes-sigs/gateway-api/issues/1112
50+
// has been resolved
51+
t.Run("Route status should have a route parent status with a ResolvedRefs condition with status False and reason RefNotPermitted", func(t *testing.T) {
52+
parents := []v1alpha2.RouteParentStatus{{
53+
ParentRef: v1alpha2.ParentReference{
54+
Group: (*v1alpha2.Group)(&v1alpha2.GroupVersion.Group),
55+
Kind: &kind,
56+
Name: v1alpha2.ObjectName(gwNN.Name),
57+
Namespace: &ns,
58+
},
59+
ControllerName: v1alpha2.GatewayController(suite.ControllerName),
60+
Conditions: []metav1.Condition{{
61+
Type: string(v1alpha2.RouteConditionResolvedRefs),
62+
Status: metav1.ConditionFalse,
63+
Reason: string(v1alpha2.RouteReasonRefNotPermitted),
64+
}},
65+
}}
66+
67+
kubernetes.HTTPRouteMustHaveParents(t, suite.Client, routeNN, parents, false, 60)
68+
})
69+
70+
// TODO(mikemorris): Add check for Listener attached routes or
71+
// Listener ResolvedRefs RefNotPermitted condition once
72+
// https://github.com/kubernetes-sigs/gateway-api/issues/1112
73+
// has been resolved
74+
},
75+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
apiVersion: gateway.networking.k8s.io/v1alpha2
2+
kind: HTTPRoute
3+
metadata:
4+
name: invalid-cross-namespace-backend-ref
5+
namespace: gateway-conformance-infra
6+
spec:
7+
parentRefs:
8+
- name: same-namespace
9+
rules:
10+
- backendRefs:
11+
- name: web-backend
12+
namespace: gateway-conformance-web-backend
13+
port: 8080

conformance/tests/httproute-invalid-cross-namespace.go renamed to conformance/tests/httproute-invalid-cross-namespace-parent-ref.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,15 @@ import (
2929
)
3030

3131
func init() {
32-
ConformanceTests = append(ConformanceTests, HTTPRouteInvalidCrossNamespace)
32+
ConformanceTests = append(ConformanceTests, HTTPRouteInvalidCrossNamespaceParentRef)
3333
}
3434

35-
var HTTPRouteInvalidCrossNamespace = suite.ConformanceTest{
36-
ShortName: "HTTPRouteInvalidCrossNamespace",
35+
var HTTPRouteInvalidCrossNamespaceParentRef = suite.ConformanceTest{
36+
ShortName: "HTTPRouteInvalidCrossNamespaceParentRef",
3737
Description: "A single HTTPRoute in the gateway-conformance-web-backend namespace should fail to attach to a Gateway in another namespace that it is not allowed to",
38-
Manifests: []string{"tests/httproute-invalid-cross-namespace.yaml"},
38+
Manifests: []string{"tests/httproute-invalid-cross-namespace-parent-ref.yaml"},
3939
Test: func(t *testing.T, suite *suite.ConformanceTestSuite) {
40-
routeName := types.NamespacedName{Name: "invalid-cross-namespace", Namespace: "gateway-conformance-web-backend"}
40+
routeName := types.NamespacedName{Name: "invalid-cross-namespace-parent-ref", Namespace: "gateway-conformance-web-backend"}
4141
gwName := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"}
4242

4343
// TODO: Determine if this is actually what we want. It is likely

conformance/tests/httproute-invalid-cross-namespace.yaml renamed to conformance/tests/httproute-invalid-cross-namespace-parent-ref.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
apiVersion: gateway.networking.k8s.io/v1alpha2
22
kind: HTTPRoute
33
metadata:
4-
name: invalid-cross-namespace
4+
name: invalid-cross-namespace-parent-ref
55
namespace: gateway-conformance-web-backend
66
spec:
77
parentRefs:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
Copyright 2022 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 tests
18+
19+
import (
20+
"testing"
21+
22+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
23+
"k8s.io/apimachinery/pkg/types"
24+
25+
"sigs.k8s.io/gateway-api/apis/v1alpha2"
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, HTTPRouteInvalidReferencePolicy)
33+
}
34+
35+
var HTTPRouteInvalidReferencePolicy = suite.ConformanceTest{
36+
ShortName: "HTTPRouteInvalidReferencePolicy",
37+
Description: "A single HTTPRoute in the gateway-conformance-infra namespace should fail to attach to a Gateway in the same namespace if the route has a backendRef Service in the gateway-conformance-app-backend namespace and a ReferencePolicy exists but does not grant permission to route to that specific Service",
38+
Features: []suite.SupportedFeature{
39+
suite.SupportReferencePolicy,
40+
},
41+
Manifests: []string{"tests/httproute-invalid-reference-policy.yaml"},
42+
Test: func(t *testing.T, s *suite.ConformanceTestSuite) {
43+
routeNN := types.NamespacedName{Name: "invalid-reference-policy", Namespace: "gateway-conformance-infra"}
44+
gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"}
45+
46+
ns := v1alpha2.Namespace(gwNN.Namespace)
47+
gwKind := v1alpha2.Kind("Gateway")
48+
49+
// TODO(mikemorris): Add check for Accepted condition once
50+
// https://github.com/kubernetes-sigs/gateway-api/issues/1112
51+
// has been resolved
52+
t.Run("Route status should have a route parent status with a ResolvedRefs condition with status False and reason RefNotPermitted", func(t *testing.T) {
53+
parents := []v1alpha2.RouteParentStatus{{
54+
ParentRef: v1alpha2.ParentReference{
55+
Group: (*v1alpha2.Group)(&v1alpha2.GroupVersion.Group),
56+
Kind: &gwKind,
57+
Name: v1alpha2.ObjectName(gwNN.Name),
58+
Namespace: &ns,
59+
},
60+
ControllerName: v1alpha2.GatewayController(s.ControllerName),
61+
Conditions: []metav1.Condition{{
62+
Type: string(v1alpha2.RouteConditionResolvedRefs),
63+
Status: metav1.ConditionFalse,
64+
Reason: string(v1alpha2.RouteReasonRefNotPermitted),
65+
}},
66+
}}
67+
68+
kubernetes.HTTPRouteMustHaveParents(t, s.Client, routeNN, parents, false, 60)
69+
})
70+
71+
// TODO(mikemorris): Un-skip check for Listener ResolvedRefs
72+
// RefNotPermitted condition and/or add check for attached
73+
// routes and any expected Listener conditions once
74+
// https://github.com/kubernetes-sigs/gateway-api/issues/1112
75+
// has been resolved
76+
t.Skip("Gateway listener should have a ResolvedRefs condition with status False and reason RefNotPermitted", func(t *testing.T) {
77+
listeners := []v1alpha2.ListenerStatus{{
78+
Name: v1alpha2.SectionName("http"),
79+
SupportedKinds: []v1alpha2.RouteGroupKind{{
80+
Group: (*v1alpha2.Group)(&v1alpha2.GroupVersion.Group),
81+
Kind: v1alpha2.Kind("HTTPRoute"),
82+
}},
83+
Conditions: []metav1.Condition{{
84+
Type: string(v1alpha2.RouteConditionResolvedRefs),
85+
Status: metav1.ConditionFalse,
86+
Reason: string(v1alpha2.RouteReasonRefNotPermitted),
87+
}},
88+
}}
89+
90+
kubernetes.GatewayStatusMustHaveListeners(t, s.Client, gwNN, listeners, 60)
91+
})
92+
93+
gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeReady(t, s.Client, s.ControllerName, gwNN, routeNN)
94+
95+
// TODO(mikemorris): Add check for HTTP requests successfully reaching
96+
// app-backend-v1 at path "/" if it is determined that a Route with at
97+
// at least one allowed BackendRef should be accepted by a Gateway
98+
// and partially configured.
99+
100+
t.Run("Simple HTTP request should not reach app-backend-v2", func(t *testing.T) {
101+
http.MakeRequestAndExpectEventuallyConsistentResponse(t, s.RoundTripper, gwAddr, http.ExpectedResponse{
102+
Request: http.ExpectedRequest{
103+
Method: "GET",
104+
Path: "/v2",
105+
},
106+
StatusCode: 503,
107+
})
108+
})
109+
},
110+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
apiVersion: gateway.networking.k8s.io/v1alpha2
2+
kind: ReferencePolicy
3+
metadata:
4+
name: invalid-reference-policy
5+
namespace: gateway-conformance-app-backend
6+
spec:
7+
from:
8+
- group: gateway.networking.k8s.io
9+
kind: HTTPRoute
10+
namespace: gateway-conformance-infra
11+
to:
12+
- group: ""
13+
kind: Service
14+
name: app-backend-v1
15+
---
16+
apiVersion: gateway.networking.k8s.io/v1alpha2
17+
kind: HTTPRoute
18+
metadata:
19+
name: invalid-reference-policy
20+
namespace: gateway-conformance-infra
21+
spec:
22+
parentRefs:
23+
- name: same-namespace
24+
rules:
25+
- matches:
26+
- path:
27+
value: "/v2"
28+
backendRefs:
29+
- name: app-backend-v2
30+
namespace: gateway-conformance-app-backend
31+
port: 8080
32+
- backendRefs:
33+
- name: app-backend-v1
34+
namespace: gateway-conformance-app-backend
35+
port: 8080
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
/*
2+
Copyright 2022 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 tests
18+
19+
import (
20+
"testing"
21+
22+
"k8s.io/apimachinery/pkg/types"
23+
24+
"sigs.k8s.io/gateway-api/conformance/utils/http"
25+
"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
26+
"sigs.k8s.io/gateway-api/conformance/utils/suite"
27+
)
28+
29+
func init() {
30+
ConformanceTests = append(ConformanceTests, HTTPRouteReferencePolicy)
31+
}
32+
33+
var HTTPRouteReferencePolicy = suite.ConformanceTest{
34+
ShortName: "HTTPRouteReferencePolicy",
35+
Description: "A single HTTPRoute in the gateway-conformance-infra namespace, with a backendRef in the gateway-conformance-web-backend namespace, should attach to Gateway in the gateway-conformance-infra namespace",
36+
Features: []suite.SupportedFeature{
37+
suite.SupportReferencePolicy,
38+
},
39+
Manifests: []string{"tests/httproute-reference-policy.yaml"},
40+
Test: func(t *testing.T, s *suite.ConformanceTestSuite) {
41+
routeNN := types.NamespacedName{Name: "reference-policy", Namespace: "gateway-conformance-infra"}
42+
gwNN := types.NamespacedName{Name: "same-namespace", Namespace: "gateway-conformance-infra"}
43+
gwAddr := kubernetes.GatewayAndHTTPRoutesMustBeReady(t, s.Client, s.ControllerName, gwNN, routeNN)
44+
45+
t.Run("Simple HTTP request should reach web-backend", func(t *testing.T) {
46+
http.MakeRequestAndExpectEventuallyConsistentResponse(t, s.RoundTripper, gwAddr, http.ExpectedResponse{
47+
Request: http.ExpectedRequest{
48+
Method: "GET",
49+
Path: "/",
50+
},
51+
StatusCode: 200,
52+
Backend: "web-backend",
53+
Namespace: "gateway-conformance-web-backend",
54+
})
55+
})
56+
},
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
apiVersion: gateway.networking.k8s.io/v1alpha2
2+
kind: ReferencePolicy
3+
metadata:
4+
name: reference-policy
5+
namespace: gateway-conformance-web-backend
6+
spec:
7+
from:
8+
- group: gateway.networking.k8s.io
9+
kind: HTTPRoute
10+
namespace: gateway-conformance-infra
11+
to:
12+
- group: ""
13+
kind: Service
14+
name: web-backend
15+
---
16+
apiVersion: gateway.networking.k8s.io/v1alpha2
17+
kind: HTTPRoute
18+
metadata:
19+
name: reference-policy
20+
namespace: gateway-conformance-infra
21+
spec:
22+
parentRefs:
23+
- name: same-namespace
24+
rules:
25+
- backendRefs:
26+
- name: web-backend
27+
namespace: gateway-conformance-web-backend
28+
port: 8080

0 commit comments

Comments
 (0)