fix: Check Applied condition before evaluating rollout status (#1243)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Signed-off-by: Qing Hao <qhao@redhat.com>
Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
Qing Hao
2025-12-01 10:14:46 +08:00
committed by GitHub
parent 8f8cd01b52
commit 26edb9423a
3 changed files with 594 additions and 71 deletions

View File

@@ -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 {

View File

@@ -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)
})
}
}

View File

@@ -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{