@@ -2,18 +2,24 @@ package tcproute
2
2
3
3
import (
4
4
"context"
5
+ "fmt"
6
+ "os"
5
7
6
8
"github.com/stretchr/testify/suite"
9
+ appsv1 "k8s.io/api/apps/v1"
10
+ corev1 "k8s.io/api/core/v1"
7
11
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8
12
v1 "sigs.k8s.io/gateway-api/apis/v1"
9
13
10
14
"github.com/solo-io/gloo/pkg/utils/kubeutils"
15
+ "github.com/solo-io/gloo/pkg/utils/kubeutils/kubectl"
11
16
"github.com/solo-io/gloo/pkg/utils/requestutils/curl"
17
+ "github.com/solo-io/gloo/test/gomega/matchers"
12
18
"github.com/solo-io/gloo/test/kubernetes/e2e"
13
19
"github.com/solo-io/gloo/test/kubernetes/e2e/defaults"
14
20
)
15
21
16
- // testingSuite is the entire Suite of tests for testing K8s Service-specific features/fixes
22
+ // testingSuite is the entire suite of tests for testing K8s Service-specific features/fixes
17
23
type testingSuite struct {
18
24
suite.Suite
19
25
@@ -31,95 +37,190 @@ func NewTestingSuite(ctx context.Context, testInst *e2e.TestInstallation) suite.
31
37
}
32
38
}
33
39
34
- func (s * testingSuite ) TestConfigureTCPRouteBackingDestinationsWithSingleService () {
35
- s .T ().Cleanup (func () {
36
- err := s .testInstallation .Actions .Kubectl ().DeleteFile (s .ctx , singleTcpRouteManifest )
37
- s .NoError (err , "can delete manifest" )
38
- err = s .testInstallation .Actions .Kubectl ().DeleteFile (s .ctx , multiBackendServiceManifest )
39
- s .NoError (err , "can delete manifest" )
40
- err = s .testInstallation .Actions .Kubectl ().DeleteFile (s .ctx , singleListenerGatewayAndClientManifest )
41
- s .NoError (err , "can delete manifest" )
42
- s .testInstallation .Assertions .EventuallyObjectsNotExist (s .ctx , proxyService , proxyDeployment )
43
- })
44
-
45
- err := s .testInstallation .Actions .Kubectl ().ApplyFile (s .ctx , singleListenerGatewayAndClientManifest )
46
- 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 )
48
-
49
- err = s .testInstallation .Actions .Kubectl ().ApplyFile (s .ctx , multiBackendServiceManifest )
50
- s .Assert ().NoError (err , "can apply backend service manifest" )
51
- s .testInstallation .Assertions .EventuallyObjectsExist (s .ctx , proxyService , proxyDeployment )
52
-
53
- err = s .testInstallation .Actions .Kubectl ().ApplyFile (s .ctx , singleTcpRouteManifest )
54
- 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 )
59
-
60
- s .testInstallation .Assertions .AssertEventualCurlResponse (
61
- s .ctx ,
62
- defaults .CurlPodExecOpt ,
63
- []curl.Option {
64
- curl .WithHost (kubeutils .ServiceFQDN (proxyService .ObjectMeta )),
65
- curl .WithPort (8088 ),
66
- },
67
- expectedTcpFooSvcResp )
68
- s .testInstallation .Assertions .AssertEventualCurlResponse (
69
- s .ctx ,
70
- defaults .CurlPodExecOpt ,
71
- []curl.Option {
72
- curl .WithHost (kubeutils .ServiceFQDN (proxyService .ObjectMeta )),
73
- curl .WithPort (8088 ),
74
- },
75
- expectedTcpBarSvcResp )
40
+ func (s * testingSuite ) SetupSuite () {
41
+ var cancel context.CancelFunc
42
+ s .ctx , cancel = context .WithTimeout (context .Background (), ctxTimeout )
43
+ s .T ().Cleanup (cancel )
44
+
45
+ manifests := []string {
46
+ singleSvcNsManifest ,
47
+ singleSvcGatewayAndClientManifest ,
48
+ singleSvcBackendManifest ,
49
+ singleSvcTcpRouteManifest ,
50
+ multiSvcNsManifest ,
51
+ multiSvcGatewayAndClientManifest ,
52
+ multiSvcBackendManifest ,
53
+ multiSvcTcpRouteManifest ,
54
+ }
55
+ for _ , file := range manifests {
56
+ s .Require ().NoError (validateManifestFile (file ), "Invalid manifest file: %s" , file )
57
+ }
58
+ }
59
+
60
+ type tcpRouteTestCase struct {
61
+ name string
62
+ nsManifest string
63
+ gtwName string
64
+ gtwNs string
65
+ gtwManifest string
66
+ svcManifest string
67
+ tcpRouteManifest string
68
+ proxyService * corev1.Service
69
+ proxyDeployment * appsv1.Deployment
70
+ expectedResponses []* matchers.HttpResponse
71
+ ports []int
72
+ listenerNames []v1.SectionName
73
+ expectedRouteCounts []int32
74
+ tcpRouteNames []string
76
75
}
77
76
78
- func (s * testingSuite ) TestConfigureTCPRouteBackingDestinationsWithMultiServices () {
79
- s .T ().Skip ("skipping test until we resolve the reason it is flaky" )
80
-
81
- s .T ().Cleanup (func () {
82
- err := s .testInstallation .Actions .Kubectl ().DeleteFile (s .ctx , multiTcpRouteManifest )
83
- s .NoError (err , "can delete manifest" )
84
- err = s .testInstallation .Actions .Kubectl ().DeleteFile (s .ctx , multiBackendServiceManifest )
85
- s .NoError (err , "can delete manifest" )
86
- err = s .testInstallation .Actions .Kubectl ().DeleteFile (s .ctx , multiListenerGatewayAndClientManifest )
87
- s .NoError (err , "can delete manifest" )
88
- s .testInstallation .Assertions .EventuallyObjectsNotExist (s .ctx , proxyService , proxyDeployment )
89
- })
90
-
91
- err := s .testInstallation .Actions .Kubectl ().ApplyFile (s .ctx , multiListenerGatewayAndClientManifest )
92
- s .Assert ().NoError (err , "can apply gateway and client manifest" )
93
- s .testInstallation .Assertions .EventuallyGatewayCondition (s .ctx , "tcp-gateway" , "default" , v1 .GatewayConditionAccepted , metav1 .ConditionTrue , timeout )
94
-
95
- err = s .testInstallation .Actions .Kubectl ().ApplyFile (s .ctx , multiBackendServiceManifest )
96
- s .Assert ().NoError (err , "can apply backend service manifest" )
97
- s .testInstallation .Assertions .EventuallyObjectsExist (s .ctx , proxyService , proxyDeployment )
98
-
99
- err = s .testInstallation .Actions .Kubectl ().ApplyFile (s .ctx , multiTcpRouteManifest )
100
- s .Assert ().NoError (err , "can apply tcproute manifest" )
101
- s .testInstallation .Assertions .EventuallyTCPRouteCondition (s .ctx , "tcp-app-1" , "default" , v1 .RouteConditionAccepted , metav1 .ConditionTrue , timeout )
102
- s .testInstallation .Assertions .EventuallyTCPRouteCondition (s .ctx , "tcp-app-1" , "default" , v1 .RouteConditionResolvedRefs , metav1 .ConditionTrue , timeout )
103
- s .testInstallation .Assertions .EventuallyTCPRouteCondition (s .ctx , "tcp-app-2" , "default" , v1 .RouteConditionAccepted , metav1 .ConditionTrue , timeout )
104
- s .testInstallation .Assertions .EventuallyTCPRouteCondition (s .ctx , "tcp-app-2" , "default" , v1 .RouteConditionResolvedRefs , metav1 .ConditionTrue , timeout )
105
- s .testInstallation .Assertions .EventuallyGatewayCondition (s .ctx , "tcp-gateway" , "default" , v1 .GatewayConditionProgrammed , metav1 .ConditionTrue , timeout )
106
- s .testInstallation .Assertions .EventuallyGatewayListenerAttachedRoutes (s .ctx , "tcp-gateway" , "default" , v1 .SectionName ("foo" ), int32 (1 ), timeout )
107
- s .testInstallation .Assertions .EventuallyGatewayListenerAttachedRoutes (s .ctx , "tcp-gateway" , "default" , v1 .SectionName ("bar" ), int32 (1 ), timeout )
108
-
109
- s .testInstallation .Assertions .AssertEventualCurlResponse (
110
- s .ctx ,
111
- defaults .CurlPodExecOpt ,
112
- []curl.Option {
113
- curl .WithHost (kubeutils .ServiceFQDN (proxyService .ObjectMeta )),
114
- curl .WithPort (8088 ),
77
+ func (s * testingSuite ) TestConfigureTCPRouteBackingDestinations () {
78
+ testCases := []tcpRouteTestCase {
79
+ {
80
+ name : "SingleServiceTCPRoute" ,
81
+ nsManifest : singleSvcNsManifest ,
82
+ gtwName : singleSvcGatewayName ,
83
+ gtwNs : singleSvcNsName ,
84
+ gtwManifest : singleSvcGatewayAndClientManifest ,
85
+ svcManifest : singleSvcBackendManifest ,
86
+ tcpRouteManifest : singleSvcTcpRouteManifest ,
87
+ proxyService : singleSvcProxyService ,
88
+ proxyDeployment : singleSvcProxyDeployment ,
89
+ expectedResponses : []* matchers.HttpResponse {
90
+ expectedSingleSvcResp ,
91
+ },
92
+ ports : []int {8087 },
93
+ listenerNames : []v1.SectionName {
94
+ v1 .SectionName (singleSvcListenerName8087 ),
95
+ },
96
+ expectedRouteCounts : []int32 {1 },
97
+ tcpRouteNames : []string {singleSvcTCPRouteName },
115
98
},
116
- expectedTcpFooSvcResp )
117
- s .testInstallation .Assertions .AssertEventualCurlResponse (
118
- s .ctx ,
119
- defaults .CurlPodExecOpt ,
120
- []curl.Option {
121
- curl .WithHost (kubeutils .ServiceFQDN (proxyService .ObjectMeta )),
122
- curl .WithPort (8089 ),
99
+ {
100
+ name : "MultiServicesTCPRoute" ,
101
+ nsManifest : multiSvcNsManifest ,
102
+ gtwName : multiSvcGatewayName ,
103
+ gtwNs : multiSvcNsName ,
104
+ gtwManifest : multiSvcGatewayAndClientManifest ,
105
+ svcManifest : multiSvcBackendManifest ,
106
+ tcpRouteManifest : multiSvcTcpRouteManifest ,
107
+ proxyService : multiProxyService ,
108
+ proxyDeployment : multiProxyDeployment ,
109
+ expectedResponses : []* matchers.HttpResponse {
110
+ expectedMultiSvc1Resp ,
111
+ expectedMultiSvc2Resp ,
112
+ },
113
+ ports : []int {8088 , 8089 },
114
+ listenerNames : []v1.SectionName {
115
+ v1 .SectionName (multiSvcListenerName8088 ),
116
+ v1 .SectionName (multiSvcListenerName8089 ),
117
+ },
118
+ expectedRouteCounts : []int32 {1 , 1 },
119
+ tcpRouteNames : []string {multiSvcTCPRouteName1 , multiSvcTCPRouteName2 },
123
120
},
124
- expectedTcpBarSvcResp )
121
+ }
122
+
123
+ for _ , tc := range testCases {
124
+ tc := tc // capture range variable
125
+ s .Run (tc .name , func () {
126
+ // Cleanup function
127
+ s .T ().Cleanup (func () {
128
+ err := s .deleteManifests (tc .nsManifest )
129
+ s .Require ().NoError (err , fmt .Sprintf ("Failed to delete manifest %s" , tc .nsManifest ))
130
+
131
+ s .testInstallation .Assertions .EventuallyObjectsNotExist (s .ctx , & corev1.Namespace {ObjectMeta : metav1.ObjectMeta {Name : tc .gtwNs }})
132
+ })
133
+
134
+ // Setup environment
135
+ s .setupTestEnvironment (
136
+ tc .nsManifest ,
137
+ tc .gtwName ,
138
+ tc .gtwNs ,
139
+ tc .gtwManifest ,
140
+ tc .svcManifest ,
141
+ tc .proxyService ,
142
+ tc .proxyDeployment ,
143
+ )
144
+
145
+ // Apply TCPRoute manifest
146
+ err := s .testInstallation .Actions .Kubectl ().ApplyFile (s .ctx , tc .tcpRouteManifest )
147
+ s .Require ().NoError (err , fmt .Sprintf ("Failed to apply manifest %s" , tc .tcpRouteManifest ))
148
+
149
+ // Assert gateway conditions
150
+ s .testInstallation .Assertions .EventuallyGatewayCondition (s .ctx , tc .gtwName , tc .gtwNs , v1 .GatewayConditionAccepted , metav1 .ConditionTrue , timeout )
151
+
152
+ // Assert TCPRoute conditions
153
+ for _ , tcpRouteName := range tc .tcpRouteNames {
154
+ s .testInstallation .Assertions .EventuallyTCPRouteCondition (s .ctx , tcpRouteName , tc .gtwNs , v1 .RouteConditionAccepted , metav1 .ConditionTrue , timeout )
155
+ s .testInstallation .Assertions .EventuallyTCPRouteCondition (s .ctx , tcpRouteName , tc .gtwNs , v1 .RouteConditionResolvedRefs , metav1 .ConditionTrue , timeout )
156
+ }
157
+
158
+ // Assert gateway programmed condition
159
+ s .testInstallation .Assertions .EventuallyGatewayCondition (s .ctx , tc .gtwName , tc .gtwNs , v1 .GatewayConditionProgrammed , metav1 .ConditionTrue , timeout )
160
+
161
+ // Assert listener attached routes
162
+ for i , listenerName := range tc .listenerNames {
163
+ expectedRouteCount := tc .expectedRouteCounts [i ]
164
+ s .testInstallation .Assertions .EventuallyGatewayListenerAttachedRoutes (s .ctx , tc .gtwName , tc .gtwNs , listenerName , expectedRouteCount , timeout )
165
+ }
166
+
167
+ // Assert expected responses
168
+ for i , port := range tc .ports {
169
+ expectedResponse := tc .expectedResponses [i ]
170
+ s .testInstallation .Assertions .AssertEventualCurlResponse (
171
+ s .ctx ,
172
+ s .execOpts (tc .gtwNs ),
173
+ []curl.Option {
174
+ curl .WithHost (kubeutils .ServiceFQDN (tc .proxyService .ObjectMeta )),
175
+ curl .WithPort (port ),
176
+ },
177
+ expectedResponse )
178
+ }
179
+ })
180
+ }
181
+ }
182
+
183
+ func validateManifestFile (path string ) error {
184
+ if _ , err := os .Stat (path ); os .IsNotExist (err ) {
185
+ return fmt .Errorf ("Manifest file not found: %s" , path )
186
+ }
187
+ return nil
188
+ }
189
+
190
+ func (s * testingSuite ) setupTestEnvironment (nsManifest , gtwName , gtwNs , gtwManifest , svcManifest string , proxySvc * corev1.Service , proxyDeploy * appsv1.Deployment ) {
191
+ s .applyManifests (nsManifest )
192
+
193
+ s .applyManifests (gtwManifest )
194
+ s .testInstallation .Assertions .EventuallyGatewayCondition (s .ctx , gtwName , gtwNs , v1 .GatewayConditionAccepted , metav1 .ConditionTrue , timeout )
195
+
196
+ s .applyManifests (svcManifest )
197
+ s .testInstallation .Assertions .EventuallyObjectsExist (s .ctx , proxySvc , proxyDeploy )
198
+ }
199
+
200
+ func (s * testingSuite ) applyManifests (manifests ... string ) {
201
+ for _ , manifest := range manifests {
202
+ s .Eventually (func () bool {
203
+ err := s .testInstallation .Actions .Kubectl ().ApplyFile (s .ctx , manifest )
204
+ if err != nil {
205
+ s .T ().Logf ("Retrying apply manifest: %s, error: %v" , manifest , err )
206
+ return false
207
+ }
208
+ return true
209
+ }, waitTime , tickTime , fmt .Sprintf ("Can apply manifest %s" , manifest ))
210
+ }
211
+ }
212
+
213
+ func (s * testingSuite ) deleteManifests (manifests ... string ) error {
214
+ for _ , manifest := range manifests {
215
+ if err := s .testInstallation .Actions .Kubectl ().DeleteFile (s .ctx , manifest ); err != nil {
216
+ return err
217
+ }
218
+ }
219
+ return nil
220
+ }
221
+
222
+ func (s * testingSuite ) execOpts (ns string ) kubectl.PodExecOptions {
223
+ opts := defaults .CurlPodExecOpt
224
+ opts .Namespace = ns
225
+ return opts
125
226
}
0 commit comments