@@ -31,6 +31,7 @@ const (
31
31
cassandraUserSecret = "medusa-secret"
32
32
k8ssandraClusterName = "test"
33
33
medusaConfigName = "medusa-config"
34
+ medusaBucketSecretName = "medusa-bucket-secret"
34
35
prefixFromMedusaConfig = "prefix-from-medusa-config"
35
36
prefixFromClusterSpec = "prefix-from-cluster-spec"
36
37
)
@@ -53,10 +54,10 @@ func dcTemplate(dcName string, dataPlaneContext string) api.CassandraDatacenterT
53
54
}
54
55
}
55
56
56
- func MedusaConfig (namespace string ) * medusaapi.MedusaConfiguration {
57
+ func MedusaConfig (name , namespace string ) * medusaapi.MedusaConfiguration {
57
58
return & medusaapi.MedusaConfiguration {
58
59
ObjectMeta : metav1.ObjectMeta {
59
- Name : medusaConfigName ,
60
+ Name : name ,
60
61
Namespace : namespace ,
61
62
},
62
63
Spec : medusaapi.MedusaConfigurationSpec {
@@ -71,21 +72,22 @@ func medusaTemplateWithoutConfigRef() *medusaapi.MedusaClusterTemplate {
71
72
return medusaTemplate (nil )
72
73
}
73
74
74
- func medusaTemplateWithConfigRef (configRefName string ) * medusaapi.MedusaClusterTemplate {
75
+ func medusaTemplateWithConfigRef (configRefName , namespace string ) * medusaapi.MedusaClusterTemplate {
75
76
configRef := & corev1.ObjectReference {
76
- Name : configRefName ,
77
+ Name : configRefName ,
78
+ Namespace : namespace ,
77
79
}
78
80
return medusaTemplate (configRef )
79
81
}
80
82
81
- func medusaTemplateWithConfigRefWithoutPrefix (configRefName string ) * medusaapi.MedusaClusterTemplate {
82
- template := medusaTemplateWithConfigRef (configRefName )
83
+ func medusaTemplateWithConfigRefWithoutPrefix (configRefName , namespace string ) * medusaapi.MedusaClusterTemplate {
84
+ template := medusaTemplateWithConfigRef (configRefName , namespace )
83
85
template .StorageProperties .Prefix = ""
84
86
return template
85
87
}
86
88
87
- func medusaTemplateWithConfigRefWithPrefix (configRefName string , prefix string ) * medusaapi.MedusaClusterTemplate {
88
- template := medusaTemplateWithConfigRef (configRefName )
89
+ func medusaTemplateWithConfigRefWithPrefix (configRefName , namespace , prefix string ) * medusaapi.MedusaClusterTemplate {
90
+ template := medusaTemplateWithConfigRef (configRefName , namespace )
89
91
template .StorageProperties .Prefix = prefix
90
92
return template
91
93
}
@@ -440,11 +442,28 @@ func reconcileMedusaStandaloneDeployment(ctx context.Context, t *testing.T, f *f
440
442
func createSingleDcClusterWithMedusaConfigRef (t * testing.T , ctx context.Context , f * framework.Framework , namespace string ) {
441
443
require := require .New (t )
442
444
445
+ t .Log ("Creating Medusa Bucket secret" )
446
+ medusaSecret := & corev1.Secret {
447
+ ObjectMeta : metav1.ObjectMeta {
448
+ Name : medusaBucketSecretName ,
449
+ Namespace : namespace ,
450
+ },
451
+ StringData : map [string ]string {
452
+ "credentials" : "some-credentials" ,
453
+ },
454
+ }
455
+ // create the secret in the control plane
456
+ err := f .Create (ctx , controlPlaneContextKey (f , medusaSecret , f .ControlPlaneContext ), medusaSecret )
457
+ require .NoError (err , fmt .Sprintf ("failed to create secret in control plane %s" , f .ControlPlaneContext ))
458
+
443
459
t .Log ("Creating Medusa Configuration object" )
444
- medusaConfigKey := framework.ClusterKey {NamespacedName : types.NamespacedName {Namespace : namespace , Name : medusaConfigName }, K8sContext : f .DataPlaneContexts [0 ]}
445
- err := f .Create (ctx , medusaConfigKey , MedusaConfig (namespace ))
460
+ medusaConfig := MedusaConfig (medusaConfigName , namespace )
461
+ medusaConfig .Spec .StorageProperties .StorageSecretRef = corev1.LocalObjectReference {Name : medusaBucketSecretName }
462
+ medusaConfigKey := controlPlaneContextKey (f , medusaConfig , f .ControlPlaneContext )
463
+ err = f .Create (ctx , medusaConfigKey , medusaConfig )
464
+
446
465
require .NoError (err , "failed to create Medusa Configuration" )
447
- require .Eventually (f .MedusaConfigExists (ctx , f .DataPlaneContexts [ 0 ] , medusaConfigKey ), timeout , interval )
466
+ require .Eventually (f .MedusaConfigExists (ctx , f .ControlPlaneContext , medusaConfigKey ), timeout , interval )
448
467
449
468
kc := & api.K8ssandraCluster {
450
469
ObjectMeta : metav1.ObjectMeta {
@@ -457,7 +476,7 @@ func createSingleDcClusterWithMedusaConfigRef(t *testing.T, ctx context.Context,
457
476
dcTemplate ("dc1" , f .DataPlaneContexts [0 ]),
458
477
},
459
478
},
460
- Medusa : medusaTemplateWithConfigRefWithPrefix (medusaConfigName , prefixFromClusterSpec ),
479
+ Medusa : medusaTemplateWithConfigRefWithPrefix (medusaConfigName , namespace , prefixFromClusterSpec ),
461
480
},
462
481
}
463
482
require .NotNil (kc .Spec .Medusa .MedusaConfigurationRef )
@@ -500,7 +519,7 @@ func creatingSingleDcClusterWithoutPrefixInClusterSpecFails(t *testing.T, ctx co
500
519
dcTemplate ("dc1" , f .DataPlaneContexts [0 ]),
501
520
},
502
521
},
503
- Medusa : medusaTemplateWithConfigRefWithoutPrefix (medusaConfigName ),
522
+ Medusa : medusaTemplateWithConfigRefWithoutPrefix (medusaConfigName , namespace ),
504
523
},
505
524
}
506
525
require .NotNil (kcFirstAttempt .Spec .Medusa .MedusaConfigurationRef )
@@ -520,7 +539,7 @@ func creatingSingleDcClusterWithoutPrefixInClusterSpecFails(t *testing.T, ctx co
520
539
// create the MedusaConfiguration object
521
540
t .Log ("Creating Medusa Configuration object" )
522
541
medusaConfigKey := framework.ClusterKey {NamespacedName : types.NamespacedName {Namespace : namespace , Name : medusaConfigName }, K8sContext : f .DataPlaneContexts [0 ]}
523
- err = f .Create (ctx , medusaConfigKey , MedusaConfig (namespace ))
542
+ err = f .Create (ctx , medusaConfigKey , MedusaConfig (medusaConfigName , namespace ))
524
543
require .NoError (err , "failed to create Medusa Configuration" )
525
544
require .Eventually (f .MedusaConfigExists (ctx , f .DataPlaneContexts [0 ], medusaConfigKey ), timeout , interval )
526
545
@@ -538,3 +557,127 @@ func creatingSingleDcClusterWithoutPrefixInClusterSpecFails(t *testing.T, ctx co
538
557
// verify the cluster still doesn't get created
539
558
require .Never (f .DatacenterExists (ctx , dc1Key ), timeout , interval )
540
559
}
560
+
561
+ func controlPlaneContextKey (f * framework.Framework , object metav1.Object , contextName string ) framework.ClusterKey {
562
+ return framework.ClusterKey {NamespacedName : utils .GetKey (object ), K8sContext : contextName }
563
+ }
564
+
565
+ func dataPlaneContextKey (f * framework.Framework , object metav1.Object , dataPlaneContextIndex int ) framework.ClusterKey {
566
+ return framework.ClusterKey {NamespacedName : utils .GetKey (object ), K8sContext : f .DataPlaneContexts [dataPlaneContextIndex ]}
567
+ }
568
+
569
+ func createMultiDcClusterWithReplicatedSecrets (t * testing.T , ctx context.Context , f * framework.Framework , namespace string ) {
570
+ require := require .New (t )
571
+
572
+ clusterName := "test-cluster"
573
+ originalConfigName := "test-config"
574
+ originalSecretName := fmt .Sprintf ("%s-bucket-key" , originalConfigName )
575
+ clusterSecretName := fmt .Sprintf ("%s-%s" , clusterName , originalSecretName )
576
+
577
+ // create a storage secret, then a MedusaConfiguration that points to it
578
+ // the ReplicatedSecrets controller is not loaded in env tests, so we "mock" it by replicating the secrets manually
579
+ medusaSecret := & corev1.Secret {
580
+ ObjectMeta : metav1.ObjectMeta {
581
+ Name : originalSecretName ,
582
+ Namespace : namespace ,
583
+ },
584
+ StringData : map [string ]string {
585
+ "credentials" : "some-credentials" ,
586
+ },
587
+ }
588
+ // create the secret in the control plane
589
+ cpMedusaSecret := medusaSecret .DeepCopy ()
590
+ err := f .Create (ctx , controlPlaneContextKey (f , cpMedusaSecret , f .ControlPlaneContext ), cpMedusaSecret )
591
+ require .NoError (err , fmt .Sprintf ("failed to create secret in control plane %s" , f .ControlPlaneContext ))
592
+ //create the secret in the data planes
593
+ for i , n := range f .DataPlaneContexts {
594
+ dpMedusaSecret := medusaSecret .DeepCopy ()
595
+ dpMedusaSecret .Name = clusterSecretName
596
+ err := f .Create (ctx , dataPlaneContextKey (f , dpMedusaSecret , i ), dpMedusaSecret )
597
+ require .NoError (err , fmt .Sprintf ("failed to create secret in context %d (%s)" , i , n ))
598
+ }
599
+
600
+ // create medusa config in the control plane only
601
+ medusaConfig := MedusaConfig (originalConfigName , namespace )
602
+ medusaConfig .Spec .StorageProperties .StorageSecretRef = corev1.LocalObjectReference {
603
+ Name : originalSecretName ,
604
+ }
605
+ cpMedusaConfig := medusaConfig .DeepCopy ()
606
+ err = f .Create (ctx , controlPlaneContextKey (f , cpMedusaConfig , f .ControlPlaneContext ), cpMedusaConfig )
607
+ require .NoError (err , fmt .Sprintf ("failed to create MedusaConfiguration in control plane %s" , f .ControlPlaneContext ))
608
+
609
+ // create a 2-dc K8ssandraCluster with Medusa featuring the reference to the above MedusaConfiguration
610
+ kc := & api.K8ssandraCluster {
611
+ ObjectMeta : metav1.ObjectMeta {
612
+ Name : clusterName ,
613
+ Namespace : namespace ,
614
+ },
615
+ Spec : api.K8ssandraClusterSpec {
616
+ Cassandra : & api.CassandraClusterTemplate {
617
+ Datacenters : []api.CassandraDatacenterTemplate {
618
+ dcTemplate ("dc1" , f .DataPlaneContexts [1 ]),
619
+ dcTemplate ("dc2" , f .DataPlaneContexts [2 ]),
620
+ },
621
+ },
622
+ Medusa : & medusaapi.MedusaClusterTemplate {
623
+ MedusaConfigurationRef : corev1.ObjectReference {
624
+ Namespace : namespace ,
625
+ Name : originalConfigName ,
626
+ },
627
+ StorageProperties : medusaapi.Storage {
628
+ Prefix : "some-prefix" ,
629
+ },
630
+ },
631
+ },
632
+ }
633
+ err = f .Client .Create (ctx , kc )
634
+ require .NoError (err , "failed to create K8ssandraCluster" )
635
+
636
+ verifySuperuserSecretCreated (ctx , t , f , kc )
637
+ verifyReplicatedSecretReconciled (ctx , t , f , kc )
638
+
639
+ reconcileMedusaStandaloneDeployment (ctx , t , f , kc , "dc1" , f .DataPlaneContexts [1 ])
640
+
641
+ // crate the first DC
642
+ dc1Key := framework.ClusterKey {NamespacedName : types.NamespacedName {Namespace : namespace , Name : "dc1" }, K8sContext : f .DataPlaneContexts [1 ]}
643
+ require .Eventually (f .DatacenterExists (ctx , dc1Key ), timeout , interval )
644
+
645
+ // mark the first DC as ready
646
+ t .Log ("update dc1 status to ready" )
647
+ err = f .SetDatacenterStatusReady (ctx , dc1Key )
648
+ require .NoError (err , "failed to update dc1 status to ready" )
649
+
650
+ // create the second DC
651
+ reconcileMedusaStandaloneDeployment (ctx , t , f , kc , "dc2" , f .DataPlaneContexts [2 ])
652
+ dc2Key := framework.ClusterKey {NamespacedName : types.NamespacedName {Namespace : namespace , Name : "dc2" }, K8sContext : f .DataPlaneContexts [2 ]}
653
+ require .Eventually (f .DatacenterExists (ctx , dc2Key ), timeout , interval )
654
+
655
+ // verify the copied secret is mounted in the pods
656
+ verifyBucketSecretMounted (ctx , t , f , dc1Key , clusterSecretName )
657
+ verifyBucketSecretMounted (ctx , t , f , dc2Key , clusterSecretName )
658
+
659
+ // verify the cluster's spec still contains the correct value
660
+ // which is empty because we used MedusaConfigRef
661
+ // merged it at runtime but never persisted to the k8ssandraCluster object
662
+ kc = & api.K8ssandraCluster {}
663
+ err = f .Client .Get (ctx , types.NamespacedName {Namespace : namespace , Name : clusterName }, kc )
664
+ require .NoError (err , "failed to get K8ssandraCluster" )
665
+ require .Equal ("" , kc .Spec .Medusa .StorageProperties .StorageSecretRef .Name )
666
+ }
667
+
668
+ func verifyBucketSecretMounted (ctx context.Context , t * testing.T , f * framework.Framework , dcKey framework.ClusterKey , clusterSecretName string ) {
669
+ require := require .New (t )
670
+
671
+ // fetch the DC spec
672
+ dc := & cassdcapi.CassandraDatacenter {}
673
+ err := f .Get (ctx , dcKey , dc )
674
+ require .NoError (err , fmt .Sprintf ("failed to get %s" , dcKey .Name ))
675
+
676
+ // fetch medusa container
677
+ containerIndex , found := cassandra .FindContainer (dc .Spec .PodTemplateSpec , "medusa" )
678
+ require .True (found , fmt .Sprintf ("%s doesn't have medusa container" , dc .Name ))
679
+ medusaContainer := dc .Spec .PodTemplateSpec .Spec .Containers [containerIndex ]
680
+
681
+ // check its mount
682
+ assert .True (t , f .ContainerHasVolumeMount (medusaContainer , clusterSecretName , "/etc/medusa-secrets" ), "Missing Volume Mount for Medusa bucket key" )
683
+ }
0 commit comments