1
1
package networking
2
2
3
3
import (
4
+ "fmt"
4
5
"net"
5
6
"reflect"
6
7
"regexp"
@@ -12,6 +13,7 @@ import (
12
13
13
14
kapi "k8s.io/kubernetes/pkg/api"
14
15
kapiunversioned "k8s.io/kubernetes/pkg/api/unversioned"
16
+ utilwait "k8s.io/kubernetes/pkg/util/wait"
15
17
e2e "k8s.io/kubernetes/test/e2e/framework"
16
18
17
19
. "github.com/onsi/ginkgo"
@@ -40,27 +42,20 @@ var _ = Describe("[networking] OVS", func() {
40
42
ipPort := e2e .LaunchWebserverPod (f1 , podName , deployNodeName )
41
43
ip := strings .Split (ipPort , ":" )[0 ]
42
44
43
- newFlows := getFlowsForAllNodes (oc , nodes .Items )
44
- for _ , node := range nodes .Items {
45
- if node .Name != deployNodeName {
46
- Expect (reflect .DeepEqual (origFlows [node .Name ], newFlows [node .Name ])).To (BeTrue (), "Flows on non-deployed-to nodes should be unchanged" )
47
- }
48
- }
49
-
50
- foundPodFlow := false
51
- for _ , flow := range newFlows [deployNodeName ] {
52
- if strings .Contains (flow , "=" + ip + "," ) || strings .Contains (flow , "=" + ip + " " ) {
53
- foundPodFlow = true
54
- break
45
+ checkFlowsForAllNodes (oc , nodes .Items , func (nodeName string , newFlows []string ) error {
46
+ if nodeName == deployNodeName {
47
+ return findFlowOrError ("Should have flows referring to pod IP address" , newFlows , ip )
48
+ } else {
49
+ return matchFlowsOrError ("Flows on non-deployed-to nodes should be unchanged" , newFlows , origFlows [nodeName ])
55
50
}
56
- }
57
- Expect (foundPodFlow ).To (BeTrue (), "Should have flows referring to pod IP address" )
51
+ })
58
52
59
53
err := f1 .ClientSet .Core ().Pods (f1 .Namespace .Name ).Delete (podName , & kapi.DeleteOptions {})
60
54
Expect (err ).NotTo (HaveOccurred ())
61
55
62
- postDeleteFlows := getFlowsForNode (oc , deployNodeName )
63
- Expect (reflect .DeepEqual (origFlows [deployNodeName ], postDeleteFlows )).To (BeTrue (), "Flows after deleting pod should be same as before creating it" )
56
+ checkFlowsForNode (oc , deployNodeName , func (nodeName string , flows []string ) error {
57
+ return matchFlowsOrError ("Flows after deleting pod should be same as before creating it" , flows , origFlows [nodeName ])
58
+ })
64
59
})
65
60
66
61
It ("should add and remove flows when nodes are added and removed" , func () {
@@ -122,17 +117,9 @@ var _ = Describe("[networking] OVS", func() {
122
117
}
123
118
Expect (err ).NotTo (HaveOccurred ())
124
119
125
- newFlows := getFlowsForAllNodes (oc , nodes .Items )
126
- for nodeName := range newFlows {
127
- foundNodeFlow := false
128
- for _ , flow := range newFlows [nodeName ] {
129
- if strings .Contains (flow , "=" + newNodeIP + "," ) || strings .Contains (flow , "=" + newNodeIP + " " ) {
130
- foundNodeFlow = true
131
- break
132
- }
133
- }
134
- Expect (foundNodeFlow ).To (BeTrue (), "Should have flows referring to node IP address" )
135
- }
120
+ checkFlowsForAllNodes (oc , nodes .Items , func (nodeName string , newFlows []string ) error {
121
+ return findFlowOrError ("Should have flows referring to node IP address" , newFlows , newNodeIP )
122
+ })
136
123
137
124
err = f1 .ClientSet .Core ().Nodes ().Delete (node .Name , & kapi.DeleteOptions {})
138
125
Expect (err ).NotTo (HaveOccurred ())
@@ -145,8 +132,9 @@ var _ = Describe("[networking] OVS", func() {
145
132
}
146
133
Expect (err ).NotTo (BeNil ())
147
134
148
- postDeleteFlows := getFlowsForAllNodes (oc , nodes .Items )
149
- Expect (reflect .DeepEqual (origFlows , postDeleteFlows )).To (BeTrue (), "Flows after deleting node should be same as before creating it" )
135
+ checkFlowsForAllNodes (oc , nodes .Items , func (nodeName string , flows []string ) error {
136
+ return matchFlowsOrError ("Flows after deleting node should be same as before creating it" , flows , origFlows [nodeName ])
137
+ })
150
138
})
151
139
})
152
140
@@ -163,29 +151,49 @@ var _ = Describe("[networking] OVS", func() {
163
151
ipPort := launchWebserverService (f1 , serviceName , deployNodeName )
164
152
ip := strings .Split (ipPort , ":" )[0 ]
165
153
166
- newFlows := getFlowsForAllNodes (oc , nodes .Items )
167
- for _ , node := range nodes .Items {
168
- foundServiceFlow := false
169
- for _ , flow := range newFlows [node .Name ] {
170
- if strings .Contains (flow , "nw_dst=" + ip + "," ) || strings .Contains (flow , "nw_dst=" + ip + " " ) {
171
- foundServiceFlow = true
172
- break
173
- }
174
- }
175
- Expect (foundServiceFlow ).To (BeTrue (), "Each node contains a rule for the service" )
176
- }
154
+ checkFlowsForAllNodes (oc , nodes .Items , func (nodeName string , newFlows []string ) error {
155
+ return findFlowOrError ("Should have flows referring to service IP address" , newFlows , ip )
156
+ })
177
157
178
158
err := f1 .ClientSet .Core ().Pods (f1 .Namespace .Name ).Delete (serviceName , & kapi.DeleteOptions {})
179
159
Expect (err ).NotTo (HaveOccurred ())
180
160
err = f1 .ClientSet .Core ().Services (f1 .Namespace .Name ).Delete (serviceName , & kapi.DeleteOptions {})
181
161
Expect (err ).NotTo (HaveOccurred ())
182
162
183
- postDeleteFlows := getFlowsForAllNodes (oc , nodes .Items )
184
- Expect (reflect .DeepEqual (origFlows , postDeleteFlows )).To (BeTrue (), "Flows after deleting service should be same as before creating it" )
163
+ checkFlowsForAllNodes (oc , nodes .Items , func (nodeName string , flows []string ) error {
164
+ return matchFlowsOrError ("Flows after deleting service should be same as before creating it" , flows , origFlows [nodeName ])
165
+ })
185
166
})
186
167
})
187
168
})
188
169
170
+ type FlowError struct {
171
+ msg string
172
+ flows []string
173
+ expected []string
174
+ }
175
+
176
+ func (err FlowError ) Error () string {
177
+ return err .msg
178
+ }
179
+
180
+ func matchFlowsOrError (msg string , flows , expected []string ) error {
181
+ if reflect .DeepEqual (flows , expected ) {
182
+ return nil
183
+ } else {
184
+ return FlowError {msg , flows , expected }
185
+ }
186
+ }
187
+
188
+ func findFlowOrError (msg string , flows []string , ip string ) error {
189
+ for _ , flow := range flows {
190
+ if strings .Contains (flow , "=" + ip + "," ) || strings .Contains (flow , "=" + ip + " " ) {
191
+ return nil
192
+ }
193
+ }
194
+ return FlowError {fmt .Sprintf ("%s (%s)" , msg , ip ), flows , nil }
195
+ }
196
+
189
197
func doGetFlowsForNode (oc * testexutil.CLI , nodeName string ) ([]string , error ) {
190
198
pod := & kapi.Pod {
191
199
TypeMeta : kapiunversioned.TypeMeta {
@@ -252,12 +260,6 @@ func doGetFlowsForNode(oc *testexutil.CLI, nodeName string) ([]string, error) {
252
260
return flows , nil
253
261
}
254
262
255
- func getFlowsForNode (oc * testexutil.CLI , nodeName string ) []string {
256
- flows , err := doGetFlowsForNode (oc , nodeName )
257
- expectNoError (err )
258
- return flows
259
- }
260
-
261
263
func getFlowsForAllNodes (oc * testexutil.CLI , nodes []kapi.Node ) map [string ][]string {
262
264
var err error
263
265
flows := make (map [string ][]string , len (nodes ))
@@ -267,3 +269,54 @@ func getFlowsForAllNodes(oc *testexutil.CLI, nodes []kapi.Node) map[string][]str
267
269
}
268
270
return flows
269
271
}
272
+
273
+ type CheckFlowFunc func (nodeName string , flows []string ) error
274
+
275
+ var checkFlowBackoff = utilwait.Backoff {
276
+ Duration : time .Second ,
277
+ Factor : 2 ,
278
+ Steps : 5 ,
279
+ }
280
+
281
+ func checkFlowsForNode (oc * testexutil.CLI , nodeName string , checkFlow CheckFlowFunc ) {
282
+ var lastCheckErr error
283
+ e2e .Logf ("Checking OVS flows for node %q up to %d times" , nodeName , checkFlowBackoff .Steps )
284
+ err := utilwait .ExponentialBackoff (checkFlowBackoff , func () (bool , error ) {
285
+ flows , err := doGetFlowsForNode (oc , nodeName )
286
+ if err != nil {
287
+ return false , err
288
+ }
289
+ if lastCheckErr = checkFlow (nodeName , flows ); lastCheckErr != nil {
290
+ e2e .Logf ("Check failed (%v)" , lastCheckErr )
291
+ return false , nil
292
+ }
293
+ return true , nil
294
+ })
295
+ if err != nil && lastCheckErr != nil {
296
+ err = lastCheckErr
297
+ }
298
+ expectNoError (err )
299
+ }
300
+
301
+ func checkFlowsForAllNodes (oc * testexutil.CLI , nodes []kapi.Node , checkFlow CheckFlowFunc ) {
302
+ var lastCheckErr error
303
+ e2e .Logf ("Checking OVS flows for all nodes up to %d times" , checkFlowBackoff .Steps )
304
+ err := utilwait .ExponentialBackoff (checkFlowBackoff , func () (bool , error ) {
305
+ lastCheckErr = nil
306
+ for _ , node := range nodes {
307
+ flows , err := doGetFlowsForNode (oc , node .Name )
308
+ if err != nil {
309
+ return false , err
310
+ }
311
+ if lastCheckErr = checkFlow (node .Name , flows ); lastCheckErr != nil {
312
+ e2e .Logf ("Check failed for node %q (%v)" , node .Name , lastCheckErr )
313
+ return false , nil
314
+ }
315
+ }
316
+ return true , nil
317
+ })
318
+ if err != nil && lastCheckErr != nil {
319
+ err = lastCheckErr
320
+ }
321
+ expectNoError (err )
322
+ }
0 commit comments