Skip to content

Commit acbf79e

Browse files
committed
Add a conformance test that checks adding and removing listeners.
#1607
1 parent 26080e9 commit acbf79e

File tree

2 files changed

+257
-0
lines changed

2 files changed

+257
-0
lines changed
Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/*
2+
Copyright 2023 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+
"context"
21+
"testing"
22+
"time"
23+
24+
"github.com/stretchr/testify/require"
25+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26+
"k8s.io/apimachinery/pkg/types"
27+
"sigs.k8s.io/controller-runtime/pkg/client"
28+
"sigs.k8s.io/gateway-api/apis/v1beta1"
29+
"sigs.k8s.io/gateway-api/conformance/utils/kubernetes"
30+
"sigs.k8s.io/gateway-api/conformance/utils/suite"
31+
)
32+
33+
func init() {
34+
ConformanceTests = append(ConformanceTests, GatewayModifyListeners)
35+
}
36+
37+
var GatewayModifyListeners = suite.ConformanceTest{
38+
ShortName: "GatewayModifyListeners",
39+
Description: "A Gateway in the gateway-conformance-infra namespace should handle adding and removing listeners.",
40+
Manifests: []string{"tests/gateway-modify-listeners.yaml"},
41+
Test: func(t *testing.T, s *suite.ConformanceTestSuite) {
42+
43+
t.Run("should be able to add a listener that then becomes available for routing traffic", func(t *testing.T) {
44+
gwNN := types.NamespacedName{Name: "gateway-add-listener", Namespace: "gateway-conformance-infra"}
45+
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
46+
defer cancel()
47+
48+
namespaces := []string{"gateway-conformance-infra"}
49+
kubernetes.NamespacesMustBeReady(t, s.Client, s.TimeoutConfig, namespaces)
50+
original := &v1beta1.Gateway{}
51+
err := s.Client.Get(ctx, gwNN, original)
52+
require.NoErrorf(t, err, "error getting Gateway: %v", err)
53+
54+
// verify that the implementation is tracking the most recent resource changes
55+
kubernetes.GatewayMustHaveLatestConditions(t, original)
56+
57+
all := v1beta1.NamespacesFromAll
58+
59+
mutate := original.DeepCopy()
60+
61+
// add a new listener to the Gateway spec
62+
hostname := v1beta1.Hostname("data.test.com")
63+
mutate.Spec.Listeners = append(mutate.Spec.Listeners, v1beta1.Listener{
64+
Name: "http",
65+
Port: 8080,
66+
Protocol: v1beta1.HTTPProtocolType,
67+
Hostname: &hostname,
68+
AllowedRoutes: &v1beta1.AllowedRoutes{
69+
Namespaces: &v1beta1.RouteNamespaces{From: &all},
70+
},
71+
})
72+
73+
err = s.Client.Patch(ctx, mutate, client.MergeFrom(original))
74+
require.NoErrorf(t, err, "error patching the Gateway: %v", err)
75+
76+
// Ensure the generation and observedGeneration sync up
77+
kubernetes.NamespacesMustBeReady(t, s.Client, s.TimeoutConfig, namespaces)
78+
updated := &v1beta1.Gateway{}
79+
err = s.Client.Get(ctx, gwNN, updated)
80+
require.NoErrorf(t, err, "error getting Gateway: %v", err)
81+
82+
listeners := []v1beta1.ListenerStatus{
83+
{
84+
Name: v1beta1.SectionName("https"),
85+
SupportedKinds: []v1beta1.RouteGroupKind{{
86+
Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group),
87+
Kind: v1beta1.Kind("HTTPRoute"),
88+
}},
89+
Conditions: []metav1.Condition{{
90+
Type: string(v1beta1.ListenerConditionAccepted),
91+
Status: metav1.ConditionTrue,
92+
Reason: "", //any reason
93+
}},
94+
AttachedRoutes: 1,
95+
},
96+
{
97+
Name: v1beta1.SectionName("http"),
98+
SupportedKinds: []v1beta1.RouteGroupKind{{
99+
Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group),
100+
Kind: v1beta1.Kind("HTTPRoute"),
101+
}},
102+
Conditions: []metav1.Condition{{
103+
Type: string(v1beta1.ListenerConditionAccepted),
104+
Status: metav1.ConditionTrue,
105+
Reason: "", //any reason
106+
}},
107+
AttachedRoutes: 1,
108+
},
109+
}
110+
111+
kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, listeners)
112+
113+
// verify that the implementation continues to keep up to date with the resource changes we've been making
114+
kubernetes.GatewayMustHaveLatestConditions(t, updated)
115+
116+
require.NotEqual(t, original.Generation, updated.Generation, "generation should change after an update")
117+
})
118+
119+
t.Run("should be able to remove listeners, which would then stop routing the relevant traffic", func(t *testing.T) {
120+
gwNN := types.NamespacedName{Name: "gateway-remove-listener", Namespace: "gateway-conformance-infra"}
121+
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
122+
defer cancel()
123+
124+
namespaces := []string{"gateway-conformance-infra"}
125+
kubernetes.NamespacesMustBeReady(t, s.Client, s.TimeoutConfig, namespaces)
126+
original := &v1beta1.Gateway{}
127+
err := s.Client.Get(ctx, gwNN, original)
128+
require.NoErrorf(t, err, "error getting Gateway: %v", err)
129+
130+
// verify that the implementation is tracking the most recent resource changes
131+
kubernetes.GatewayMustHaveLatestConditions(t, original)
132+
133+
mutate := original.DeepCopy()
134+
require.Equalf(t, 2, len(mutate.Spec.Listeners), "the gateway must have 2 listeners")
135+
136+
// remove the "https" Gateway listener, leaving only the "http" listener
137+
var newListeners []v1beta1.Listener
138+
for _, listener := range mutate.Spec.Listeners {
139+
if listener.Name == "http" {
140+
newListeners = append(newListeners, listener)
141+
}
142+
}
143+
mutate.Spec.Listeners = newListeners
144+
145+
err = s.Client.Patch(ctx, mutate, client.MergeFrom(original))
146+
require.NoErrorf(t, err, "error patching the Gateway: %v", err)
147+
148+
// Ensure the generation and observedGeneration sync up
149+
kubernetes.NamespacesMustBeReady(t, s.Client, s.TimeoutConfig, namespaces)
150+
updated := &v1beta1.Gateway{}
151+
err = s.Client.Get(ctx, gwNN, updated)
152+
require.NoErrorf(t, err, "error getting Gateway: %v", err)
153+
154+
listeners := []v1beta1.ListenerStatus{
155+
{
156+
Name: v1beta1.SectionName("http"),
157+
SupportedKinds: []v1beta1.RouteGroupKind{{
158+
Group: (*v1beta1.Group)(&v1beta1.GroupVersion.Group),
159+
Kind: v1beta1.Kind("HTTPRoute"),
160+
}},
161+
Conditions: []metav1.Condition{{
162+
Type: string(v1beta1.ListenerConditionAccepted),
163+
Status: metav1.ConditionTrue,
164+
Reason: "", //any reason
165+
}},
166+
AttachedRoutes: 1,
167+
},
168+
}
169+
170+
kubernetes.GatewayStatusMustHaveListeners(t, s.Client, s.TimeoutConfig, gwNN, listeners)
171+
172+
// verify that the implementation continues to keep up to date with the resource changes we've been making
173+
kubernetes.GatewayMustHaveLatestConditions(t, updated)
174+
175+
require.NotEqual(t, original.Generation, updated.Generation, "generation should change after an update")
176+
})
177+
},
178+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
apiVersion: gateway.networking.k8s.io/v1beta1
2+
kind: Gateway
3+
metadata:
4+
name: gateway-add-listener
5+
namespace: gateway-conformance-infra
6+
spec:
7+
gatewayClassName: "{GATEWAY_CLASS_NAME}"
8+
listeners:
9+
- name: https
10+
port: 443
11+
protocol: HTTPS
12+
hostname: "secure.test.com"
13+
allowedRoutes:
14+
namespaces:
15+
from: All
16+
tls:
17+
certificateRefs:
18+
- group: ""
19+
kind: Secret
20+
name: tls-validity-checks-certificate
21+
namespace: gateway-conformance-infra
22+
---
23+
apiVersion: gateway.networking.k8s.io/v1beta1
24+
kind: HTTPRoute
25+
metadata:
26+
name: http-route-1
27+
namespace: gateway-conformance-infra
28+
spec:
29+
parentRefs:
30+
- kind: Gateway
31+
name: gateway-add-listener
32+
namespace: gateway-conformance-infra
33+
rules:
34+
- backendRefs:
35+
- name: foo-svc
36+
port: 8080
37+
---
38+
apiVersion: gateway.networking.k8s.io/v1beta1
39+
kind: Gateway
40+
metadata:
41+
name: gateway-remove-listener
42+
namespace: gateway-conformance-infra
43+
spec:
44+
gatewayClassName: "{GATEWAY_CLASS_NAME}"
45+
listeners:
46+
- name: https
47+
port: 443
48+
protocol: HTTPS
49+
hostname: "secure.test.com"
50+
allowedRoutes:
51+
namespaces:
52+
from: All
53+
tls:
54+
certificateRefs:
55+
- group: ""
56+
kind: Secret
57+
name: tls-validity-checks-certificate
58+
namespace: gateway-conformance-infra
59+
- name: http
60+
port: 8080
61+
protocol: HTTP
62+
allowedRoutes:
63+
namespaces:
64+
from: All
65+
---
66+
apiVersion: gateway.networking.k8s.io/v1beta1
67+
kind: HTTPRoute
68+
metadata:
69+
name: http-route-2
70+
namespace: gateway-conformance-infra
71+
spec:
72+
parentRefs:
73+
- kind: Gateway
74+
name: gateway-remove-listener
75+
namespace: gateway-conformance-infra
76+
rules:
77+
- backendRefs:
78+
- name: foo-svc
79+
port: 8080

0 commit comments

Comments
 (0)