@@ -136,7 +136,7 @@ var _ = Describe("Dataplane NodeSet RabbitMQ Finalizer Management", func() {
136136 }
137137
138138 // Helper to simulate deployment completion
139- SimulateDeploymentComplete := func (deploymentName types.NamespacedName , nodesetName string , ansibleLimit []string ) {
139+ SimulateDeploymentComplete := func (deploymentName types.NamespacedName , nodesetName string , _ []string ) {
140140 // First, complete the AnsibleEE jobs for each service
141141 deployment := GetDataplaneDeployment (deploymentName )
142142 nodeset := GetDataplaneNodeSet (types.NamespacedName {
@@ -273,7 +273,7 @@ var _ = Describe("Dataplane NodeSet RabbitMQ Finalizer Management", func() {
273273 })
274274
275275 AfterEach (func () {
276- k8sClient .Delete (ctx , novaUser )
276+ _ = k8sClient .Delete (ctx , novaUser )
277277 })
278278
279279 It ("Should add finalizer only after ALL nodes are updated in rolling deployment" , func () {
@@ -444,7 +444,7 @@ var _ = Describe("Dataplane NodeSet RabbitMQ Finalizer Management", func() {
444444 })
445445
446446 AfterEach (func () {
447- k8sClient .Delete (ctx , novaUser )
447+ _ = k8sClient .Delete (ctx , novaUser )
448448 })
449449
450450 It ("Should add independent finalizers from each nodeset to shared user" , func () {
@@ -618,8 +618,8 @@ var _ = Describe("Dataplane NodeSet RabbitMQ Finalizer Management", func() {
618618 })
619619
620620 AfterEach (func () {
621- k8sClient .Delete (ctx , oldUser )
622- k8sClient .Delete (ctx , newUser )
621+ _ = k8sClient .Delete (ctx , oldUser )
622+ _ = k8sClient .Delete (ctx , newUser )
623623 })
624624
625625 It ("Should switch finalizer from old user to new user after rotation completes" , func () {
@@ -792,9 +792,9 @@ var _ = Describe("Dataplane NodeSet RabbitMQ Finalizer Management", func() {
792792 })
793793
794794 AfterEach (func () {
795- k8sClient .Delete (ctx , novaUser )
796- k8sClient .Delete (ctx , neutronUser )
797- k8sClient .Delete (ctx , ironicUser )
795+ _ = k8sClient .Delete (ctx , novaUser )
796+ _ = k8sClient .Delete (ctx , neutronUser )
797+ _ = k8sClient .Delete (ctx , ironicUser )
798798 })
799799
800800 It ("Should manage service-specific finalizers independently across different clusters" , func () {
@@ -945,7 +945,7 @@ var _ = Describe("Dataplane NodeSet RabbitMQ Finalizer Management", func() {
945945 })
946946
947947 AfterEach (func () {
948- k8sClient .Delete (ctx , novaUser )
948+ _ = k8sClient .Delete (ctx , novaUser )
949949 })
950950
951951 It ("Should use deployment completion time not creation time" , func () {
@@ -1002,7 +1002,7 @@ var _ = Describe("Dataplane NodeSet RabbitMQ Finalizer Management", func() {
10021002 // Rotate secret (secret modified time = now, AFTER deployment creation)
10031003 UpdateNovaCellConfigSecret ("cell1" , "nova-user2" , "rabbitmq-cell1" )
10041004 newUser := CreateRabbitMQUser ("nova-user2" )
1005- DeferCleanup (func () { k8sClient .Delete (ctx , newUser ) })
1005+ DeferCleanup (func () { _ = k8sClient .Delete (ctx , newUser ) })
10061006
10071007 // Wait for secret to propagate
10081008 time .Sleep (time .Second * 2 )
@@ -1120,7 +1120,7 @@ var _ = Describe("Dataplane NodeSet RabbitMQ Finalizer Management", func() {
11201120 // Change secret (this triggers credential rotation)
11211121 UpdateNovaCellConfigSecret ("cell1" , "nova-user2" , "rabbitmq-cell1" )
11221122 newUser := CreateRabbitMQUser ("nova-user2" )
1123- DeferCleanup (func () { k8sClient .Delete (ctx , newUser ) })
1123+ DeferCleanup (func () { _ = k8sClient .Delete (ctx , newUser ) })
11241124
11251125 // Wait for secret to propagate
11261126 time .Sleep (time .Second * 2 )
@@ -1237,7 +1237,7 @@ var _ = Describe("Dataplane NodeSet RabbitMQ Finalizer Management", func() {
12371237 // Change secret to user2
12381238 UpdateNovaCellConfigSecret ("cell1" , "nova-user2" , "rabbitmq-cell1" )
12391239 user2 := CreateRabbitMQUser ("nova-user2" )
1240- DeferCleanup (func () { k8sClient .Delete (ctx , user2 ) })
1240+ DeferCleanup (func () { _ = k8sClient .Delete (ctx , user2 ) })
12411241
12421242 // Wait for secret to propagate
12431243 time .Sleep (time .Second * 2 )
@@ -1425,8 +1425,162 @@ var _ = Describe("Dataplane NodeSet RabbitMQ Finalizer Management", func() {
14251425 Eventually (func (g Gomega ) {
14261426 nodeset := GetDataplaneNodeSet (dataplaneNodeSetName )
14271427 // Should have exactly 2 nodes defined (not 4 with hostName and ansibleHost)
1428- g .Expect (len ( nodeset .Spec .Nodes )) .Should (Equal (2 ))
1428+ g .Expect (nodeset .Spec .Nodes ).Should (HaveLen (2 ))
14291429 }, th .Timeout , th .Interval ).Should (Succeed ())
14301430 })
14311431 })
1432+
1433+ Context ("When RabbitMQ users have cleanup-blocked finalizer" , func () {
1434+ var novaUser * rabbitmqv1.RabbitMQUser
1435+
1436+ BeforeEach (func () {
1437+ // Create Nova cell config secret
1438+ CreateNovaCellConfigSecret ("cell1" , "nova-user1" , "rabbitmq-cell1" )
1439+
1440+ // Create RabbitMQ user with cleanup-blocked finalizer
1441+ novaUser = CreateRabbitMQUser ("nova-user1" )
1442+
1443+ // Manually add the cleanup-blocked finalizer to simulate migration scenario
1444+ Eventually (func (g Gomega ) {
1445+ user := GetRabbitMQUser ("nova-user1" )
1446+ user .Finalizers = append (user .Finalizers , rabbitmqv1 .RabbitMQUserCleanupBlockedFinalizer )
1447+ g .Expect (k8sClient .Update (ctx , user )).Should (Succeed ())
1448+ }, timeout , interval ).Should (Succeed ())
1449+
1450+ // Setup infrastructure
1451+ netConfigName := types.NamespacedName {Namespace : namespace , Name : "dataplane-netconfig-cleanup" }
1452+ DeferCleanup (th .DeleteInstance , CreateNetConfig (netConfigName , DefaultNetConfigSpec ()))
1453+
1454+ dnsMasqName := types.NamespacedName {Namespace : namespace , Name : "dnsmasq-cleanup" }
1455+ DeferCleanup (th .DeleteInstance , CreateDNSMasq (dnsMasqName , DefaultDNSMasqSpec ()))
1456+ SimulateDNSMasqComplete (dnsMasqName )
1457+
1458+ CreateSSHSecret (types.NamespacedName {
1459+ Namespace : namespace ,
1460+ Name : "nova-migration-ssh-key" ,
1461+ })
1462+ })
1463+
1464+ AfterEach (func () {
1465+ _ = k8sClient .Delete (ctx , novaUser )
1466+ })
1467+
1468+ It ("Should remove cleanup-blocked finalizer during normal reconciliation" , func () {
1469+ // Verify cleanup-blocked finalizer is present initially
1470+ Eventually (func (g Gomega ) {
1471+ user := GetRabbitMQUser ("nova-user1" )
1472+ g .Expect (user .Finalizers ).Should (ContainElement (rabbitmqv1 .RabbitMQUserCleanupBlockedFinalizer ))
1473+ }, timeout , interval ).Should (Succeed ())
1474+
1475+ // Create nodeset with Nova service
1476+ nodeSetSpec := map [string ]interface {}{
1477+ "preProvisioned" : true ,
1478+ "services" : []string {"nova" },
1479+ "nodes" : map [string ]dataplanev1.NodeSection {
1480+ "compute-0" : {
1481+ HostName : "compute-0" ,
1482+ Ansible : dataplanev1.AnsibleOpts {
1483+ AnsibleHost : "192.168.122.100" ,
1484+ },
1485+ },
1486+ },
1487+ "nodeTemplate" : map [string ]interface {}{
1488+ "ansibleSSHPrivateKeySecret" : "dataplane-ansible-ssh-private-key-secret" ,
1489+ "managementNetwork" : "ctlplane" ,
1490+ "ansible" : map [string ]interface {}{
1491+ "ansibleUser" : "cloud-admin" ,
1492+ },
1493+ },
1494+ }
1495+ dataplaneNodeSetName := types.NamespacedName {
1496+ Name : "edpm-nodeset-cleanup-test" ,
1497+ Namespace : namespace ,
1498+ }
1499+ DeferCleanup (th .DeleteInstance , CreateDataplaneNodeSet (dataplaneNodeSetName , nodeSetSpec ))
1500+
1501+ CreateSSHSecret (types.NamespacedName {
1502+ Namespace : namespace ,
1503+ Name : "nova-migration-ssh-key" ,
1504+ })
1505+
1506+ SimulateIPSetComplete (types.NamespacedName {Namespace : namespace , Name : "compute-0" })
1507+ SimulateDNSDataComplete (dataplaneNodeSetName )
1508+
1509+ // Deploy the nodeset
1510+ deploymentName := types.NamespacedName {
1511+ Name : "cleanup-deployment" ,
1512+ Namespace : namespace ,
1513+ }
1514+ deploymentSpec := map [string ]interface {}{
1515+ "nodeSets" : []string {dataplaneNodeSetName .Name },
1516+ }
1517+ DeferCleanup (th .DeleteInstance , CreateDataplaneDeployment (deploymentName , deploymentSpec ))
1518+ SimulateDeploymentComplete (deploymentName , dataplaneNodeSetName .Name , []string {"compute-0" })
1519+
1520+ // Verify the cleanup-blocked finalizer is removed
1521+ Eventually (func (g Gomega ) {
1522+ user := GetRabbitMQUser ("nova-user1" )
1523+ g .Expect (user .Finalizers ).ShouldNot (ContainElement (rabbitmqv1 .RabbitMQUserCleanupBlockedFinalizer ),
1524+ "cleanup-blocked finalizer should be automatically removed during reconciliation" )
1525+ }, timeout , interval ).Should (Succeed ())
1526+
1527+ // Verify our nodeset finalizer is still added
1528+ Eventually (func (g Gomega ) {
1529+ user := GetRabbitMQUser ("nova-user1" )
1530+ hasNodesetFinalizer := false
1531+ for _ , f := range user .Finalizers {
1532+ if len (f ) > 11 && f [:11 ] == "nodeset.os/" {
1533+ hasNodesetFinalizer = true
1534+ break
1535+ }
1536+ }
1537+ g .Expect (hasNodesetFinalizer ).Should (BeTrue (),
1538+ "nodeset finalizer should still be present" )
1539+ }, timeout , interval ).Should (Succeed ())
1540+ })
1541+
1542+ It ("Should remove cleanup-blocked finalizer during nodeset deletion" , func () {
1543+ // Create a simple nodeset
1544+ nodeSetSpec := map [string ]interface {}{
1545+ "preProvisioned" : true ,
1546+ "services" : []string {"nova" },
1547+ "nodes" : map [string ]dataplanev1.NodeSection {
1548+ "compute-0" : {
1549+ HostName : "compute-0" ,
1550+ },
1551+ },
1552+ "nodeTemplate" : map [string ]interface {}{
1553+ "ansibleSSHPrivateKeySecret" : "dataplane-ansible-ssh-private-key-secret" ,
1554+ },
1555+ }
1556+ dataplaneNodeSetName := types.NamespacedName {
1557+ Name : "edpm-nodeset-deletion-cleanup" ,
1558+ Namespace : namespace ,
1559+ }
1560+ CreateDataplaneNodeSet (dataplaneNodeSetName , nodeSetSpec )
1561+
1562+ // Verify cleanup-blocked finalizer is present
1563+ Eventually (func (g Gomega ) {
1564+ user := GetRabbitMQUser ("nova-user1" )
1565+ g .Expect (user .Finalizers ).Should (ContainElement (rabbitmqv1 .RabbitMQUserCleanupBlockedFinalizer ))
1566+ }, timeout , interval ).Should (Succeed ())
1567+
1568+ // Delete the nodeset
1569+ nodeset := GetDataplaneNodeSet (dataplaneNodeSetName )
1570+ Expect (k8sClient .Delete (ctx , nodeset )).Should (Succeed ())
1571+
1572+ // Wait for nodeset to be deleted
1573+ Eventually (func (g Gomega ) {
1574+ err := k8sClient .Get (ctx , dataplaneNodeSetName , nodeset )
1575+ g .Expect (err ).Should (HaveOccurred ())
1576+ }, timeout , interval ).Should (Succeed ())
1577+
1578+ // Verify cleanup-blocked finalizer is removed from the user
1579+ Eventually (func (g Gomega ) {
1580+ user := GetRabbitMQUser ("nova-user1" )
1581+ g .Expect (user .Finalizers ).ShouldNot (ContainElement (rabbitmqv1 .RabbitMQUserCleanupBlockedFinalizer ),
1582+ "cleanup-blocked finalizer should be removed during nodeset deletion" )
1583+ }, timeout , interval ).Should (Succeed ())
1584+ })
1585+ })
14321586})
0 commit comments