From 26edb9423ae235edc10d75e4f0a1aab5ec5b60e1 Mon Sep 17 00:00:00 2001 From: Qing Hao Date: Mon, 1 Dec 2025 10:14:46 +0800 Subject: [PATCH] fix: Check Applied condition before evaluating rollout status (#1243) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 🤖 Generated with [Claude Code](https://claude.com/claude-code) Signed-off-by: Qing Hao Co-authored-by: Claude --- ...manifestworkreplicaset_deploy_reconcile.go | 65 +- .../manifestworkreplicaset_deploy_test.go | 566 ++++++++++++++++-- .../work/manifestworkreplicaset_test.go | 34 ++ 3 files changed, 594 insertions(+), 71 deletions(-) diff --git a/pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go b/pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go index e7a9f9018..53f4307fe 100644 --- a/pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go +++ b/pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_reconcile.go @@ -218,15 +218,10 @@ func (d *deployReconciler) clusterRolloutStatusFunc(clusterName string, manifest // Get all relevant conditions progressingCond := apimeta.FindStatusCondition(manifestWork.Status.Conditions, workv1.WorkProgressing) degradedCond := apimeta.FindStatusCondition(manifestWork.Status.Conditions, workv1.WorkDegraded) + appliedCond := apimeta.FindStatusCondition(manifestWork.Status.Conditions, workv1.WorkApplied) - // Return ToApply if: - // - No Progressing condition exists yet (work hasn't been reconciled by agent) - // - Progressing condition hasn't observed the latest spec - // - Degraded condition exists but hasn't observed the latest spec - // (Degraded is optional, but if it exists, we wait for it to catch up) - if progressingCond == nil || - progressingCond.ObservedGeneration != manifestWork.Generation || - (degradedCond != nil && degradedCond.ObservedGeneration != manifestWork.Generation) { + // Check if the work should be in ToApply status + if shouldReturnToApply(manifestWork.Generation, appliedCond, progressingCond, degradedCond) { return clsRolloutStatus, nil } @@ -262,6 +257,60 @@ func (d *deployReconciler) clusterRolloutStatusFunc(clusterName string, manifest return clsRolloutStatus, nil } +// shouldReturnToApply determines if the ManifestWork should be in ToApply status +// based on the state of its conditions. +// +// Returns true if: +// - The Applied condition is not ready (missing, hasn't observed latest spec, or not True) +// - The Progressing condition is not ready (missing or hasn't observed latest spec) +// - The Degraded condition exists but hasn't observed the latest spec +// +// IMPORTANT: Applied condition is checked FIRST to ensure the work has been properly applied +// by the spoke agent before checking other agent-side conditions (Progressing/Degraded). +// This prevents using stale timestamps from previous generations when conditions update +// their ObservedGeneration without changing Status. +func shouldReturnToApply(generation int64, appliedCond, progressingCond, degradedCond *metav1.Condition) bool { + // Check Applied condition first - work must be applied by spoke agent + if !isConditionReady(appliedCond, generation, true) { + return true + } + + // Check Progressing condition - work must be reconciled by spoke agent + if !isConditionReady(progressingCond, generation, false) { + return true + } + + // Check Degraded condition if it exists - it must have observed the latest spec + // Degraded is optional, but if it exists, we wait for it to catch up to avoid + // using stale status information + if degradedCond != nil && degradedCond.ObservedGeneration != generation { + return true + } + + return false +} + +// isConditionReady checks if a condition is ready for rollout status evaluation. +// A condition is ready if: +// - It exists (not nil) +// - It has observed the latest generation +// - If requireTrue is set, it must also have Status=True +func isConditionReady(cond *metav1.Condition, generation int64, requireTrue bool) bool { + if cond == nil { + return false + } + + if cond.ObservedGeneration != generation { + return false + } + + if requireTrue && cond.Status != metav1.ConditionTrue { + return false + } + + return true +} + // GetManifestworkApplied return only True status if there all clusters have manifests applied as expected func GetManifestworkApplied(reason string, message string) metav1.Condition { if reason == workapiv1alpha1.ReasonAsExpected { diff --git a/pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go b/pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go index 2908b654f..0d24af096 100644 --- a/pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go +++ b/pkg/work/hub/controllers/manifestworkreplicasetcontroller/manifestworkreplicaset_deploy_test.go @@ -591,6 +591,14 @@ func TestRequeueWithProgressDeadline(t *testing.T) { }, } mw, _ := CreateManifestWork(mwrSet, "cls1", "place-test") + // Set Applied=True first to ensure work has been applied by hub controller + apimeta.SetStatusCondition(&mw.Status.Conditions, metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + Reason: "Applied", + ObservedGeneration: mw.Generation, + LastTransitionTime: metav1.NewTime(time.Now()), + }) // Set Progressing=True AND Degraded=True to simulate a failed work (matching new logic) apimeta.SetStatusCondition(&mw.Status.Conditions, metav1.Condition{ Type: workapiv1.WorkProgressing, @@ -850,7 +858,7 @@ func TestClusterRolloutStatusFunc(t *testing.T) { expectedLastTransition: nil, }, { - name: "degraded condition with unobserved generation - should return ToApply", + name: "no Applied condition with stale Degraded - should return ToApply", manifestWork: &workapiv1.ManifestWork{ ObjectMeta: metav1.ObjectMeta{ Name: "test-mw", @@ -891,6 +899,13 @@ func TestClusterRolloutStatusFunc(t *testing.T) { }, Status: workapiv1.ManifestWorkStatus{ Conditions: []metav1.Condition{ + { + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: 2, + LastTransitionTime: now, + Reason: "Applied", + }, { Type: workapiv1.WorkProgressing, Status: metav1.ConditionTrue, @@ -915,6 +930,13 @@ func TestClusterRolloutStatusFunc(t *testing.T) { }, Status: workapiv1.ManifestWorkStatus{ Conditions: []metav1.Condition{ + { + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: 2, + LastTransitionTime: now, + Reason: "Applied", + }, { Type: workapiv1.WorkProgressing, Status: metav1.ConditionTrue, @@ -935,68 +957,6 @@ func TestClusterRolloutStatusFunc(t *testing.T) { expectedStatus: clustersdkv1alpha1.Failed, expectedLastTransition: &now, }, - { - name: "progressing true but degraded false - should return Progressing", - manifestWork: &workapiv1.ManifestWork{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-mw", - Namespace: "cls1", - Generation: 2, - CreationTimestamp: creationTime, - }, - Status: workapiv1.ManifestWorkStatus{ - Conditions: []metav1.Condition{ - { - Type: workapiv1.WorkProgressing, - Status: metav1.ConditionTrue, - ObservedGeneration: 2, - LastTransitionTime: now, - Reason: "Applying", - }, - { - Type: workapiv1.WorkDegraded, - Status: metav1.ConditionFalse, - ObservedGeneration: 2, - LastTransitionTime: now, - Reason: "Healthy", - }, - }, - }, - }, - expectedStatus: clustersdkv1alpha1.Progressing, - expectedLastTransition: &now, - }, - { - name: "progressing true with degraded unknown - should return Progressing", - manifestWork: &workapiv1.ManifestWork{ - ObjectMeta: metav1.ObjectMeta{ - Name: "test-mw", - Namespace: "cls1", - Generation: 2, - CreationTimestamp: creationTime, - }, - Status: workapiv1.ManifestWorkStatus{ - Conditions: []metav1.Condition{ - { - Type: workapiv1.WorkProgressing, - Status: metav1.ConditionTrue, - ObservedGeneration: 2, - LastTransitionTime: now, - Reason: "Applying", - }, - { - Type: workapiv1.WorkDegraded, - Status: metav1.ConditionUnknown, - ObservedGeneration: 2, - LastTransitionTime: now, - Reason: "Unknown", - }, - }, - }, - }, - expectedStatus: clustersdkv1alpha1.Progressing, - expectedLastTransition: &now, - }, { name: "progressing false - should return Succeeded", manifestWork: &workapiv1.ManifestWork{ @@ -1008,6 +968,13 @@ func TestClusterRolloutStatusFunc(t *testing.T) { }, Status: workapiv1.ManifestWorkStatus{ Conditions: []metav1.Condition{ + { + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: 2, + LastTransitionTime: now, + Reason: "Applied", + }, { Type: workapiv1.WorkProgressing, Status: metav1.ConditionFalse, @@ -1032,6 +999,13 @@ func TestClusterRolloutStatusFunc(t *testing.T) { }, Status: workapiv1.ManifestWorkStatus{ Conditions: []metav1.Condition{ + { + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: 2, + LastTransitionTime: now, + Reason: "Applied", + }, { Type: workapiv1.WorkProgressing, Status: metav1.ConditionFalse, @@ -1063,6 +1037,13 @@ func TestClusterRolloutStatusFunc(t *testing.T) { }, Status: workapiv1.ManifestWorkStatus{ Conditions: []metav1.Condition{ + { + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: 2, + LastTransitionTime: now, + Reason: "Applied", + }, { Type: workapiv1.WorkProgressing, Status: metav1.ConditionUnknown, @@ -1076,6 +1057,130 @@ func TestClusterRolloutStatusFunc(t *testing.T) { expectedStatus: clustersdkv1alpha1.Progressing, expectedLastTransition: &now, }, + { + name: "WorkApplied Status=False with current generation - should return ToApply", + manifestWork: &workapiv1.ManifestWork{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-mw", + Namespace: "cls1", + Generation: 2, + CreationTimestamp: creationTime, + }, + Status: workapiv1.ManifestWorkStatus{ + Conditions: []metav1.Condition{ + { + Type: workapiv1.WorkApplied, + Status: metav1.ConditionFalse, + ObservedGeneration: 2, + LastTransitionTime: now, + Reason: "ApplyFailed", + }, + { + Type: workapiv1.WorkProgressing, + Status: metav1.ConditionFalse, + ObservedGeneration: 2, + LastTransitionTime: now, + Reason: "Completed", + }, + }, + }, + }, + expectedStatus: clustersdkv1alpha1.ToApply, + expectedLastTransition: nil, + }, + { + name: "WorkApplied Status=Unknown with current generation - should return ToApply", + manifestWork: &workapiv1.ManifestWork{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-mw", + Namespace: "cls1", + Generation: 2, + CreationTimestamp: creationTime, + }, + Status: workapiv1.ManifestWorkStatus{ + Conditions: []metav1.Condition{ + { + Type: workapiv1.WorkApplied, + Status: metav1.ConditionUnknown, + ObservedGeneration: 2, + LastTransitionTime: now, + Reason: "ApplyStatusUnknown", + }, + { + Type: workapiv1.WorkProgressing, + Status: metav1.ConditionFalse, + ObservedGeneration: 2, + LastTransitionTime: now, + Reason: "Completed", + }, + }, + }, + }, + expectedStatus: clustersdkv1alpha1.ToApply, + expectedLastTransition: nil, + }, + { + name: "WorkApplied with stale ObservedGeneration (old gen 1, current gen 2) - should return ToApply", + manifestWork: &workapiv1.ManifestWork{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-mw", + Namespace: "cls1", + Generation: 2, + CreationTimestamp: creationTime, + }, + Status: workapiv1.ManifestWorkStatus{ + Conditions: []metav1.Condition{ + { + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: 1, + LastTransitionTime: now, + Reason: "Applied", + }, + { + Type: workapiv1.WorkProgressing, + Status: metav1.ConditionFalse, + ObservedGeneration: 2, + LastTransitionTime: now, + Reason: "Completed", + }, + }, + }, + }, + expectedStatus: clustersdkv1alpha1.ToApply, + expectedLastTransition: nil, + }, + { + name: "Progressing with old ObservedGeneration but newer WorkApplied - should return ToApply", + manifestWork: &workapiv1.ManifestWork{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-mw", + Namespace: "cls1", + Generation: 3, + CreationTimestamp: creationTime, + }, + Status: workapiv1.ManifestWorkStatus{ + Conditions: []metav1.Condition{ + { + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: 3, + LastTransitionTime: now, + Reason: "Applied", + }, + { + Type: workapiv1.WorkProgressing, + Status: metav1.ConditionFalse, + ObservedGeneration: 2, + LastTransitionTime: now, + Reason: "Completed", + }, + }, + }, + }, + expectedStatus: clustersdkv1alpha1.ToApply, + expectedLastTransition: nil, + }, } for _, tt := range tests { @@ -1106,3 +1211,338 @@ func TestClusterRolloutStatusFunc(t *testing.T) { }) } } + +func TestShouldReturnToApply(t *testing.T) { + now := metav1.Now() + generation := int64(2) + + tests := []struct { + name string + generation int64 + appliedCond *metav1.Condition + progressCond *metav1.Condition + degradedCond *metav1.Condition + expected bool + description string + }{ + { + name: "applied condition is nil - should return true", + generation: generation, + appliedCond: nil, + progressCond: &metav1.Condition{Type: workapiv1.WorkProgressing, Status: metav1.ConditionTrue, ObservedGeneration: generation}, + degradedCond: nil, + expected: true, + description: "When Applied condition doesn't exist, work hasn't been applied by hub controller yet", + }, + { + name: "applied condition has stale generation - should return true", + generation: generation, + appliedCond: &metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: 1, + LastTransitionTime: now, + }, + progressCond: &metav1.Condition{Type: workapiv1.WorkProgressing, Status: metav1.ConditionTrue, ObservedGeneration: generation}, + degradedCond: nil, + expected: true, + description: "When Applied condition hasn't observed latest spec, work needs to be reapplied", + }, + { + name: "applied condition is false - should return true", + generation: generation, + appliedCond: &metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionFalse, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + progressCond: &metav1.Condition{Type: workapiv1.WorkProgressing, Status: metav1.ConditionTrue, ObservedGeneration: generation}, + degradedCond: nil, + expected: true, + description: "When Applied condition is False, work failed to apply", + }, + { + name: "progressing condition is nil - should return true", + generation: generation, + appliedCond: &metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + progressCond: nil, + degradedCond: nil, + expected: true, + description: "When Progressing condition doesn't exist, work hasn't been reconciled by agent yet", + }, + { + name: "progressing condition has stale generation - should return true", + generation: generation, + appliedCond: &metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + progressCond: &metav1.Condition{ + Type: workapiv1.WorkProgressing, + Status: metav1.ConditionFalse, + ObservedGeneration: 1, + LastTransitionTime: now, + }, + degradedCond: nil, + expected: true, + description: "When Progressing condition hasn't observed latest spec, agent hasn't reconciled the new work yet", + }, + { + name: "degraded condition exists with stale generation - should return true", + generation: generation, + appliedCond: &metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + progressCond: &metav1.Condition{ + Type: workapiv1.WorkProgressing, + Status: metav1.ConditionTrue, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + degradedCond: &metav1.Condition{ + Type: workapiv1.WorkDegraded, + Status: metav1.ConditionTrue, + ObservedGeneration: 1, + LastTransitionTime: now, + }, + expected: true, + description: "When Degraded condition exists but hasn't observed latest spec, we wait for it to catch up", + }, + { + name: "all conditions ready - should return false", + generation: generation, + appliedCond: &metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + progressCond: &metav1.Condition{ + Type: workapiv1.WorkProgressing, + Status: metav1.ConditionTrue, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + degradedCond: nil, + expected: false, + description: "When all conditions are current, proceed with rollout status evaluation", + }, + { + name: "all conditions ready including degraded - should return false", + generation: generation, + appliedCond: &metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + progressCond: &metav1.Condition{ + Type: workapiv1.WorkProgressing, + Status: metav1.ConditionFalse, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + degradedCond: &metav1.Condition{ + Type: workapiv1.WorkDegraded, + Status: metav1.ConditionFalse, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + expected: false, + description: "When all conditions including Degraded are current, proceed with rollout status evaluation", + }, + { + name: "applied condition status unknown - should return true", + generation: generation, + appliedCond: &metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionUnknown, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + progressCond: &metav1.Condition{ + Type: workapiv1.WorkProgressing, + Status: metav1.ConditionTrue, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + degradedCond: nil, + expected: true, + description: "When Applied condition status is Unknown even with current generation, work is not ready to apply", + }, + { + name: "degraded ahead of applied generation - should return true", + generation: generation, + appliedCond: &metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: 1, + LastTransitionTime: now, + }, + progressCond: &metav1.Condition{ + Type: workapiv1.WorkProgressing, + Status: metav1.ConditionTrue, + ObservedGeneration: 1, + LastTransitionTime: now, + }, + degradedCond: &metav1.Condition{ + Type: workapiv1.WorkDegraded, + Status: metav1.ConditionTrue, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + expected: true, + description: "When Degraded is ahead of Applied generation, wait for Applied to catch up", + }, + { + name: "applied and progressing both stale but degraded current - should return true", + generation: generation, + appliedCond: &metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: 1, + LastTransitionTime: now, + }, + progressCond: &metav1.Condition{ + Type: workapiv1.WorkProgressing, + Status: metav1.ConditionFalse, + ObservedGeneration: 1, + LastTransitionTime: now, + }, + degradedCond: &metav1.Condition{ + Type: workapiv1.WorkDegraded, + Status: metav1.ConditionFalse, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + expected: true, + description: "When both Applied and Progressing are stale, return ToApply regardless of Degraded status", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := shouldReturnToApply(tt.generation, tt.appliedCond, tt.progressCond, tt.degradedCond) + assert.Equal(t, tt.expected, result, tt.description) + }) + } +} + +func TestIsConditionReady(t *testing.T) { + now := metav1.Now() + generation := int64(2) + + tests := []struct { + name string + condition *metav1.Condition + generation int64 + requireTrue bool + expected bool + description string + }{ + { + name: "nil condition - should return false", + condition: nil, + generation: generation, + requireTrue: false, + expected: false, + description: "When condition doesn't exist, it's not ready", + }, + { + name: "stale observed generation - should return false", + condition: &metav1.Condition{ + Type: workapiv1.WorkProgressing, + Status: metav1.ConditionTrue, + ObservedGeneration: 1, + LastTransitionTime: now, + }, + generation: generation, + requireTrue: false, + expected: false, + description: "When condition hasn't observed latest generation, it's not ready", + }, + { + name: "current generation but status not true when required - should return false", + condition: &metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionFalse, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + generation: generation, + requireTrue: true, + expected: false, + description: "When requireTrue is set and status is False, condition is not ready", + }, + { + name: "current generation but status unknown when required true - should return false", + condition: &metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionUnknown, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + generation: generation, + requireTrue: true, + expected: false, + description: "When requireTrue is set and status is Unknown, condition is not ready", + }, + { + name: "current generation and status true when required - should return true", + condition: &metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + generation: generation, + requireTrue: true, + expected: true, + description: "When condition has current generation and status is True when required, it's ready", + }, + { + name: "current generation and status false when not requiring true - should return true", + condition: &metav1.Condition{ + Type: workapiv1.WorkProgressing, + Status: metav1.ConditionFalse, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + generation: generation, + requireTrue: false, + expected: true, + description: "When requireTrue is false, any status with current generation is ready", + }, + { + name: "current generation and status true when not requiring true - should return true", + condition: &metav1.Condition{ + Type: workapiv1.WorkProgressing, + Status: metav1.ConditionTrue, + ObservedGeneration: generation, + LastTransitionTime: now, + }, + generation: generation, + requireTrue: false, + expected: true, + description: "When requireTrue is false, any status with current generation is ready", + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + result := isConditionReady(tt.condition, tt.generation, tt.requireTrue) + assert.Equal(t, tt.expected, result, tt.description) + }) + } +} diff --git a/test/integration/work/manifestworkreplicaset_test.go b/test/integration/work/manifestworkreplicaset_test.go index 70411fb82..e03c5d340 100644 --- a/test/integration/work/manifestworkreplicaset_test.go +++ b/test/integration/work/manifestworkreplicaset_test.go @@ -386,6 +386,12 @@ var _ = ginkgo.Describe("ManifestWorkReplicaSet", func() { gomega.Expect(err).ToNot(gomega.HaveOccurred()) for _, work := range works.Items { workCopy := work.DeepCopy() + meta.SetStatusCondition(&workCopy.Status.Conditions, metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + Reason: "AppliedManifestWorkComplete", + ObservedGeneration: workCopy.Generation, + }) meta.SetStatusCondition(&workCopy.Status.Conditions, metav1.Condition{ Type: workapiv1.WorkProgressing, Status: metav1.ConditionFalse, @@ -404,6 +410,12 @@ var _ = ginkgo.Describe("ManifestWorkReplicaSet", func() { gomega.Expect(err).ToNot(gomega.HaveOccurred()) for _, work := range works.Items { workCopy := work.DeepCopy() + meta.SetStatusCondition(&workCopy.Status.Conditions, metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + Reason: "AppliedManifestWorkComplete", + ObservedGeneration: workCopy.Generation, + }) meta.SetStatusCondition(&workCopy.Status.Conditions, metav1.Condition{ Type: workapiv1.WorkProgressing, Status: metav1.ConditionFalse, @@ -441,6 +453,12 @@ var _ = ginkgo.Describe("ManifestWorkReplicaSet", func() { gomega.Expect(err).ToNot(gomega.HaveOccurred()) for _, work := range works.Items { workCopy := work.DeepCopy() + meta.SetStatusCondition(&workCopy.Status.Conditions, metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + Reason: "Applied", + ObservedGeneration: workCopy.Generation, + }) meta.SetStatusCondition(&workCopy.Status.Conditions, metav1.Condition{ Type: workapiv1.WorkProgressing, Status: metav1.ConditionTrue, @@ -497,6 +515,14 @@ var _ = ginkgo.Describe("ManifestWorkReplicaSet", func() { gomega.Expect(err).ToNot(gomega.HaveOccurred()) for _, work := range works.Items { workCopy := work.DeepCopy() + meta.SetStatusCondition( + &workCopy.Status.Conditions, + metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + Reason: "Applied", + ObservedGeneration: workCopy.Generation, + }) meta.SetStatusCondition( &workCopy.Status.Conditions, metav1.Condition{ @@ -564,6 +590,14 @@ var _ = ginkgo.Describe("ManifestWorkReplicaSet", func() { gomega.Expect(err).ToNot(gomega.HaveOccurred()) for _, work := range works.Items { workCopy := work.DeepCopy() + meta.SetStatusCondition( + &workCopy.Status.Conditions, + metav1.Condition{ + Type: workapiv1.WorkApplied, + Status: metav1.ConditionTrue, + Reason: "Applied", + ObservedGeneration: workCopy.Generation, + }) meta.SetStatusCondition( &workCopy.Status.Conditions, metav1.Condition{