@@ -24,7 +24,9 @@ import (
24
24
corev1 "k8s.io/api/core/v1"
25
25
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
26
26
operatorv1 "sigs.k8s.io/cluster-api-operator/api/v1alpha2"
27
+ clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
27
28
"sigs.k8s.io/cluster-api/util/conditions"
29
+ "sigs.k8s.io/cluster-api/util/patch"
28
30
"sigs.k8s.io/controller-runtime/pkg/client"
29
31
)
30
32
@@ -45,8 +47,8 @@ func TestConfigMapChangesAreAppliedToTheProvider(t *testing.T) {
45
47
// Create ConfigMap with initial content
46
48
configMap := & corev1.ConfigMap {
47
49
ObjectMeta : metav1.ObjectMeta {
48
- GenerateName : "edge-provider-" ,
49
- Namespace : ns .Name ,
50
+ Name : testCurrentVersion ,
51
+ Namespace : ns .Name ,
50
52
Labels : map [string ]string {
51
53
"provider-components" : "edge" ,
52
54
},
@@ -86,6 +88,12 @@ func TestConfigMapChangesAreAppliedToTheProvider(t *testing.T) {
86
88
87
89
t .Log ("CoreProvider is installed" )
88
90
91
+ // Manually set ReadyCondition as it's not set automatically in test env
92
+ patchHelper , err := patch .NewHelper (coreProvider , env )
93
+ g .Expect (err ).ToNot (HaveOccurred ())
94
+ conditions .MarkTrue (coreProvider , clusterv1 .ReadyCondition )
95
+ g .Expect (patchHelper .Patch (ctx , coreProvider )).To (Succeed ())
96
+
89
97
// Create InfrastructureProvider that uses the ConfigMap
90
98
provider := & operatorv1.InfrastructureProvider {
91
99
ObjectMeta : metav1.ObjectMeta {
@@ -121,6 +129,15 @@ func TestConfigMapChangesAreAppliedToTheProvider(t *testing.T) {
121
129
122
130
t .Log ("Provider is installed" )
123
131
132
+ // Wait for the provider to have a hash annotation (this happens after full reconciliation)
133
+ g .Eventually (func () bool {
134
+ if err := env .Get (ctx , client .ObjectKeyFromObject (provider ), provider ); err != nil {
135
+ return false
136
+ }
137
+ hash := provider .GetAnnotations ()[appliedSpecHashAnnotation ]
138
+ return hash != ""
139
+ }, timeout ).Should (BeTrue (), "Provider should have a hash annotation after reconciliation" )
140
+
124
141
// Get the initial hash annotation
125
142
g .Expect (env .Get (ctx , client .ObjectKeyFromObject (provider ), provider )).To (Succeed ())
126
143
initialHash := provider .GetAnnotations ()[appliedSpecHashAnnotation ]
@@ -148,40 +165,20 @@ func TestConfigMapChangesAreAppliedToTheProvider(t *testing.T) {
148
165
t .Log ("Provider reconciled with new hash" )
149
166
}
150
167
151
- func TestConfigMapChangesWithMultipleProviders (t * testing.T ) {
168
+ func TestConfigMapChangesWithNonMatchingSelector (t * testing.T ) {
152
169
g := NewWithT (t )
153
170
objs := []client.Object {}
154
171
155
172
defer func () {
156
173
g .Expect (env .CleanupAndWait (ctx , objs ... )).To (Succeed ())
157
174
}()
158
175
159
- ns , err := env .CreateNamespace (ctx , "multiple-providers -namespace" )
176
+ ns , err := env .CreateNamespace (ctx , "non-matching-selector -namespace" )
160
177
g .Expect (err ).ToNot (HaveOccurred ())
161
178
g .Expect (ns .Name ).NotTo (BeEmpty ())
162
179
163
180
t .Log ("Ensure namespace exists" , ns .Name )
164
181
165
- // Create ConfigMap with initial content
166
- configMap := & corev1.ConfigMap {
167
- ObjectMeta : metav1.ObjectMeta {
168
- GenerateName : "shared-configmap-" ,
169
- Namespace : ns .Name ,
170
- Labels : map [string ]string {
171
- "provider-components" : "shared" ,
172
- "environment" : "test" ,
173
- },
174
- },
175
- Data : map [string ]string {
176
- "metadata" : testMetadata ,
177
- "components" : testComponents ,
178
- },
179
- }
180
- g .Expect (env .CreateAndWait (ctx , configMap )).To (Succeed ())
181
- objs = append (objs , configMap )
182
-
183
- t .Log ("Created shared ConfigMap" )
184
-
185
182
// Create CoreProvider first (required for InfrastructureProvider)
186
183
coreProvider := & operatorv1.CoreProvider {
187
184
ObjectMeta : metav1.ObjectMeta {
@@ -207,93 +204,11 @@ func TestConfigMapChangesWithMultipleProviders(t *testing.T) {
207
204
208
205
t .Log ("CoreProvider is installed" )
209
206
210
- // Create multiple providers that use the same ConfigMap
211
- providers := []* operatorv1.InfrastructureProvider {}
212
- for i := 0 ; i < 2 ; i ++ {
213
- provider := & operatorv1.InfrastructureProvider {
214
- ObjectMeta : metav1.ObjectMeta {
215
- GenerateName : "provider-" ,
216
- Namespace : ns .Name ,
217
- },
218
- Spec : operatorv1.InfrastructureProviderSpec {
219
- ProviderSpec : operatorv1.ProviderSpec {
220
- Version : testCurrentVersion ,
221
- FetchConfig : & operatorv1.FetchConfiguration {
222
- Selector : & metav1.LabelSelector {
223
- MatchLabels : map [string ]string {
224
- "provider-components" : "shared" ,
225
- },
226
- },
227
- },
228
- },
229
- },
230
- }
231
- g .Expect (env .CreateAndWait (ctx , provider )).To (Succeed ())
232
- objs = append (objs , provider )
233
- providers = append (providers , provider )
234
- }
235
-
236
- t .Log ("Created multiple providers" )
237
-
238
- // Wait for all providers to be ready
239
- for _ , provider := range providers {
240
- g .Eventually (func () bool {
241
- if err := env .Get (ctx , client .ObjectKeyFromObject (provider ), provider ); err != nil {
242
- return false
243
- }
244
-
245
- return conditions .IsTrue (provider , operatorv1 .ProviderInstalledCondition )
246
- }, timeout ).Should (BeTrue ())
247
- }
248
-
249
- t .Log ("All providers are installed" )
250
-
251
- // Get initial hash annotations
252
- initialHashes := make (map [string ]string )
253
- for i , provider := range providers {
254
- g .Expect (env .Get (ctx , client .ObjectKeyFromObject (provider ), provider )).To (Succeed ())
255
- hash := provider .GetAnnotations ()[appliedSpecHashAnnotation ]
256
- g .Expect (hash ).ToNot (BeEmpty ())
257
- initialHashes [provider .GetName ()] = hash
258
- t .Logf ("Provider %d initial hash: %s" , i , hash )
259
- }
260
-
261
- // Update the ConfigMap content
262
- g .Expect (env .Get (ctx , client .ObjectKeyFromObject (configMap ), configMap )).To (Succeed ())
263
- configMap .Data ["components" ] = testComponents + "\n # Updated shared content"
264
- g .Expect (env .Update (ctx , configMap )).To (Succeed ())
265
-
266
- t .Log ("Shared ConfigMap updated" )
267
-
268
- // Wait for all providers to be reconciled with new hashes
269
- for i , provider := range providers {
270
- g .Eventually (func () bool {
271
- if err := env .Get (ctx , client .ObjectKeyFromObject (provider ), provider ); err != nil {
272
- return false
273
- }
274
-
275
- currentHash := provider .GetAnnotations ()[appliedSpecHashAnnotation ]
276
- initialHash := initialHashes [provider .GetName ()]
277
- return currentHash != "" && currentHash != initialHash
278
- }, 30 * time .Second ).Should (BeTrue ())
279
-
280
- t .Logf ("Provider %d reconciled with new hash" , i )
281
- }
282
- }
283
-
284
- func TestConfigMapChangesWithNonMatchingSelector (t * testing.T ) {
285
- g := NewWithT (t )
286
- objs := []client.Object {}
287
-
288
- defer func () {
289
- g .Expect (env .CleanupAndWait (ctx , objs ... )).To (Succeed ())
290
- }()
291
-
292
- ns , err := env .CreateNamespace (ctx , "non-matching-selector-namespace" )
207
+ // Manually set ReadyCondition as it's not set automatically in test env
208
+ patchHelper , err := patch .NewHelper (coreProvider , env )
293
209
g .Expect (err ).ToNot (HaveOccurred ())
294
- g .Expect (ns .Name ).NotTo (BeEmpty ())
295
-
296
- t .Log ("Ensure namespace exists" , ns .Name )
210
+ conditions .MarkTrue (coreProvider , clusterv1 .ReadyCondition )
211
+ g .Expect (patchHelper .Patch (ctx , coreProvider )).To (Succeed ())
297
212
298
213
// Create ConfigMap that won't match any provider selector
299
214
configMap := & corev1.ConfigMap {
@@ -362,6 +277,15 @@ func TestConfigMapChangesWithNonMatchingSelector(t *testing.T) {
362
277
return conditions .IsTrue (provider , operatorv1 .ProviderInstalledCondition )
363
278
}, timeout ).Should (BeTrue ())
364
279
280
+ // Wait for the provider to have a hash annotation (this happens after full reconciliation)
281
+ g .Eventually (func () bool {
282
+ if err := env .Get (ctx , client .ObjectKeyFromObject (provider ), provider ); err != nil {
283
+ return false
284
+ }
285
+ hash := provider .GetAnnotations ()[appliedSpecHashAnnotation ]
286
+ return hash != ""
287
+ }, timeout ).Should (BeTrue (), "Provider should have a hash annotation after reconciliation" )
288
+
365
289
// Get initial hash
366
290
g .Expect (env .Get (ctx , client .ObjectKeyFromObject (provider ), provider )).To (Succeed ())
367
291
initialHash := provider .GetAnnotations ()[appliedSpecHashAnnotation ]
@@ -405,3 +329,119 @@ func TestConfigMapChangesWithNonMatchingSelector(t *testing.T) {
405
329
406
330
t .Log ("Provider reconciled with new hash after matching ConfigMap update" )
407
331
}
332
+
333
+ func TestMultipleConfigMapsError (t * testing.T ) {
334
+ g := NewWithT (t )
335
+ objs := []client.Object {}
336
+
337
+ defer func () {
338
+ g .Expect (env .CleanupAndWait (ctx , objs ... )).To (Succeed ())
339
+ }()
340
+
341
+ ns , err := env .CreateNamespace (ctx , "multiple-configmaps-error-namespace" )
342
+ g .Expect (err ).ToNot (HaveOccurred ())
343
+ g .Expect (ns .Name ).NotTo (BeEmpty ())
344
+
345
+ t .Log ("Ensure namespace exists" , ns .Name )
346
+
347
+ // Create CoreProvider first (required for InfrastructureProvider)
348
+ coreProvider := & operatorv1.CoreProvider {
349
+ ObjectMeta : metav1.ObjectMeta {
350
+ Name : "cluster-api" ,
351
+ Namespace : ns .Name ,
352
+ },
353
+ Spec : operatorv1.CoreProviderSpec {
354
+ ProviderSpec : operatorv1.ProviderSpec {
355
+ Version : testCurrentVersion ,
356
+ },
357
+ },
358
+ }
359
+ g .Expect (env .CreateAndWait (ctx , coreProvider )).To (Succeed ())
360
+ objs = append (objs , coreProvider )
361
+
362
+ // Wait for CoreProvider to be installed
363
+ g .Eventually (func () bool {
364
+ if err := env .Get (ctx , client .ObjectKeyFromObject (coreProvider ), coreProvider ); err != nil {
365
+ return false
366
+ }
367
+ return conditions .IsTrue (coreProvider , operatorv1 .ProviderInstalledCondition )
368
+ }, timeout ).Should (BeTrue ())
369
+
370
+ t .Log ("CoreProvider is installed" )
371
+
372
+ // Manually set ReadyCondition as it's not set automatically in test env
373
+ patchHelper , err := patch .NewHelper (coreProvider , env )
374
+ g .Expect (err ).ToNot (HaveOccurred ())
375
+ conditions .MarkTrue (coreProvider , clusterv1 .ReadyCondition )
376
+ g .Expect (patchHelper .Patch (ctx , coreProvider )).To (Succeed ())
377
+
378
+ // Create multiple ConfigMaps with the same labels (this should cause an error)
379
+ configMap1 := & corev1.ConfigMap {
380
+ ObjectMeta : metav1.ObjectMeta {
381
+ Name : testCurrentVersion ,
382
+ Namespace : ns .Name ,
383
+ Labels : map [string ]string {
384
+ "provider-components" : "edge" ,
385
+ },
386
+ },
387
+ Data : map [string ]string {
388
+ "metadata" : testMetadata ,
389
+ "components" : testComponents ,
390
+ },
391
+ }
392
+ g .Expect (env .CreateAndWait (ctx , configMap1 )).To (Succeed ())
393
+ objs = append (objs , configMap1 )
394
+
395
+ configMap2 := & corev1.ConfigMap {
396
+ ObjectMeta : metav1.ObjectMeta {
397
+ Name : "v1.1.0" ,
398
+ Namespace : ns .Name ,
399
+ Labels : map [string ]string {
400
+ "provider-components" : "edge" ,
401
+ },
402
+ },
403
+ Data : map [string ]string {
404
+ "metadata" : testMetadata ,
405
+ "components" : testComponents + "\n # Different content" ,
406
+ },
407
+ }
408
+ g .Expect (env .CreateAndWait (ctx , configMap2 )).To (Succeed ())
409
+ objs = append (objs , configMap2 )
410
+
411
+ t .Log ("Created multiple ConfigMaps with same labels" )
412
+
413
+ // Create InfrastructureProvider that uses the ConfigMaps (should fail due to multiple matches)
414
+ provider := & operatorv1.InfrastructureProvider {
415
+ ObjectMeta : metav1.ObjectMeta {
416
+ GenerateName : "edge-provider-" ,
417
+ Namespace : ns .Name ,
418
+ },
419
+ Spec : operatorv1.InfrastructureProviderSpec {
420
+ ProviderSpec : operatorv1.ProviderSpec {
421
+ Version : testCurrentVersion ,
422
+ FetchConfig : & operatorv1.FetchConfiguration {
423
+ Selector : & metav1.LabelSelector {
424
+ MatchLabels : map [string ]string {
425
+ "provider-components" : "edge" ,
426
+ },
427
+ },
428
+ },
429
+ },
430
+ },
431
+ }
432
+ g .Expect (env .CreateAndWait (ctx , provider )).To (Succeed ())
433
+ objs = append (objs , provider )
434
+
435
+ t .Log ("Created provider with selector matching multiple ConfigMaps" )
436
+
437
+ // Provider should have error condition due to multiple ConfigMaps
438
+ g .Eventually (func () bool {
439
+ if err := env .Get (ctx , client .ObjectKeyFromObject (provider ), provider ); err != nil {
440
+ return false
441
+ }
442
+ return conditions .IsFalse (provider , operatorv1 .ProviderInstalledCondition ) &&
443
+ conditions .GetReason (provider , operatorv1 .ProviderInstalledCondition ) != ""
444
+ }, timeout ).Should (BeTrue ())
445
+
446
+ t .Log ("Provider correctly failed with multiple ConfigMaps error" )
447
+ }
0 commit comments