Skip to content

Commit 483799e

Browse files
danehansnfuden
andauthored
CI: Adds Ginkgo Resource Condition Assertions (#10398)
Signed-off-by: Daneyon Hansen <[email protected]> Co-authored-by: Nathan Fudenberg <[email protected]>
1 parent 7af653c commit 483799e

File tree

5 files changed

+116
-3
lines changed

5 files changed

+116
-3
lines changed
+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
changelog:
2+
- type: NON_USER_FACING
3+
issueLink: https://github.com/solo-io/gloo/issues/10397
4+
resolvesIssue: false
5+
description: >-
6+
Adds ginkgo assertions for resource status of TCPRoute e2e tests.

test/kubernetes/e2e/features/services/tcproute/suite.go

+17-2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"context"
55

66
"github.com/stretchr/testify/suite"
7+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8+
v1 "sigs.k8s.io/gateway-api/apis/v1"
79

810
"github.com/solo-io/gloo/pkg/utils/kubeutils"
911
"github.com/solo-io/gloo/pkg/utils/requestutils/curl"
@@ -42,14 +44,19 @@ func (s *testingSuite) TestConfigureTCPRouteBackingDestinationsWithSingleService
4244

4345
err := s.testInstallation.Actions.Kubectl().ApplyFile(s.ctx, singleListenerGatewayAndClientManifest)
4446
s.Assert().NoError(err, "can apply gateway and client manifest")
47+
s.testInstallation.Assertions.EventuallyGatewayCondition(s.ctx, "tcp-gateway", "default", v1.GatewayConditionAccepted, metav1.ConditionTrue, timeout)
4548

4649
err = s.testInstallation.Actions.Kubectl().ApplyFile(s.ctx, multiBackendServiceManifest)
4750
s.Assert().NoError(err, "can apply backend service manifest")
51+
s.testInstallation.Assertions.EventuallyObjectsExist(s.ctx, proxyService, proxyDeployment)
4852

4953
err = s.testInstallation.Actions.Kubectl().ApplyFile(s.ctx, singleTcpRouteManifest)
5054
s.Assert().NoError(err, "can apply tcproute manifest")
55+
s.testInstallation.Assertions.EventuallyTCPRouteCondition(s.ctx, "tcp-app-1", "default", v1.RouteConditionAccepted, metav1.ConditionTrue, timeout)
56+
s.testInstallation.Assertions.EventuallyTCPRouteCondition(s.ctx, "tcp-app-1", "default", v1.RouteConditionResolvedRefs, metav1.ConditionTrue, timeout)
57+
s.testInstallation.Assertions.EventuallyGatewayCondition(s.ctx, "tcp-gateway", "default", v1.GatewayConditionProgrammed, metav1.ConditionTrue, timeout)
58+
s.testInstallation.Assertions.EventuallyGatewayListenerAttachedRoutes(s.ctx, "tcp-gateway", "default", v1.SectionName("foo"), int32(1), timeout)
5159

52-
s.testInstallation.Assertions.EventuallyObjectsExist(s.ctx, proxyService, proxyDeployment)
5360
s.testInstallation.Assertions.AssertEventualCurlResponse(
5461
s.ctx,
5562
defaults.CurlPodExecOpt,
@@ -81,14 +88,22 @@ func (s *testingSuite) TestConfigureTCPRouteBackingDestinationsWithMultiServices
8188

8289
err := s.testInstallation.Actions.Kubectl().ApplyFile(s.ctx, multiListenerGatewayAndClientManifest)
8390
s.Assert().NoError(err, "can apply gateway and client manifest")
91+
s.testInstallation.Assertions.EventuallyGatewayCondition(s.ctx, "tcp-gateway", "default", v1.GatewayConditionAccepted, metav1.ConditionTrue, timeout)
8492

8593
err = s.testInstallation.Actions.Kubectl().ApplyFile(s.ctx, multiBackendServiceManifest)
8694
s.Assert().NoError(err, "can apply backend service manifest")
95+
s.testInstallation.Assertions.EventuallyObjectsExist(s.ctx, proxyService, proxyDeployment)
8796

8897
err = s.testInstallation.Actions.Kubectl().ApplyFile(s.ctx, multiTcpRouteManifest)
8998
s.Assert().NoError(err, "can apply tcproute manifest")
99+
s.testInstallation.Assertions.EventuallyTCPRouteCondition(s.ctx, "tcp-app-1", "default", v1.RouteConditionAccepted, metav1.ConditionTrue, timeout)
100+
s.testInstallation.Assertions.EventuallyTCPRouteCondition(s.ctx, "tcp-app-1", "default", v1.RouteConditionResolvedRefs, metav1.ConditionTrue, timeout)
101+
s.testInstallation.Assertions.EventuallyTCPRouteCondition(s.ctx, "tcp-app-2", "default", v1.RouteConditionAccepted, metav1.ConditionTrue, timeout)
102+
s.testInstallation.Assertions.EventuallyTCPRouteCondition(s.ctx, "tcp-app-2", "default", v1.RouteConditionResolvedRefs, metav1.ConditionTrue, timeout)
103+
s.testInstallation.Assertions.EventuallyGatewayCondition(s.ctx, "tcp-gateway", "default", v1.GatewayConditionProgrammed, metav1.ConditionTrue, timeout)
104+
s.testInstallation.Assertions.EventuallyGatewayListenerAttachedRoutes(s.ctx, "tcp-gateway", "default", v1.SectionName("foo"), int32(1), timeout)
105+
s.testInstallation.Assertions.EventuallyGatewayListenerAttachedRoutes(s.ctx, "tcp-gateway", "default", v1.SectionName("bar"), int32(1), timeout)
90106

91-
s.testInstallation.Assertions.EventuallyObjectsExist(s.ctx, proxyService, proxyDeployment)
92107
s.testInstallation.Assertions.AssertEventualCurlResponse(
93108
s.ctx,
94109
defaults.CurlPodExecOpt,

test/kubernetes/e2e/features/services/tcproute/types.go

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package tcproute
33
import (
44
"net/http"
55
"path/filepath"
6+
"time"
67

78
testmatchers "github.com/solo-io/gloo/test/gomega/matchers"
89

@@ -20,6 +21,8 @@ var (
2021
multiTcpRouteManifest = filepath.Join(util.MustGetThisDir(), "testdata", "multi-tcproute.yaml")
2122
singleListenerGatewayAndClientManifest = filepath.Join(util.MustGetThisDir(), "testdata", "single-listener-gateway-and-client.yaml")
2223
singleTcpRouteManifest = filepath.Join(util.MustGetThisDir(), "testdata", "single-tcproute.yaml")
24+
// Test assertion timeout
25+
timeout = 30 * time.Second
2326

2427
// Proxy resource to be translated
2528
glooProxyObjectMeta = metav1.ObjectMeta{

test/kubernetes/testutils/assertions/status.go

+89
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package assertions
22

33
import (
44
"context"
5+
"fmt"
56
"time"
67

78
"github.com/onsi/ginkgo/v2"
@@ -15,6 +16,7 @@ import (
1516
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1617
"k8s.io/apimachinery/pkg/types"
1718
gwv1 "sigs.k8s.io/gateway-api/apis/v1"
19+
gwv1a2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
1820
)
1921

2022
// Checks GetNamespacedStatuses status for gloo installation namespace
@@ -162,3 +164,90 @@ func (p *Provider) EventuallyHTTPRouteStatusContainsReason(
162164
g.Expect(route.Status.RouteStatus).To(gomega.HaveValue(matcher))
163165
}, currentTimeout, pollingInterval).Should(gomega.Succeed())
164166
}
167+
168+
// EventuallyGatewayCondition checks the provided Gateway condition is set to expect.
169+
func (p *Provider) EventuallyGatewayCondition(
170+
ctx context.Context,
171+
gatewayName string,
172+
gatewayNamespace string,
173+
cond gwv1.GatewayConditionType,
174+
expect metav1.ConditionStatus,
175+
timeout ...time.Duration,
176+
) {
177+
ginkgo.GinkgoHelper()
178+
currentTimeout, pollingInterval := helper.GetTimeouts(timeout...)
179+
p.Gomega.Eventually(func(g gomega.Gomega) {
180+
gateway := &gwv1.Gateway{}
181+
err := p.clusterContext.Client.Get(ctx, types.NamespacedName{Name: gatewayName, Namespace: gatewayNamespace}, gateway)
182+
g.Expect(err).NotTo(gomega.HaveOccurred(), "failed to get Gateway")
183+
184+
condition := getConditionByType(gateway.Status.Conditions, string(cond))
185+
g.Expect(condition).NotTo(gomega.BeNil(), fmt.Sprintf("%v condition not found", cond))
186+
g.Expect(condition.Status).To(gomega.Equal(expect), fmt.Sprintf("%v condition is not %v", cond, expect))
187+
}, currentTimeout, pollingInterval).Should(gomega.Succeed())
188+
}
189+
190+
// EventuallyGatewayListenerAttachedRoutes checks the provided Gateway contains the expected attached routes for the listener.
191+
func (p *Provider) EventuallyGatewayListenerAttachedRoutes(
192+
ctx context.Context,
193+
gatewayName string,
194+
gatewayNamespace string,
195+
listener gwv1.SectionName,
196+
routes int32,
197+
timeout ...time.Duration,
198+
) {
199+
ginkgo.GinkgoHelper()
200+
currentTimeout, pollingInterval := helper.GetTimeouts(timeout...)
201+
p.Gomega.Eventually(func(g gomega.Gomega) {
202+
gateway := &gwv1.Gateway{}
203+
err := p.clusterContext.Client.Get(ctx, types.NamespacedName{Name: gatewayName, Namespace: gatewayNamespace}, gateway)
204+
g.Expect(err).NotTo(gomega.HaveOccurred(), "failed to get Gateway")
205+
206+
found := false
207+
for _, l := range gateway.Status.Listeners {
208+
if l.Name == listener {
209+
found = true
210+
g.Expect(l.AttachedRoutes).To(gomega.Equal(routes), fmt.Sprintf("%v listener does not contain %d attached routes", l, routes))
211+
}
212+
}
213+
g.Expect(found).To(gomega.BeTrue(), fmt.Sprintf("%v listener not found", listener))
214+
}, currentTimeout, pollingInterval).Should(gomega.Succeed())
215+
}
216+
217+
// EventuallyTCPRouteCondition checks that provided TCPRoute condition is set to expect.
218+
func (p *Provider) EventuallyTCPRouteCondition(
219+
ctx context.Context,
220+
routeName string,
221+
routeNamespace string,
222+
cond gwv1.RouteConditionType,
223+
expect metav1.ConditionStatus,
224+
timeout ...time.Duration,
225+
) {
226+
ginkgo.GinkgoHelper()
227+
currentTimeout, pollingInterval := helper.GetTimeouts(timeout...)
228+
p.Gomega.Eventually(func(g gomega.Gomega) {
229+
route := &gwv1a2.TCPRoute{}
230+
err := p.clusterContext.Client.Get(ctx, types.NamespacedName{Name: routeName, Namespace: routeNamespace}, route)
231+
g.Expect(err).NotTo(gomega.HaveOccurred(), "failed to get TCPRoute")
232+
233+
var conditionFound bool
234+
for _, parentStatus := range route.Status.Parents {
235+
condition := getConditionByType(parentStatus.Conditions, string(cond))
236+
if condition != nil && condition.Status == expect {
237+
conditionFound = true
238+
break
239+
}
240+
}
241+
g.Expect(conditionFound).To(gomega.BeTrue(), fmt.Sprintf("%v condition is not %v for any parent", cond, expect))
242+
}, currentTimeout, pollingInterval).Should(gomega.Succeed())
243+
}
244+
245+
// Helper function to retrieve a condition by type from a list of conditions.
246+
func getConditionByType(conditions []metav1.Condition, conditionType string) *metav1.Condition {
247+
for _, condition := range conditions {
248+
if condition.Type == conditionType {
249+
return &condition
250+
}
251+
}
252+
return nil
253+
}

test/kubernetes/testutils/cluster/kind.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import (
1919

2020
// MustKindContext returns the Context for a KinD cluster with the given name
2121
func MustKindContext(clusterName string) *Context {
22-
return MustKindContextWithScheme(clusterName, schemes.DefaultScheme())
22+
return MustKindContextWithScheme(clusterName, schemes.TestingScheme())
2323
}
2424

2525
// MustKindContextWithScheme returns the Context for a KinD cluster with the given name and scheme

0 commit comments

Comments
 (0)