@@ -20,10 +20,11 @@ import (
20
20
)
21
21
22
22
type predicateTestCase struct {
23
- name string
24
- etcdSpecChanged bool
25
- etcdStatusChanged bool
26
- lastOperationState * druidv1alpha1.LastOperationState
23
+ name string
24
+ etcdSpecChanged bool
25
+ etcdStatusChanged bool
26
+ previouslyReconciled bool
27
+ lastOperationState * druidv1alpha1.LastOperationState
27
28
// expected behavior for different event types
28
29
shouldAllowCreateEvent bool
29
30
shouldAllowDeleteEvent bool
@@ -45,6 +46,7 @@ func TestBuildPredicateWithOnlyAutoReconcileEnabled(t *testing.T) {
45
46
{
46
47
name : "only spec has changed and previous reconciliation has completed" ,
47
48
etcdSpecChanged : true ,
49
+ previouslyReconciled : true ,
48
50
lastOperationState : ptr .To (druidv1alpha1 .LastOperationStateSucceeded ),
49
51
shouldAllowCreateEvent : true ,
50
52
shouldAllowDeleteEvent : true ,
@@ -54,6 +56,7 @@ func TestBuildPredicateWithOnlyAutoReconcileEnabled(t *testing.T) {
54
56
{
55
57
name : "only spec has changed and previous reconciliation has errored" ,
56
58
etcdSpecChanged : true ,
59
+ previouslyReconciled : true ,
57
60
lastOperationState : ptr .To (druidv1alpha1 .LastOperationStateError ),
58
61
shouldAllowCreateEvent : true ,
59
62
shouldAllowDeleteEvent : true ,
@@ -63,6 +66,7 @@ func TestBuildPredicateWithOnlyAutoReconcileEnabled(t *testing.T) {
63
66
{
64
67
name : "only status has changed" ,
65
68
etcdStatusChanged : true ,
69
+ previouslyReconciled : true ,
66
70
shouldAllowCreateEvent : true ,
67
71
shouldAllowDeleteEvent : true ,
68
72
shouldAllowGenericEvent : false ,
@@ -72,6 +76,7 @@ func TestBuildPredicateWithOnlyAutoReconcileEnabled(t *testing.T) {
72
76
name : "both spec and status have changed and previous reconciliation is in progress" ,
73
77
etcdSpecChanged : true ,
74
78
etcdStatusChanged : true ,
79
+ previouslyReconciled : true ,
75
80
lastOperationState : ptr .To (druidv1alpha1 .LastOperationStateProcessing ),
76
81
shouldAllowCreateEvent : true ,
77
82
shouldAllowDeleteEvent : true ,
@@ -80,11 +85,21 @@ func TestBuildPredicateWithOnlyAutoReconcileEnabled(t *testing.T) {
80
85
},
81
86
{
82
87
name : "neither spec nor status has changed" ,
88
+ previouslyReconciled : true ,
83
89
shouldAllowCreateEvent : true ,
84
90
shouldAllowDeleteEvent : true ,
85
91
shouldAllowGenericEvent : false ,
86
92
shouldAllowUpdateEvent : false ,
87
93
},
94
+ {
95
+ // This case is described in https://github.com/gardener/etcd-druid/issues/898
96
+ name : "for an existing Etcd resource, neither spec nor status has changed and it has never been reconciled before" ,
97
+ previouslyReconciled : false ,
98
+ shouldAllowCreateEvent : true ,
99
+ shouldAllowDeleteEvent : true ,
100
+ shouldAllowGenericEvent : false ,
101
+ shouldAllowUpdateEvent : true ,
102
+ },
88
103
}
89
104
g := NewWithT (t )
90
105
etcd := createEtcd ()
@@ -93,7 +108,7 @@ func TestBuildPredicateWithOnlyAutoReconcileEnabled(t *testing.T) {
93
108
for _ , tc := range testCases {
94
109
t .Run (tc .name , func (t * testing.T ) {
95
110
t .Parallel ()
96
- updatedEtcd := updateEtcd (etcd , tc .etcdSpecChanged , tc .etcdStatusChanged , tc .lastOperationState , false )
111
+ updatedEtcd := updateEtcd (etcd , tc .etcdSpecChanged , tc .etcdStatusChanged , tc .previouslyReconciled , tc . lastOperationState , false )
97
112
g .Expect (predicate .Create (event.CreateEvent {Object : updatedEtcd })).To (Equal (tc .shouldAllowCreateEvent ))
98
113
g .Expect (predicate .Delete (event.DeleteEvent {Object : updatedEtcd })).To (Equal (tc .shouldAllowDeleteEvent ))
99
114
g .Expect (predicate .Generic (event.GenericEvent {Object : updatedEtcd })).To (Equal (tc .shouldAllowGenericEvent ))
@@ -107,6 +122,7 @@ func TestBuildPredicateWithNoAutoReconcileAndNoReconcileAnnot(t *testing.T) {
107
122
{
108
123
name : "only spec has changed" ,
109
124
etcdSpecChanged : true ,
125
+ previouslyReconciled : true ,
110
126
shouldAllowCreateEvent : true ,
111
127
shouldAllowDeleteEvent : true ,
112
128
shouldAllowGenericEvent : false ,
@@ -115,6 +131,7 @@ func TestBuildPredicateWithNoAutoReconcileAndNoReconcileAnnot(t *testing.T) {
115
131
{
116
132
name : "only status has changed" ,
117
133
etcdStatusChanged : true ,
134
+ previouslyReconciled : true ,
118
135
shouldAllowCreateEvent : true ,
119
136
shouldAllowDeleteEvent : true ,
120
137
shouldAllowGenericEvent : false ,
@@ -123,6 +140,7 @@ func TestBuildPredicateWithNoAutoReconcileAndNoReconcileAnnot(t *testing.T) {
123
140
{
124
141
name : "both spec and status have changed" ,
125
142
etcdSpecChanged : true ,
143
+ previouslyReconciled : true ,
126
144
etcdStatusChanged : true ,
127
145
shouldAllowCreateEvent : true ,
128
146
shouldAllowDeleteEvent : true ,
@@ -131,6 +149,16 @@ func TestBuildPredicateWithNoAutoReconcileAndNoReconcileAnnot(t *testing.T) {
131
149
},
132
150
{
133
151
name : "neither spec nor status has changed" ,
152
+ previouslyReconciled : true ,
153
+ shouldAllowCreateEvent : true ,
154
+ shouldAllowDeleteEvent : true ,
155
+ shouldAllowGenericEvent : false ,
156
+ shouldAllowUpdateEvent : false ,
157
+ },
158
+ {
159
+ // This case is described in https://github.com/gardener/etcd-druid/issues/898
160
+ name : "for an existing Etcd resource, neither spec nor status has changed and it has never been reconciled before" ,
161
+ previouslyReconciled : false ,
134
162
shouldAllowCreateEvent : true ,
135
163
shouldAllowDeleteEvent : true ,
136
164
shouldAllowGenericEvent : false ,
@@ -144,7 +172,7 @@ func TestBuildPredicateWithNoAutoReconcileAndNoReconcileAnnot(t *testing.T) {
144
172
for _ , tc := range testCases {
145
173
t .Run (tc .name , func (t * testing.T ) {
146
174
t .Parallel ()
147
- updatedEtcd := updateEtcd (etcd , tc .etcdSpecChanged , tc .etcdStatusChanged , tc .lastOperationState , false )
175
+ updatedEtcd := updateEtcd (etcd , tc .etcdSpecChanged , tc .etcdStatusChanged , tc .previouslyReconciled , tc . lastOperationState , false )
148
176
g .Expect (predicate .Create (event.CreateEvent {Object : updatedEtcd })).To (Equal (tc .shouldAllowCreateEvent ))
149
177
g .Expect (predicate .Delete (event.DeleteEvent {Object : updatedEtcd })).To (Equal (tc .shouldAllowDeleteEvent ))
150
178
g .Expect (predicate .Generic (event.GenericEvent {Object : updatedEtcd })).To (Equal (tc .shouldAllowGenericEvent ))
@@ -168,6 +196,7 @@ func TestBuildPredicateWithNoAutoReconcileButReconcileAnnotPresent(t *testing.T)
168
196
name : "only spec has changed and previous reconciliation is completed" ,
169
197
etcdSpecChanged : true ,
170
198
lastOperationState : ptr .To (druidv1alpha1 .LastOperationStateSucceeded ),
199
+ previouslyReconciled : true ,
171
200
shouldAllowCreateEvent : true ,
172
201
shouldAllowDeleteEvent : true ,
173
202
shouldAllowGenericEvent : false ,
@@ -176,6 +205,7 @@ func TestBuildPredicateWithNoAutoReconcileButReconcileAnnotPresent(t *testing.T)
176
205
{
177
206
name : "only status has changed and previous reconciliation is in progress" ,
178
207
etcdStatusChanged : true ,
208
+ previouslyReconciled : true ,
179
209
lastOperationState : ptr .To (druidv1alpha1 .LastOperationStateProcessing ),
180
210
shouldAllowCreateEvent : true ,
181
211
shouldAllowDeleteEvent : true ,
@@ -185,6 +215,7 @@ func TestBuildPredicateWithNoAutoReconcileButReconcileAnnotPresent(t *testing.T)
185
215
{
186
216
name : "only status has changed and previous reconciliation is completed" ,
187
217
etcdStatusChanged : true ,
218
+ previouslyReconciled : true ,
188
219
lastOperationState : ptr .To (druidv1alpha1 .LastOperationStateSucceeded ),
189
220
shouldAllowCreateEvent : true ,
190
221
shouldAllowDeleteEvent : true ,
@@ -195,6 +226,7 @@ func TestBuildPredicateWithNoAutoReconcileButReconcileAnnotPresent(t *testing.T)
195
226
name : "both spec and status have changed" ,
196
227
etcdSpecChanged : true ,
197
228
etcdStatusChanged : true ,
229
+ previouslyReconciled : true ,
198
230
shouldAllowCreateEvent : true ,
199
231
shouldAllowDeleteEvent : true ,
200
232
shouldAllowGenericEvent : false ,
@@ -203,6 +235,7 @@ func TestBuildPredicateWithNoAutoReconcileButReconcileAnnotPresent(t *testing.T)
203
235
{
204
236
name : "neither spec nor status has changed and previous reconciliation is in error" ,
205
237
lastOperationState : ptr .To (druidv1alpha1 .LastOperationStateError ),
238
+ previouslyReconciled : true ,
206
239
shouldAllowCreateEvent : true ,
207
240
shouldAllowDeleteEvent : true ,
208
241
shouldAllowGenericEvent : false ,
@@ -211,6 +244,16 @@ func TestBuildPredicateWithNoAutoReconcileButReconcileAnnotPresent(t *testing.T)
211
244
{
212
245
name : "neither spec nor status has changed and previous reconciliation is completed" ,
213
246
lastOperationState : ptr .To (druidv1alpha1 .LastOperationStateSucceeded ),
247
+ previouslyReconciled : true ,
248
+ shouldAllowCreateEvent : true ,
249
+ shouldAllowDeleteEvent : true ,
250
+ shouldAllowGenericEvent : false ,
251
+ shouldAllowUpdateEvent : true ,
252
+ },
253
+ {
254
+ // This case is described in https://github.com/gardener/etcd-druid/issues/898
255
+ name : "for an existing Etcd resource, neither spec nor status has changed and it has never been reconciled before" ,
256
+ previouslyReconciled : false ,
214
257
shouldAllowCreateEvent : true ,
215
258
shouldAllowDeleteEvent : true ,
216
259
shouldAllowGenericEvent : false ,
@@ -224,7 +267,7 @@ func TestBuildPredicateWithNoAutoReconcileButReconcileAnnotPresent(t *testing.T)
224
267
for _ , tc := range testCases {
225
268
t .Run (tc .name , func (t * testing.T ) {
226
269
t .Parallel ()
227
- updatedEtcd := updateEtcd (etcd , tc .etcdSpecChanged , tc .etcdStatusChanged , tc .lastOperationState , true )
270
+ updatedEtcd := updateEtcd (etcd , tc .etcdSpecChanged , tc .etcdStatusChanged , tc .previouslyReconciled , tc . lastOperationState , true )
228
271
g .Expect (predicate .Create (event.CreateEvent {Object : updatedEtcd })).To (Equal (tc .shouldAllowCreateEvent ))
229
272
g .Expect (predicate .Delete (event.DeleteEvent {Object : updatedEtcd })).To (Equal (tc .shouldAllowDeleteEvent ))
230
273
g .Expect (predicate .Generic (event.GenericEvent {Object : updatedEtcd })).To (Equal (tc .shouldAllowGenericEvent ))
@@ -256,6 +299,7 @@ func TestBuildPredicateWithAutoReconcileAndReconcileAnnotSet(t *testing.T) {
256
299
name : "only status has changed and previous reconciliation is completed" ,
257
300
etcdStatusChanged : true ,
258
301
lastOperationState : ptr .To (druidv1alpha1 .LastOperationStateSucceeded ),
302
+ previouslyReconciled : true ,
259
303
shouldAllowCreateEvent : true ,
260
304
shouldAllowDeleteEvent : true ,
261
305
shouldAllowGenericEvent : false ,
@@ -265,6 +309,7 @@ func TestBuildPredicateWithAutoReconcileAndReconcileAnnotSet(t *testing.T) {
265
309
name : "both spec and status have changed" ,
266
310
etcdSpecChanged : true ,
267
311
etcdStatusChanged : true ,
312
+ previouslyReconciled : true ,
268
313
shouldAllowCreateEvent : true ,
269
314
shouldAllowDeleteEvent : true ,
270
315
shouldAllowGenericEvent : false ,
@@ -273,6 +318,7 @@ func TestBuildPredicateWithAutoReconcileAndReconcileAnnotSet(t *testing.T) {
273
318
{
274
319
name : "neither spec nor status has changed and previous reconciliation is in error" ,
275
320
lastOperationState : ptr .To (druidv1alpha1 .LastOperationStateError ),
321
+ previouslyReconciled : true ,
276
322
shouldAllowCreateEvent : true ,
277
323
shouldAllowDeleteEvent : true ,
278
324
shouldAllowGenericEvent : false ,
@@ -289,6 +335,16 @@ func TestBuildPredicateWithAutoReconcileAndReconcileAnnotSet(t *testing.T) {
289
335
{
290
336
name : "neither spec nor status has changed and previous reconciliation is completed" ,
291
337
lastOperationState : ptr .To (druidv1alpha1 .LastOperationStateSucceeded ),
338
+ previouslyReconciled : true ,
339
+ shouldAllowCreateEvent : true ,
340
+ shouldAllowDeleteEvent : true ,
341
+ shouldAllowGenericEvent : false ,
342
+ shouldAllowUpdateEvent : true ,
343
+ },
344
+ {
345
+ // This case is described in https://github.com/gardener/etcd-druid/issues/898
346
+ name : "for an existing Etcd resource, neither spec nor status has changed and it has never been reconciled before" ,
347
+ previouslyReconciled : false ,
292
348
shouldAllowCreateEvent : true ,
293
349
shouldAllowDeleteEvent : true ,
294
350
shouldAllowGenericEvent : false ,
@@ -302,7 +358,7 @@ func TestBuildPredicateWithAutoReconcileAndReconcileAnnotSet(t *testing.T) {
302
358
for _ , tc := range testCases {
303
359
t .Run (tc .name , func (t * testing.T ) {
304
360
t .Parallel ()
305
- updatedEtcd := updateEtcd (etcd , tc .etcdSpecChanged , tc .etcdStatusChanged , tc .lastOperationState , true )
361
+ updatedEtcd := updateEtcd (etcd , tc .etcdSpecChanged , tc .etcdStatusChanged , tc .previouslyReconciled , tc . lastOperationState , true )
306
362
g .Expect (predicate .Create (event.CreateEvent {Object : updatedEtcd })).To (Equal (tc .shouldAllowCreateEvent ))
307
363
g .Expect (predicate .Delete (event.DeleteEvent {Object : updatedEtcd })).To (Equal (tc .shouldAllowDeleteEvent ))
308
364
g .Expect (predicate .Generic (event.GenericEvent {Object : updatedEtcd })).To (Equal (tc .shouldAllowGenericEvent ))
@@ -314,7 +370,7 @@ func TestBuildPredicateWithAutoReconcileAndReconcileAnnotSet(t *testing.T) {
314
370
func createEtcd () * druidv1alpha1.Etcd {
315
371
etcd := testutils .EtcdBuilderWithDefaults (testutils .TestEtcdName , testutils .TestNamespace ).WithReplicas (3 ).Build ()
316
372
etcd .Status = druidv1alpha1.EtcdStatus {
317
- ObservedGeneration : ptr. To [ int64 ]( 0 ) ,
373
+ ObservedGeneration : nil ,
318
374
Etcd : & druidv1alpha1.CrossVersionObjectReference {
319
375
Kind : "StatefulSet" ,
320
376
Name : testutils .TestEtcdName ,
@@ -328,7 +384,7 @@ func createEtcd() *druidv1alpha1.Etcd {
328
384
return etcd
329
385
}
330
386
331
- func updateEtcd (originalEtcd * druidv1alpha1.Etcd , specChanged , statusChanged bool , lastOpState * druidv1alpha1.LastOperationState , reconcileAnnotPresent bool ) * druidv1alpha1.Etcd {
387
+ func updateEtcd (originalEtcd * druidv1alpha1.Etcd , specChanged , statusChanged bool , previouslyReconciled bool , lastOpState * druidv1alpha1.LastOperationState , reconcileAnnotPresent bool ) * druidv1alpha1.Etcd {
332
388
newEtcd := originalEtcd .DeepCopy ()
333
389
annotations := make (map [string ]string )
334
390
if reconcileAnnotPresent {
@@ -345,6 +401,9 @@ func updateEtcd(originalEtcd *druidv1alpha1.Etcd, specChanged, statusChanged boo
345
401
newEtcd .Status .ReadyReplicas = 2
346
402
newEtcd .Status .Ready = ptr .To (false )
347
403
}
404
+ if previouslyReconciled && originalEtcd .Status .ObservedGeneration == nil {
405
+ newEtcd .Status .ObservedGeneration = ptr.To [int64 ](1 )
406
+ }
348
407
if lastOpState != nil {
349
408
newEtcd .Status .LastOperation = & druidv1alpha1.LastOperation {
350
409
Type : druidv1alpha1 .LastOperationTypeReconcile ,
0 commit comments