@@ -2907,6 +2907,54 @@ var _ = Describe("OpenStackOperator Webhook", func() {
29072907 Expect (OSCtlplane .Labels ).Should (HaveKeyWithValue ("core.openstack.org/openstackcontrolplane" , "foo" ))
29082908 })
29092909
2910+ It ("Enforces queueType=Quorum for new resources" , func () {
2911+ spec := GetDefaultOpenStackControlPlaneSpec ()
2912+ spec ["tls" ] = GetTLSPublicSpec ()
2913+
2914+ DeferCleanup (
2915+ th .DeleteInstance ,
2916+ CreateOpenStackControlPlane (types.NamespacedName {Name : "test-new-quorum" , Namespace : namespace }, spec ),
2917+ )
2918+
2919+ OSCtlplane := GetOpenStackControlPlane (types.NamespacedName {Name : "test-new-quorum" , Namespace : namespace })
2920+ Expect (OSCtlplane .Spec .Rabbitmq .Templates ).Should (Not (BeNil ()))
2921+
2922+ // Verify that all templates get queueType=Quorum for new resources
2923+ for templateName , template := range * OSCtlplane .Spec .Rabbitmq .Templates {
2924+ Expect (template .QueueType ).Should (Equal ("Quorum" ), "RabbitMQ template %s should have queueType=Quorum" , templateName )
2925+ }
2926+ })
2927+
2928+ It ("Preserves existing queueType values on updates" , func () {
2929+ spec := GetDefaultOpenStackControlPlaneSpec ()
2930+ spec ["tls" ] = GetTLSPublicSpec ()
2931+
2932+ // Create a resource first (will get Quorum by default)
2933+ ctlplane := CreateOpenStackControlPlane (types.NamespacedName {Name : "test-preserve-existing" , Namespace : namespace }, spec )
2934+ DeferCleanup (th .DeleteInstance , ctlplane )
2935+
2936+ // Manually set it to Mirrored to simulate existing deployment
2937+ Eventually (func (g Gomega ) {
2938+ existingCtlplane := GetOpenStackControlPlane (types.NamespacedName {Name : "test-preserve-existing" , Namespace : namespace })
2939+ (* existingCtlplane .Spec .Rabbitmq .Templates )["rabbitmq" ] = rabbitmqv1.RabbitMqSpecCore {
2940+ QueueType : "Mirrored" , // Simulate existing value
2941+ }
2942+ g .Expect (k8sClient .Update (ctx , existingCtlplane )).Should (Succeed ())
2943+ }).Should (Succeed ())
2944+
2945+ // Verify it's preserved on subsequent updates
2946+ Eventually (func (g Gomega ) {
2947+ updatedCtlplane := GetOpenStackControlPlane (types.NamespacedName {Name : "test-preserve-existing" , Namespace : namespace })
2948+ updatedCtlplane .Spec .Secret = "updated-secret" // Trigger webhook
2949+ g .Expect (k8sClient .Update (ctx , updatedCtlplane )).Should (Succeed ())
2950+
2951+ // Should still be Mirrored after update
2952+ finalCtlplane := GetOpenStackControlPlane (types.NamespacedName {Name : "test-preserve-existing" , Namespace : namespace })
2953+ rabbitTemplate := (* finalCtlplane .Spec .Rabbitmq .Templates )["rabbitmq" ]
2954+ g .Expect (rabbitTemplate .QueueType ).Should (Equal ("Mirrored" ), "Existing queueType should be preserved" )
2955+ }).Should (Succeed ())
2956+ })
2957+
29102958 It ("calls placement validation webhook" , func () {
29112959 spec := GetDefaultOpenStackControlPlaneSpec ()
29122960 spec ["tls" ] = GetTLSPublicSpec ()
0 commit comments