@@ -21,10 +21,8 @@ import (
21
21
22
22
"k8s.io/api/core/v1"
23
23
apiequality "k8s.io/apimachinery/pkg/api/equality"
24
- "k8s.io/apimachinery/pkg/api/errors"
25
24
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26
25
"k8s.io/apimachinery/pkg/runtime"
27
- "k8s.io/apimachinery/pkg/util/wait"
28
26
"k8s.io/apimachinery/pkg/watch"
29
27
"k8s.io/kubernetes/test/e2e/framework"
30
28
@@ -33,158 +31,330 @@ import (
33
31
)
34
32
35
33
const (
36
- watchPodLabelKey = "watch-this-pod"
37
- watchPodLabelValueA = "AAA"
38
- watchPodLabelValueB = "BBB"
34
+ watchConfigMapLabelKey = "watch-this-configmap"
35
+
36
+ multipleWatchersLabelValueA = "multiple-watchers-A"
37
+ multipleWatchersLabelValueB = "multiple-watchers-B"
38
+ fromResourceVersionLabelValue = "from-resource-version"
39
+ watchRestartedLabelValue = "watch-closed-and-restarted"
40
+ toBeChangedLabelValue = "label-changed-and-restored"
39
41
)
40
42
41
43
var _ = SIGDescribe ("Watchers" , func () {
42
44
f := framework .NewDefaultFramework ("watch" )
43
45
44
- It ("should observe add, update, and delete events on pods" , func () {
46
+ /*
47
+ Testname: watch-configmaps-with-multiple-watchers
48
+ Description: Ensure that multiple watchers are able to receive all add,
49
+ update, and delete notifications on configmaps that match a label selector and do
50
+ not receive notifications for configmaps which do not match that label selector.
51
+ */
52
+ framework .ConformanceIt ("should observe add, update, and delete watch notifications on configmaps" , func () {
45
53
c := f .ClientSet
46
54
ns := f .Namespace .Name
47
55
48
- By ("creating multiple similar watches on pods " )
49
- watchA , err := watchPodsWithLabels (f , watchPodLabelValueA )
56
+ By ("creating a watch on configmaps with label A " )
57
+ watchA , err := watchConfigMaps (f , "" , multipleWatchersLabelValueA )
50
58
Expect (err ).NotTo (HaveOccurred ())
51
59
52
- watchB , err := watchPodsWithLabels (f , watchPodLabelValueB )
60
+ By ("creating a watch on configmaps with label B" )
61
+ watchB , err := watchConfigMaps (f , "" , multipleWatchersLabelValueB )
53
62
Expect (err ).NotTo (HaveOccurred ())
54
63
55
- watchAB , err := watchPodsWithLabels (f , watchPodLabelValueA , watchPodLabelValueB )
64
+ By ("creating a watch on configmaps with label A or B" )
65
+ watchAB , err := watchConfigMaps (f , "" , multipleWatchersLabelValueA , multipleWatchersLabelValueB )
56
66
Expect (err ).NotTo (HaveOccurred ())
57
67
58
- By ("creating, modifying, and deleting pods" )
59
- testPodA := & v1.Pod {
68
+ testConfigMapA := & v1.ConfigMap {
60
69
ObjectMeta : metav1.ObjectMeta {
61
- Name : "e2e-watch-test-pod -a" ,
70
+ Name : "e2e-watch-test-configmap -a" ,
62
71
Labels : map [string ]string {
63
- watchPodLabelKey : watchPodLabelValueA ,
64
- },
65
- },
66
- Spec : v1.PodSpec {
67
- Containers : []v1.Container {
68
- {
69
- Name : "example" ,
70
- Image : framework .GetPauseImageName (c ),
71
- },
72
+ watchConfigMapLabelKey : multipleWatchersLabelValueA ,
72
73
},
73
74
},
74
75
}
75
- testPodB := & v1.Pod {
76
+ testConfigMapB := & v1.ConfigMap {
76
77
ObjectMeta : metav1.ObjectMeta {
77
- Name : "e2e-watch-test-pod -b" ,
78
+ Name : "e2e-watch-test-configmap -b" ,
78
79
Labels : map [string ]string {
79
- watchPodLabelKey : watchPodLabelValueB ,
80
- },
81
- },
82
- Spec : v1.PodSpec {
83
- Containers : []v1.Container {
84
- {
85
- Name : "example" ,
86
- Image : framework .GetPauseImageName (c ),
87
- },
80
+ watchConfigMapLabelKey : multipleWatchersLabelValueB ,
88
81
},
89
82
},
90
83
}
91
- testPodA , err = c .CoreV1 ().Pods (ns ).Create (testPodA )
84
+
85
+ By ("creating a configmap with label A and ensuring the correct watchers observe the notification" )
86
+ testConfigMapA , err = c .CoreV1 ().ConfigMaps (ns ).Create (testConfigMapA )
92
87
Expect (err ).NotTo (HaveOccurred ())
93
- expectEvent (watchA , watch .Added , testPodA )
94
- expectEvent (watchAB , watch .Added , testPodA )
95
- expectNoEvent (watchB , watch .Added , testPodA )
88
+ expectEvent (watchA , watch .Added , testConfigMapA )
89
+ expectEvent (watchAB , watch .Added , testConfigMapA )
90
+ expectNoEvent (watchB , watch .Added , testConfigMapA )
96
91
97
- testPodA , err = updatePod (f , testPodA .GetName (), func (p * v1.Pod ) {
98
- p .ObjectMeta .Labels ["mutation" ] = "1"
92
+ By ("modifying configmap A and ensuring the correct watchers observe the notification" )
93
+ testConfigMapA , err = updateConfigMap (c , ns , testConfigMapA .GetName (), func (cm * v1.ConfigMap ) {
94
+ setConfigMapData (cm , "mutation" , "1" )
99
95
})
100
96
Expect (err ).NotTo (HaveOccurred ())
101
- expectEvent (watchA , watch .Modified , testPodA )
102
- expectEvent (watchAB , watch .Modified , testPodA )
103
- expectNoEvent (watchB , watch .Modified , testPodA )
97
+ expectEvent (watchA , watch .Modified , testConfigMapA )
98
+ expectEvent (watchAB , watch .Modified , testConfigMapA )
99
+ expectNoEvent (watchB , watch .Modified , testConfigMapA )
104
100
105
- testPodA , err = updatePod (f , testPodA .GetName (), func (p * v1.Pod ) {
106
- p .ObjectMeta .Labels ["mutation" ] = "2"
101
+ By ("modifying configmap A again and ensuring the correct watchers observe the notification" )
102
+ testConfigMapA , err = updateConfigMap (c , ns , testConfigMapA .GetName (), func (cm * v1.ConfigMap ) {
103
+ setConfigMapData (cm , "mutation" , "2" )
107
104
})
108
105
Expect (err ).NotTo (HaveOccurred ())
109
- expectEvent (watchA , watch .Modified , testPodA )
110
- expectEvent (watchAB , watch .Modified , testPodA )
111
- expectNoEvent (watchB , watch .Modified , testPodA )
106
+ expectEvent (watchA , watch .Modified , testConfigMapA )
107
+ expectEvent (watchAB , watch .Modified , testConfigMapA )
108
+ expectNoEvent (watchB , watch .Modified , testConfigMapA )
112
109
113
- err = c .CoreV1 ().Pods (ns ).Delete (testPodA .GetName (), nil )
110
+ By ("deleting configmap A and ensuring the correct watchers observe the notification" )
111
+ err = c .CoreV1 ().ConfigMaps (ns ).Delete (testConfigMapA .GetName (), nil )
114
112
Expect (err ).NotTo (HaveOccurred ())
115
113
expectEvent (watchA , watch .Deleted , nil )
116
114
expectEvent (watchAB , watch .Deleted , nil )
117
115
expectNoEvent (watchB , watch .Deleted , nil )
118
116
119
- testPodB , err = c .CoreV1 ().Pods (ns ).Create (testPodB )
117
+ By ("creating a configmap with label B and ensuring the correct watchers observe the notification" )
118
+ testConfigMapB , err = c .CoreV1 ().ConfigMaps (ns ).Create (testConfigMapB )
120
119
Expect (err ).NotTo (HaveOccurred ())
121
- expectEvent (watchB , watch .Added , testPodB )
122
- expectEvent (watchAB , watch .Added , testPodB )
123
- expectNoEvent (watchA , watch .Added , testPodB )
120
+ expectEvent (watchB , watch .Added , testConfigMapB )
121
+ expectEvent (watchAB , watch .Added , testConfigMapB )
122
+ expectNoEvent (watchA , watch .Added , testConfigMapB )
124
123
125
- err = c .CoreV1 ().Pods (ns ).Delete (testPodB .GetName (), nil )
124
+ By ("deleting configmap B and ensuring the correct watchers observe the notification" )
125
+ err = c .CoreV1 ().ConfigMaps (ns ).Delete (testConfigMapB .GetName (), nil )
126
126
Expect (err ).NotTo (HaveOccurred ())
127
127
expectEvent (watchB , watch .Deleted , nil )
128
128
expectEvent (watchAB , watch .Deleted , nil )
129
129
expectNoEvent (watchA , watch .Deleted , nil )
130
130
})
131
+
132
+ /*
133
+ Testname: watch-configmaps-from-resource-version
134
+ Description: Ensure that a watch can be opened from a particular resource version
135
+ in the past and only notifications happening after that resource version are observed.
136
+ */
137
+ framework .ConformanceIt ("should be able to start watching from a specific resource version" , func () {
138
+ c := f .ClientSet
139
+ ns := f .Namespace .Name
140
+
141
+ testConfigMap := & v1.ConfigMap {
142
+ ObjectMeta : metav1.ObjectMeta {
143
+ Name : "e2e-watch-test-resource-version" ,
144
+ Labels : map [string ]string {
145
+ watchConfigMapLabelKey : fromResourceVersionLabelValue ,
146
+ },
147
+ },
148
+ }
149
+
150
+ By ("creating a new configmap" )
151
+ testConfigMap , err := c .CoreV1 ().ConfigMaps (ns ).Create (testConfigMap )
152
+ Expect (err ).NotTo (HaveOccurred ())
153
+
154
+ By ("modifying the configmap once" )
155
+ testConfigMapFirstUpdate , err := updateConfigMap (c , ns , testConfigMap .GetName (), func (cm * v1.ConfigMap ) {
156
+ setConfigMapData (cm , "mutation" , "1" )
157
+ })
158
+ Expect (err ).NotTo (HaveOccurred ())
159
+
160
+ By ("modifying the configmap a second time" )
161
+ testConfigMapSecondUpdate , err := updateConfigMap (c , ns , testConfigMap .GetName (), func (cm * v1.ConfigMap ) {
162
+ setConfigMapData (cm , "mutation" , "2" )
163
+ })
164
+ Expect (err ).NotTo (HaveOccurred ())
165
+
166
+ By ("deleting the configmap" )
167
+ err = c .CoreV1 ().ConfigMaps (ns ).Delete (testConfigMap .GetName (), nil )
168
+ Expect (err ).NotTo (HaveOccurred ())
169
+
170
+ By ("creating a watch on configmaps from the resource version returned by the first update" )
171
+ testWatch , err := watchConfigMaps (f , testConfigMapFirstUpdate .ObjectMeta .ResourceVersion , fromResourceVersionLabelValue )
172
+ Expect (err ).NotTo (HaveOccurred ())
173
+
174
+ By ("Expecting to observe notifications for all changes to the configmap after the first update" )
175
+ expectEvent (testWatch , watch .Modified , testConfigMapSecondUpdate )
176
+ expectEvent (testWatch , watch .Deleted , nil )
177
+ })
178
+
179
+ /*
180
+ Testname: watch-configmaps-closed-and-restarted
181
+ Description: Ensure that a watch can be reopened from the last resource version
182
+ observed by the previous watch, and it will continue delivering notifications from
183
+ that point in time.
184
+ */
185
+ framework .ConformanceIt ("should be able to restart watching from the last resource version observed by the previous watch" , func () {
186
+ c := f .ClientSet
187
+ ns := f .Namespace .Name
188
+
189
+ testConfigMap := & v1.ConfigMap {
190
+ ObjectMeta : metav1.ObjectMeta {
191
+ Name : "e2e-watch-test-watch-closed" ,
192
+ Labels : map [string ]string {
193
+ watchConfigMapLabelKey : watchRestartedLabelValue ,
194
+ },
195
+ },
196
+ }
197
+
198
+ By ("creating a watch on configmaps" )
199
+ testWatchBroken , err := watchConfigMaps (f , "" , watchRestartedLabelValue )
200
+ Expect (err ).NotTo (HaveOccurred ())
201
+
202
+ By ("creating a new configmap" )
203
+ testConfigMap , err = c .CoreV1 ().ConfigMaps (ns ).Create (testConfigMap )
204
+ Expect (err ).NotTo (HaveOccurred ())
205
+
206
+ By ("modifying the configmap once" )
207
+ _ , err = updateConfigMap (c , ns , testConfigMap .GetName (), func (cm * v1.ConfigMap ) {
208
+ setConfigMapData (cm , "mutation" , "1" )
209
+ })
210
+ Expect (err ).NotTo (HaveOccurred ())
211
+
212
+ By ("closing the watch once it receives two notifications" )
213
+ expectEvent (testWatchBroken , watch .Added , testConfigMap )
214
+ lastEvent , ok := waitForEvent (testWatchBroken , watch .Modified , nil , 1 * time .Minute )
215
+ if ! ok {
216
+ framework .Failf ("Timed out waiting for second watch notification" )
217
+ }
218
+ testWatchBroken .Stop ()
219
+
220
+ By ("modifying the configmap a second time, while the watch is closed" )
221
+ testConfigMapSecondUpdate , err := updateConfigMap (c , ns , testConfigMap .GetName (), func (cm * v1.ConfigMap ) {
222
+ setConfigMapData (cm , "mutation" , "2" )
223
+ })
224
+ Expect (err ).NotTo (HaveOccurred ())
225
+
226
+ By ("creating a new watch on configmaps from the last resource version observed by the first watch" )
227
+ lastEventConfigMap , ok := lastEvent .Object .(* v1.ConfigMap )
228
+ if ! ok {
229
+ framework .Failf ("Expected last notfication to refer to a configmap but got: %v" , lastEvent )
230
+ }
231
+ testWatchRestarted , err := watchConfigMaps (f , lastEventConfigMap .ObjectMeta .ResourceVersion , watchRestartedLabelValue )
232
+ Expect (err ).NotTo (HaveOccurred ())
233
+
234
+ By ("deleting the configmap" )
235
+ err = c .CoreV1 ().ConfigMaps (ns ).Delete (testConfigMap .GetName (), nil )
236
+ Expect (err ).NotTo (HaveOccurred ())
237
+
238
+ By ("Expecting to observe notifications for all changes to the configmap since the first watch closed" )
239
+ expectEvent (testWatchRestarted , watch .Modified , testConfigMapSecondUpdate )
240
+ expectEvent (testWatchRestarted , watch .Deleted , nil )
241
+ })
242
+
243
+ /*
244
+ Testname: watch-configmaps-label-changed
245
+ Description: Ensure that a watched object stops meeting the requirements of
246
+ a watch's selector, the watch will observe a delete, and will not observe
247
+ notifications for that object until it meets the selector's requirements again.
248
+ */
249
+ framework .ConformanceIt ("should observe an object deletion if it stops meeting the requirements of the selector" , func () {
250
+ c := f .ClientSet
251
+ ns := f .Namespace .Name
252
+
253
+ testConfigMap := & v1.ConfigMap {
254
+ ObjectMeta : metav1.ObjectMeta {
255
+ Name : "e2e-watch-test-label-changed" ,
256
+ Labels : map [string ]string {
257
+ watchConfigMapLabelKey : toBeChangedLabelValue ,
258
+ },
259
+ },
260
+ }
261
+
262
+ By ("creating a watch on configmaps with a certain label" )
263
+ testWatch , err := watchConfigMaps (f , "" , toBeChangedLabelValue )
264
+ Expect (err ).NotTo (HaveOccurred ())
265
+
266
+ By ("creating a new configmap" )
267
+ testConfigMap , err = c .CoreV1 ().ConfigMaps (ns ).Create (testConfigMap )
268
+ Expect (err ).NotTo (HaveOccurred ())
269
+
270
+ By ("modifying the configmap once" )
271
+ testConfigMapFirstUpdate , err := updateConfigMap (c , ns , testConfigMap .GetName (), func (cm * v1.ConfigMap ) {
272
+ setConfigMapData (cm , "mutation" , "1" )
273
+ })
274
+ Expect (err ).NotTo (HaveOccurred ())
275
+
276
+ By ("changing the label value of the configmap" )
277
+ _ , err = updateConfigMap (c , ns , testConfigMap .GetName (), func (cm * v1.ConfigMap ) {
278
+ cm .ObjectMeta .Labels [watchConfigMapLabelKey ] = "wrong-value"
279
+ })
280
+ Expect (err ).NotTo (HaveOccurred ())
281
+
282
+ By ("Expecting to observe a delete notification for the watched object" )
283
+ expectEvent (testWatch , watch .Added , testConfigMap )
284
+ expectEvent (testWatch , watch .Modified , testConfigMapFirstUpdate )
285
+ expectEvent (testWatch , watch .Deleted , nil )
286
+
287
+ By ("modifying the configmap a second time" )
288
+ testConfigMapSecondUpdate , err := updateConfigMap (c , ns , testConfigMap .GetName (), func (cm * v1.ConfigMap ) {
289
+ setConfigMapData (cm , "mutation" , "2" )
290
+ })
291
+ Expect (err ).NotTo (HaveOccurred ())
292
+
293
+ By ("Expecting not to observe a notification because the object no longer meets the selector's requirements" )
294
+ expectNoEvent (testWatch , watch .Modified , testConfigMapSecondUpdate )
295
+
296
+ By ("changing the label value of the configmap back" )
297
+ testConfigMapLabelRestored , err := updateConfigMap (c , ns , testConfigMap .GetName (), func (cm * v1.ConfigMap ) {
298
+ cm .ObjectMeta .Labels [watchConfigMapLabelKey ] = toBeChangedLabelValue
299
+ })
300
+ Expect (err ).NotTo (HaveOccurred ())
301
+
302
+ By ("modifying the configmap a third time" )
303
+ testConfigMapThirdUpdate , err := updateConfigMap (c , ns , testConfigMap .GetName (), func (cm * v1.ConfigMap ) {
304
+ setConfigMapData (cm , "mutation" , "3" )
305
+ })
306
+ Expect (err ).NotTo (HaveOccurred ())
307
+
308
+ By ("deleting the configmap" )
309
+ err = c .CoreV1 ().ConfigMaps (ns ).Delete (testConfigMap .GetName (), nil )
310
+ Expect (err ).NotTo (HaveOccurred ())
311
+
312
+ By ("Expecting to observe an add notification for the watched object when the label value was restored" )
313
+ expectEvent (testWatch , watch .Added , testConfigMapLabelRestored )
314
+ expectEvent (testWatch , watch .Modified , testConfigMapThirdUpdate )
315
+ expectEvent (testWatch , watch .Deleted , nil )
316
+ })
131
317
})
132
318
133
- func watchPodsWithLabels (f * framework.Framework , labels ... string ) (watch.Interface , error ) {
319
+ func watchConfigMaps (f * framework.Framework , resourceVersion string , labels ... string ) (watch.Interface , error ) {
134
320
c := f .ClientSet
135
321
ns := f .Namespace .Name
136
322
opts := metav1.ListOptions {
323
+ ResourceVersion : resourceVersion ,
137
324
LabelSelector : metav1 .FormatLabelSelector (& metav1.LabelSelector {
138
325
MatchExpressions : []metav1.LabelSelectorRequirement {
139
326
{
140
- Key : watchPodLabelKey ,
327
+ Key : watchConfigMapLabelKey ,
141
328
Operator : metav1 .LabelSelectorOpIn ,
142
329
Values : labels ,
143
330
},
144
331
},
145
332
}),
146
333
}
147
- return c .CoreV1 ().Pods (ns ).Watch (opts )
334
+ return c .CoreV1 ().ConfigMaps (ns ).Watch (opts )
148
335
}
149
336
150
337
func int64ptr (i int ) * int64 {
151
338
i64 := int64 (i )
152
339
return & i64
153
340
}
154
341
155
- type updatePodFunc func (p * v1.Pod )
156
-
157
- func updatePod (f * framework.Framework , name string , update updatePodFunc ) (* v1.Pod , error ) {
158
- c := f .ClientSet
159
- ns := f .Namespace .Name
160
- var p * v1.Pod
161
- pollErr := wait .PollImmediate (2 * time .Second , 1 * time .Minute , func () (bool , error ) {
162
- var err error
163
- if p , err = c .CoreV1 ().Pods (ns ).Get (name , metav1.GetOptions {}); err != nil {
164
- return false , err
165
- }
166
- update (p )
167
- if p , err = c .CoreV1 ().Pods (ns ).Update (p ); err == nil {
168
- return true , nil
169
- }
170
- // Only retry update on conflict
171
- if ! errors .IsConflict (err ) {
172
- return false , err
173
- }
174
- return false , nil
175
- })
176
- return p , pollErr
342
+ func setConfigMapData (cm * v1.ConfigMap , key , value string ) {
343
+ if cm .Data == nil {
344
+ cm .Data = make (map [string ]string )
345
+ }
346
+ cm .Data [key ] = value
177
347
}
178
348
179
349
func expectEvent (w watch.Interface , eventType watch.EventType , object runtime.Object ) {
180
350
if event , ok := waitForEvent (w , eventType , object , 1 * time .Minute ); ! ok {
181
- framework .Failf ("Timed out waiting for expected event : %v" , event )
351
+ framework .Failf ("Timed out waiting for expected watch notification : %v" , event )
182
352
}
183
353
}
184
354
185
355
func expectNoEvent (w watch.Interface , eventType watch.EventType , object runtime.Object ) {
186
356
if event , ok := waitForEvent (w , eventType , object , 10 * time .Second ); ok {
187
- framework .Failf ("Unexpected event occurred : %v" , event )
357
+ framework .Failf ("Unexpected watch notification observed : %v" , event )
188
358
}
189
359
}
190
360
0 commit comments