Skip to content

Commit bb97afe

Browse files
authored
Merge pull request #1827 from mmamczur/conformance-modify-listeners
Add a conformance test that checks adding and removing listeners
2 parents d5d4e6f + bf8543b commit bb97afe

File tree

2 files changed

+258
-0
lines changed

2 files changed

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