Skip to content

Commit 96f2ca9

Browse files
Merge pull request #1671 from rabi/fix_update
Don't ignore earlier completed deployments
2 parents b608ce3 + 951fd2e commit 96f2ca9

File tree

2 files changed

+51
-47
lines changed

2 files changed

+51
-47
lines changed

controllers/dataplane/openstackdataplanenodeset_controller.go

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,9 @@ func (r *OpenStackDataPlaneNodeSetReconciler) Reconcile(ctx context.Context, req
476476
}
477477

478478
func checkDeployment(ctx context.Context, helper *helper.Helper,
479-
instance *dataplanev1.OpenStackDataPlaneNodeSet) (isDeploymentReady bool, isDeploymentRunning bool, isDeploymentFailed bool, failedDeploymentName string, err error) {
479+
instance *dataplanev1.OpenStackDataPlaneNodeSet) (
480+
isNodeSetDeploymentReady bool, isNodeSetDeploymentRunning bool,
481+
isNodeSetDeploymentFailed bool, failedDeploymentName string, err error) {
480482

481483
// Get all completed deployments
482484
deployments := &dataplanev1.OpenStackDataPlaneDeploymentList{}
@@ -486,7 +488,7 @@ func checkDeployment(ctx context.Context, helper *helper.Helper,
486488
err = helper.GetClient().List(ctx, deployments, opts...)
487489
if err != nil {
488490
helper.GetLogger().Error(err, "Unable to retrieve OpenStackDataPlaneDeployment CRs %v")
489-
return isDeploymentReady, isDeploymentRunning, isDeploymentFailed, failedDeploymentName, err
491+
return isNodeSetDeploymentReady, isNodeSetDeploymentRunning, isNodeSetDeploymentFailed, failedDeploymentName, err
490492
}
491493

492494
// Collect deployments that target this nodeset (excluding deleted ones)
@@ -528,33 +530,41 @@ func checkDeployment(ctx context.Context, helper *helper.Helper,
528530
// Apply filtering for overall nodeset deployment state logic
529531
isLatestDeployment := latestRelevantDeployment != nil && deployment.Name == latestRelevantDeployment.Name
530532
deploymentCondition := deploymentConditions.Get(dataplanev1.NodeSetDeploymentReadyCondition)
531-
isRunningDeployment := deploymentConditions.IsFalse(dataplanev1.NodeSetDeploymentReadyCondition) && !condition.IsError(deploymentCondition)
532533

533-
// Skip processing for overall nodeset state if not running AND not latest
534-
// (This handles both completed and failed deployments that aren't the latest)
535-
if !isRunningDeployment && !isLatestDeployment {
534+
// Skip failed/error deployments that aren't the latest
535+
// All running and completed deployments are processed
536+
isCurrentDeploymentFailed := condition.IsError(deploymentCondition)
537+
if isCurrentDeploymentFailed && !isLatestDeployment {
536538
continue
537539
}
538540

541+
isCurrentDeploymentRunning := deploymentConditions.IsFalse(dataplanev1.NodeSetDeploymentReadyCondition) && !isCurrentDeploymentFailed
542+
isCurrentDeploymentReady := deploymentConditions.IsTrue(dataplanev1.NodeSetDeploymentReadyCondition)
543+
539544
// Reset the vars for every deployment that affects overall state
540-
isDeploymentReady = false
541-
isDeploymentRunning = false
542-
if condition.IsError(deploymentCondition) {
545+
isNodeSetDeploymentReady = false
546+
isNodeSetDeploymentRunning = false
547+
isNodeSetDeploymentFailed = false
548+
549+
if isCurrentDeploymentFailed {
543550
err = fmt.Errorf("%s", deploymentCondition.Message)
544-
isDeploymentFailed = true
545551
failedDeploymentName = deployment.Name
552+
isNodeSetDeploymentFailed = true
546553
break
547-
} else if deploymentConditions.IsFalse(dataplanev1.NodeSetDeploymentReadyCondition) {
548-
isDeploymentRunning = true
549-
} else if deploymentConditions.IsTrue(dataplanev1.NodeSetDeploymentReadyCondition) {
554+
}
555+
if isCurrentDeploymentRunning {
556+
isNodeSetDeploymentRunning = true
557+
}
558+
559+
if isCurrentDeploymentReady {
550560
// If the nodeset configHash does not match with what's in the deployment or
551561
// deployedBmhHash is different from current bmhRefHash.
552562
if (deployment.Status.NodeSetHashes[instance.Name] != instance.Status.ConfigHash) ||
553563
(!instance.Spec.PreProvisioned &&
554564
deployment.Status.BmhRefHashes[instance.Name] != instance.Status.BmhRefHash) {
555565
continue
556566
}
557-
isDeploymentReady = true
567+
isNodeSetDeploymentReady = true
558568
for k, v := range deployment.Status.ConfigMapHashes {
559569
instance.Status.ConfigMapHashes[k] = v
560570
}
@@ -587,7 +597,7 @@ func checkDeployment(ctx context.Context, helper *helper.Helper,
587597
err := helper.GetClient().Get(ctx, name, service)
588598
if err != nil {
589599
helper.GetLogger().Error(err, "Unable to retrieve OpenStackDataPlaneService %v")
590-
return isDeploymentReady, isDeploymentRunning, isDeploymentFailed, failedDeploymentName, err
600+
return isNodeSetDeploymentReady, isNodeSetDeploymentRunning, isNodeSetDeploymentFailed, failedDeploymentName, err
591601
}
592602

593603
if service.Spec.EDPMServiceType != "update" && service.Spec.EDPMServiceType != "update-services" {
@@ -602,7 +612,7 @@ func checkDeployment(ctx context.Context, helper *helper.Helper,
602612
}
603613
}
604614

605-
return isDeploymentReady, isDeploymentRunning, isDeploymentFailed, failedDeploymentName, err
615+
return isNodeSetDeploymentReady, isNodeSetDeploymentRunning, isNodeSetDeploymentFailed, failedDeploymentName, err
606616
}
607617

608618
// SetupWithManager sets up the controller with the Manager.

tests/functional/dataplane/openstackdataplanenodeset_controller_test.go

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1494,17 +1494,12 @@ var _ = Describe("Dataplane NodeSet Test", func() {
14941494

14951495
When("Testing deployment filtering logic", func() {
14961496
var secondDeploymentName types.NamespacedName
1497-
var thirdDeploymentName types.NamespacedName
14981497

14991498
BeforeEach(func() {
15001499
secondDeploymentName = types.NamespacedName{
15011500
Name: "edpm-deployment-2",
15021501
Namespace: namespace,
15031502
}
1504-
thirdDeploymentName = types.NamespacedName{
1505-
Name: "edpm-deployment-3",
1506-
Namespace: namespace,
1507-
}
15081503
})
15091504

15101505
When("Multiple deployments exist with ServicesOverride", func() {
@@ -1546,7 +1541,7 @@ var _ = Describe("Dataplane NodeSet Test", func() {
15461541
}, th.Timeout, th.Interval).Should(Succeed())
15471542

15481543
// Both deployments should be in status (for visibility)
1549-
// But only latest deployment affects overall nodeset state
1544+
// All completed deployments are processed, with latest deployment determining final state
15501545
Eventually(func(g Gomega) {
15511546
instance := GetDataplaneNodeSet(dataplaneNodeSetName)
15521547
g.Expect(instance.Status.DeploymentStatuses).Should(HaveKey(dataplaneDeploymentName.Name))
@@ -1581,7 +1576,7 @@ var _ = Describe("Dataplane NodeSet Test", func() {
15811576
SimulateDNSDataComplete(dataplaneNodeSetName)
15821577
})
15831578

1584-
It("Should show all deployments in status but only latest affects overall state", func() {
1579+
It("Should show all deployments in status and process all completed deployments", func() {
15851580
// Complete the first deployment
15861581
Eventually(func(g Gomega) {
15871582
ansibleeeName := types.NamespacedName{
@@ -1594,7 +1589,7 @@ var _ = Describe("Dataplane NodeSet Test", func() {
15941589
}, th.Timeout, th.Interval).Should(Succeed())
15951590

15961591
// Both deployments should be included (for visibility)
1597-
// But only latest deployment affects overall nodeset state
1592+
// All completed deployments are processed, with latest determining final state
15981593
Eventually(func(g Gomega) {
15991594
instance := GetDataplaneNodeSet(dataplaneNodeSetName)
16001595
g.Expect(instance.Status.DeploymentStatuses).Should(HaveKey(dataplaneDeploymentName.Name))
@@ -1642,10 +1637,10 @@ var _ = Describe("Dataplane NodeSet Test", func() {
16421637

16431638
// Leave second deployment running (don't complete it)
16441639
// Both deployments should be in status (for visibility)
1645-
// Second deployment affects overall state (running and latest)
1640+
// First deployment is processed (completed), second affects final state (running and latest)
16461641
Eventually(func(g Gomega) {
16471642
instance := GetDataplaneNodeSet(dataplaneNodeSetName)
1648-
// Should have first deployment (for visibility)
1643+
// Should have first deployment (completed, processed)
16491644
g.Expect(instance.Status.DeploymentStatuses).Should(HaveKey(dataplaneDeploymentName.Name))
16501645
// Should have second deployment (running and latest)
16511646
g.Expect(instance.Status.DeploymentStatuses).Should(HaveKey(secondDeploymentName.Name))
@@ -1702,10 +1697,10 @@ var _ = Describe("Dataplane NodeSet Test", func() {
17021697
}, th.Timeout, th.Interval).Should(Succeed())
17031698

17041699
// Both error deployments should be in status (for visibility)
1705-
// But only latest error affects overall nodeset state
1700+
// First failed deployment is skipped (not latest), second error affects final state (latest)
17061701
Eventually(func(g Gomega) {
17071702
instance := GetDataplaneNodeSet(dataplaneNodeSetName)
1708-
// Should have first deployment (for visibility)
1703+
// Should have first deployment (for visibility only)
17091704
g.Expect(instance.Status.DeploymentStatuses).Should(HaveKey(dataplaneDeploymentName.Name))
17101705
// Should have second deployment (latest - affects overall state)
17111706
g.Expect(instance.Status.DeploymentStatuses).Should(HaveKey(secondDeploymentName.Name))
@@ -1721,7 +1716,7 @@ var _ = Describe("Dataplane NodeSet Test", func() {
17211716
})
17221717
})
17231718

1724-
When("Mixed deployment states exist", func() {
1719+
When("Failed deployment followed by completed deployment", func() {
17251720
BeforeEach(func() {
17261721
nodeSetSpec := DefaultDataPlaneNodeSetSpec("edpm-compute")
17271722
nodeSetSpec["preProvisioned"] = true
@@ -1731,18 +1726,13 @@ var _ = Describe("Dataplane NodeSet Test", func() {
17311726
DeferCleanup(th.DeleteInstance, CreateDNSMasq(dnsMasqName, DefaultDNSMasqSpec()))
17321727
DeferCleanup(th.DeleteInstance, CreateDataplaneNodeSet(dataplaneNodeSetName, nodeSetSpec))
17331728

1734-
// Create first deployment (will have error - should be ignored)
1729+
// Create first deployment (will fail)
17351730
firstDeploymentSpec := DefaultDataPlaneDeploymentSpec()
17361731
DeferCleanup(th.DeleteInstance, CreateDataplaneDeployment(dataplaneDeploymentName, firstDeploymentSpec))
17371732

1738-
// Create second deployment with ServicesOverride (should be ignored)
1739-
overrideDeploymentSpec := DefaultDataPlaneDeploymentSpec()
1740-
overrideDeploymentSpec["servicesOverride"] = []string{"bootstrap"}
1741-
DeferCleanup(th.DeleteInstance, CreateDataplaneDeployment(secondDeploymentName, overrideDeploymentSpec))
1742-
1743-
// Create third deployment (will succeed - should be processed)
1744-
thirdDeploymentSpec := DefaultDataPlaneDeploymentSpec()
1745-
DeferCleanup(th.DeleteInstance, CreateDataplaneDeployment(thirdDeploymentName, thirdDeploymentSpec))
1733+
// Create second deployment (will complete successfully)
1734+
secondDeploymentSpec := DefaultDataPlaneDeploymentSpec()
1735+
DeferCleanup(th.DeleteInstance, CreateDataplaneDeployment(secondDeploymentName, secondDeploymentSpec))
17461736

17471737
CreateSSHSecret(dataplaneSSHSecretName)
17481738
CreateCABundleSecret(caBundleSecretName)
@@ -1751,7 +1741,7 @@ var _ = Describe("Dataplane NodeSet Test", func() {
17511741
SimulateDNSDataComplete(dataplaneNodeSetName)
17521742
})
17531743

1754-
It("Should show all deployments in status but only latest affects overall state", func() {
1744+
It("Should show all deployments in status and process completed deployment", func() {
17551745
// Fail the first deployment
17561746
Eventually(func(g Gomega) {
17571747
ansibleeeName := types.NamespacedName{
@@ -1763,27 +1753,31 @@ var _ = Describe("Dataplane NodeSet Test", func() {
17631753
g.Expect(th.K8sClient.Status().Update(th.Ctx, ansibleEE)).To(Succeed())
17641754
}, th.Timeout, th.Interval).Should(Succeed())
17651755

1766-
// Complete the third deployment
1756+
// Complete the second deployment
17671757
Eventually(func(g Gomega) {
17681758
ansibleeeName := types.NamespacedName{
1769-
Name: "bootstrap-" + thirdDeploymentName.Name + "-" + dataplaneNodeSetName.Name,
1759+
Name: "bootstrap-" + secondDeploymentName.Name + "-" + dataplaneNodeSetName.Name,
17701760
Namespace: namespace,
17711761
}
17721762
ansibleEE := GetAnsibleee(ansibleeeName)
17731763
ansibleEE.Status.Succeeded = 1
17741764
g.Expect(th.K8sClient.Status().Update(th.Ctx, ansibleEE)).To(Succeed())
17751765
}, th.Timeout, th.Interval).Should(Succeed())
17761766

1777-
// All deployments should be in status (for visibility)
1778-
// But only latest deployment affects overall nodeset state
1767+
// Wait for deployment controller to populate hashes
1768+
Eventually(func(g Gomega) {
1769+
deployment := GetDataplaneDeployment(secondDeploymentName)
1770+
g.Expect(deployment.Status.NodeSetHashes).Should(HaveKey(dataplaneNodeSetName.Name))
1771+
}, th.Timeout, th.Interval).Should(Succeed())
1772+
1773+
// Both deployments should be in status (for visibility)
1774+
// First failed deployment is skipped (not latest), second completed deployment is processed and determines final state
17791775
Eventually(func(g Gomega) {
17801776
instance := GetDataplaneNodeSet(dataplaneNodeSetName)
1781-
// Should have first deployment (for visibility)
1777+
// Should have first deployment (for visibility only)
17821778
g.Expect(instance.Status.DeploymentStatuses).Should(HaveKey(dataplaneDeploymentName.Name))
1783-
// Should have second deployment (for visibility)
1779+
// Should have second deployment (completed and latest - affects overall state)
17841780
g.Expect(instance.Status.DeploymentStatuses).Should(HaveKey(secondDeploymentName.Name))
1785-
// Should have third deployment (latest - affects overall state)
1786-
g.Expect(instance.Status.DeploymentStatuses).Should(HaveKey(thirdDeploymentName.Name))
17871781
}, th.Timeout, th.Interval).Should(Succeed())
17881782

17891783
// The overall deployment condition should be true from the successful deployment

0 commit comments

Comments
 (0)