@@ -2,6 +2,7 @@ package status_test
2
2
3
3
import (
4
4
"context"
5
+ "sync"
5
6
"time"
6
7
7
8
"github.com/awslabs/operatorpkg/status"
@@ -25,11 +26,11 @@ var _ = Describe("Controller", func() {
25
26
var ctx context.Context
26
27
var recorder * record.FakeRecorder
27
28
var controller * status.Controller [* TestObject ]
28
- var client client.Client
29
+ var kubeClient client.Client
29
30
BeforeEach (func () {
30
31
recorder = record .NewFakeRecorder (10 )
31
- client = fake .NewClientBuilder ().WithScheme (scheme .Scheme ).Build ()
32
- controller = status .NewController [* TestObject ](client , recorder )
32
+ kubeClient = fake .NewClientBuilder ().WithScheme (scheme .Scheme ).Build ()
33
+ controller = status .NewController [* TestObject ](kubeClient , recorder )
33
34
ctx = log .IntoContext (context .Background (), ginkgo .GinkgoLogr )
34
35
})
35
36
@@ -38,7 +39,7 @@ var _ = Describe("Controller", func() {
38
39
testObject .StatusConditions () // initialize conditions
39
40
40
41
// conditions not set
41
- ExpectApplied (ctx , client , testObject )
42
+ ExpectApplied (ctx , kubeClient , testObject )
42
43
ExpectReconciled (ctx , controller , testObject )
43
44
44
45
// Ready Condition
@@ -73,9 +74,9 @@ var _ = Describe("Controller", func() {
73
74
// Transition Foo
74
75
time .Sleep (time .Second * 1 )
75
76
testObject .StatusConditions ().SetTrue (ConditionTypeFoo )
76
- ExpectApplied (ctx , client , testObject )
77
+ ExpectApplied (ctx , kubeClient , testObject )
77
78
ExpectReconciled (ctx , controller , testObject )
78
- ExpectStatusConditions (ctx , client , FastTimeout , testObject , status.Condition {Type : ConditionTypeFoo , Status : metav1 .ConditionTrue })
79
+ ExpectStatusConditions (ctx , kubeClient , FastTimeout , testObject , status.Condition {Type : ConditionTypeFoo , Status : metav1 .ConditionTrue })
79
80
80
81
// Ready Condition
81
82
Expect (GetMetric ("operator_status_condition_count" , conditionLabels (status .ConditionReady , metav1 .ConditionTrue ))).To (BeNil ())
@@ -125,9 +126,9 @@ var _ = Describe("Controller", func() {
125
126
126
127
// Transition Bar, root condition should also flip
127
128
testObject .StatusConditions ().SetTrueWithReason (ConditionTypeBar , "reason" , "message" )
128
- ExpectApplied (ctx , client , testObject )
129
+ ExpectApplied (ctx , kubeClient , testObject )
129
130
ExpectReconciled (ctx , controller , testObject )
130
- ExpectStatusConditions (ctx , client , FastTimeout , testObject , status.Condition {Type : ConditionTypeBar , Status : metav1 .ConditionTrue , Reason : "reason" , Message : "message" })
131
+ ExpectStatusConditions (ctx , kubeClient , FastTimeout , testObject , status.Condition {Type : ConditionTypeBar , Status : metav1 .ConditionTrue , Reason : "reason" , Message : "message" })
131
132
132
133
// Ready Condition
133
134
Expect (GetMetric ("operator_status_condition_count" , conditionLabels (status .ConditionReady , metav1 .ConditionTrue )).GetGauge ().GetValue ()).To (BeEquivalentTo (1 ))
@@ -201,7 +202,7 @@ var _ = Describe("Controller", func() {
201
202
Expect (recorder .Events ).To (Receive (Equal ("Normal Ready Status condition transitioned, Type: Ready, Status: Unknown -> True, Reason: Ready" )))
202
203
203
204
// Delete the object, state should clear
204
- ExpectDeleted (ctx , client , testObject )
205
+ ExpectDeleted (ctx , kubeClient , testObject )
205
206
ExpectReconciled (ctx , controller , testObject )
206
207
207
208
// Ready Condition
@@ -233,15 +234,15 @@ var _ = Describe("Controller", func() {
233
234
testObject .StatusConditions () // initialize conditions
234
235
235
236
// conditions not set
236
- ExpectApplied (ctx , client , testObject )
237
+ ExpectApplied (ctx , kubeClient , testObject )
237
238
ExpectReconciled (ctx , controller , testObject )
238
239
239
- // set the bar condition and transition it to true
240
+ // set the baz condition and transition it to true
240
241
testObject .StatusConditions ().SetTrue (ConditionTypeBaz )
241
242
242
- ExpectApplied (ctx , client , testObject )
243
+ ExpectApplied (ctx , kubeClient , testObject )
243
244
ExpectReconciled (ctx , controller , testObject )
244
- ExpectStatusConditions (ctx , client , FastTimeout , testObject , status.Condition {Type : ConditionTypeBaz , Status : metav1 .ConditionTrue , Reason : ConditionTypeBaz , Message : "" })
245
+ ExpectStatusConditions (ctx , kubeClient , FastTimeout , testObject , status.Condition {Type : ConditionTypeBaz , Status : metav1 .ConditionTrue , Reason : ConditionTypeBaz , Message : "" })
245
246
246
247
Expect (GetMetric ("operator_status_condition_transitions_total" , conditionLabels (ConditionTypeBaz , metav1 .ConditionTrue )).GetCounter ().GetValue ()).To (BeEquivalentTo (1 ))
247
248
Expect (GetMetric ("operator_status_condition_transitions_total" , conditionLabels (ConditionTypeBaz , metav1 .ConditionFalse ))).To (BeNil ())
@@ -250,9 +251,9 @@ var _ = Describe("Controller", func() {
250
251
// set the bar condition and transition it to false
251
252
testObject .StatusConditions ().SetFalse (ConditionTypeBaz , "reason" , "message" )
252
253
253
- ExpectApplied (ctx , client , testObject )
254
+ ExpectApplied (ctx , kubeClient , testObject )
254
255
ExpectReconciled (ctx , controller , testObject )
255
- ExpectStatusConditions (ctx , client , FastTimeout , testObject , status.Condition {Type : ConditionTypeBaz , Status : metav1 .ConditionFalse , Reason : "reason" , Message : "message" })
256
+ ExpectStatusConditions (ctx , kubeClient , FastTimeout , testObject , status.Condition {Type : ConditionTypeBaz , Status : metav1 .ConditionFalse , Reason : "reason" , Message : "message" })
256
257
257
258
Expect (GetMetric ("operator_status_condition_transitions_total" , conditionLabels (ConditionTypeBaz , metav1 .ConditionTrue )).GetCounter ().GetValue ()).To (BeEquivalentTo (1 ))
258
259
Expect (GetMetric ("operator_status_condition_transitions_total" , conditionLabels (ConditionTypeBaz , metav1 .ConditionFalse )).GetCounter ().GetValue ()).To (BeEquivalentTo (1 ))
@@ -261,13 +262,52 @@ var _ = Describe("Controller", func() {
261
262
// clear the condition and don't expect the metrics to change
262
263
_ = testObject .StatusConditions ().Clear (ConditionTypeBaz )
263
264
264
- ExpectApplied (ctx , client , testObject )
265
+ ExpectApplied (ctx , kubeClient , testObject )
265
266
ExpectReconciled (ctx , controller , testObject )
266
267
267
268
Expect (GetMetric ("operator_status_condition_transitions_total" , conditionLabels (ConditionTypeBaz , metav1 .ConditionTrue )).GetCounter ().GetValue ()).To (BeEquivalentTo (1 ))
268
269
Expect (GetMetric ("operator_status_condition_transitions_total" , conditionLabels (ConditionTypeBaz , metav1 .ConditionFalse )).GetCounter ().GetValue ()).To (BeEquivalentTo (1 ))
269
270
Expect (GetMetric ("operator_status_condition_transitions_total" , conditionLabels (ConditionTypeBaz , metav1 .ConditionUnknown ))).To (BeNil ())
270
271
})
272
+ It ("should not race when reconciling status conditions simultaneously" , func () {
273
+ var objs []* TestObject
274
+ for range 100 {
275
+ testObject := test .Object (& TestObject {})
276
+ testObject .StatusConditions () // initialize conditions
277
+ // conditions not set
278
+ ExpectApplied (ctx , kubeClient , testObject )
279
+ objs = append (objs , testObject )
280
+ }
281
+
282
+ // Run 100 object reconciles at once to attempt to trigger a data raceg
283
+ var wg sync.WaitGroup
284
+ for _ , obj := range objs {
285
+ wg .Add (1 )
286
+ go func () {
287
+ defer wg .Done ()
288
+ defer GinkgoRecover ()
289
+
290
+ ExpectReconciled (ctx , controller , obj )
291
+ }()
292
+ }
293
+
294
+ for _ , obj := range objs {
295
+ // set the baz condition and transition it to true
296
+ obj .StatusConditions ().SetTrue (ConditionTypeBaz )
297
+ ExpectApplied (ctx , kubeClient , obj )
298
+ }
299
+
300
+ // Run 100 object reconciles at once to attempt to trigger a data race
301
+ for _ , obj := range objs {
302
+ wg .Add (1 )
303
+ go func () {
304
+ defer wg .Done ()
305
+ defer GinkgoRecover ()
306
+
307
+ ExpectReconciled (ctx , controller , obj )
308
+ }()
309
+ }
310
+ })
271
311
})
272
312
273
313
// GetMetric attempts to find a metric given name and labels
0 commit comments