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