@@ -24,7 +24,9 @@ import (
2424 corev1 "k8s.io/api/core/v1"
2525 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2626 operatorv1 "sigs.k8s.io/cluster-api-operator/api/v1alpha2"
27+ clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
2728 "sigs.k8s.io/cluster-api/util/conditions"
29+ "sigs.k8s.io/cluster-api/util/patch"
2830 "sigs.k8s.io/controller-runtime/pkg/client"
2931)
3032
@@ -45,8 +47,8 @@ func TestConfigMapChangesAreAppliedToTheProvider(t *testing.T) {
4547 // Create ConfigMap with initial content
4648 configMap := & corev1.ConfigMap {
4749 ObjectMeta : metav1.ObjectMeta {
48- GenerateName : "edge-provider-" ,
49- Namespace : ns .Name ,
50+ Name : testCurrentVersion ,
51+ Namespace : ns .Name ,
5052 Labels : map [string ]string {
5153 "provider-components" : "edge" ,
5254 },
@@ -86,6 +88,12 @@ func TestConfigMapChangesAreAppliedToTheProvider(t *testing.T) {
8688
8789 t .Log ("CoreProvider is installed" )
8890
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+
8997 // Create InfrastructureProvider that uses the ConfigMap
9098 provider := & operatorv1.InfrastructureProvider {
9199 ObjectMeta : metav1.ObjectMeta {
@@ -121,6 +129,15 @@ func TestConfigMapChangesAreAppliedToTheProvider(t *testing.T) {
121129
122130 t .Log ("Provider is installed" )
123131
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+
124141 // Get the initial hash annotation
125142 g .Expect (env .Get (ctx , client .ObjectKeyFromObject (provider ), provider )).To (Succeed ())
126143 initialHash := provider .GetAnnotations ()[appliedSpecHashAnnotation ]
@@ -148,40 +165,20 @@ func TestConfigMapChangesAreAppliedToTheProvider(t *testing.T) {
148165 t .Log ("Provider reconciled with new hash" )
149166}
150167
151- func TestConfigMapChangesWithMultipleProviders (t * testing.T ) {
168+ func TestConfigMapChangesWithNonMatchingSelector (t * testing.T ) {
152169 g := NewWithT (t )
153170 objs := []client.Object {}
154171
155172 defer func () {
156173 g .Expect (env .CleanupAndWait (ctx , objs ... )).To (Succeed ())
157174 }()
158175
159- ns , err := env .CreateNamespace (ctx , "multiple-providers -namespace" )
176+ ns , err := env .CreateNamespace (ctx , "non-matching-selector -namespace" )
160177 g .Expect (err ).ToNot (HaveOccurred ())
161178 g .Expect (ns .Name ).NotTo (BeEmpty ())
162179
163180 t .Log ("Ensure namespace exists" , ns .Name )
164181
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-
185182 // Create CoreProvider first (required for InfrastructureProvider)
186183 coreProvider := & operatorv1.CoreProvider {
187184 ObjectMeta : metav1.ObjectMeta {
@@ -207,93 +204,11 @@ func TestConfigMapChangesWithMultipleProviders(t *testing.T) {
207204
208205 t .Log ("CoreProvider is installed" )
209206
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 )
293209 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 ())
297212
298213 // Create ConfigMap that won't match any provider selector
299214 configMap := & corev1.ConfigMap {
@@ -362,6 +277,15 @@ func TestConfigMapChangesWithNonMatchingSelector(t *testing.T) {
362277 return conditions .IsTrue (provider , operatorv1 .ProviderInstalledCondition )
363278 }, timeout ).Should (BeTrue ())
364279
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+
365289 // Get initial hash
366290 g .Expect (env .Get (ctx , client .ObjectKeyFromObject (provider ), provider )).To (Succeed ())
367291 initialHash := provider .GetAnnotations ()[appliedSpecHashAnnotation ]
@@ -405,3 +329,119 @@ func TestConfigMapChangesWithNonMatchingSelector(t *testing.T) {
405329
406330 t .Log ("Provider reconciled with new hash after matching ConfigMap update" )
407331}
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