diff --git a/apis/common/condition.go b/apis/common/condition.go index 03f67110c..b7017d61c 100644 --- a/apis/common/condition.go +++ b/apis/common/condition.go @@ -45,6 +45,10 @@ const ( // as a system condition. See the tracking issue for more details // https://github.com/crossplane/crossplane/issues/5643. TypeHealthy ConditionType = "Healthy" + + // TypeUpToDate resources are believed to accurately represent the remote resource state. + // The condition is controlled by the ResourceUpToDate return value from the Observe method. + TypeUpToDate ConditionType = "UpToDate" ) // A ConditionReason represents the reason a resource is in a condition. @@ -65,6 +69,14 @@ const ( ReasonReconcilePaused ConditionReason = "ReconcilePaused" ) +// Reasons a resource is or is not up to date. +const ( + ReasonUpdateRestricted ConditionReason = "UpdateRestricted" + ReasonObserveMatch ConditionReason = "ObserveMatch" + ReasonUpdateFailed ConditionReason = "UpdateFailed" + ReasonUpdateRequested ConditionReason = "UpdateRequested" +) + // See https://github.com/kubernetes/community/blob/master/contributors/devel/sig-architecture/api-conventions.md#typical-status-properties // A Condition that may apply to a resource. @@ -130,7 +142,7 @@ func (c Condition) WithObservedGeneration(gen int64) Condition { // Crossplane system (e.g, Ready, Synced, Healthy). func IsSystemConditionType(t ConditionType) bool { switch t { - case TypeReady, TypeSynced, TypeHealthy: + case TypeReady, TypeSynced, TypeHealthy, TypeUpToDate: return true } @@ -312,3 +324,58 @@ func ReconcilePaused() Condition { Reason: ReasonReconcilePaused, } } + +// ObserveMatch returns a condition that indicates the Observe +// method returned true. +func ObserveMatch() Condition { + return Condition{ + Type: TypeUpToDate, + Status: corev1.ConditionTrue, + LastTransitionTime: metav1.Now(), + Reason: ReasonObserveMatch, + } +} + +// UpdateRequested returns a condition that indicates the Observe +// method returned false and the Update method was called successfully. +func UpdateRequested() Condition { + return Condition{ + Type: TypeUpToDate, + Status: corev1.ConditionFalse, + LastTransitionTime: metav1.Now(), + Reason: ReasonUpdateRequested, + } +} + +// UpdateRestricted returns a condition that indicates the Observe +// method returned false and the Update method is not allowed. +func UpdateRestricted() Condition { + return Condition{ + Type: TypeUpToDate, + Status: corev1.ConditionFalse, + LastTransitionTime: metav1.Now(), + Reason: ReasonUpdateRestricted, + } +} + +// UpdateFailed returns a condition that indicates the Observe +// method returned false and the Update method was unsuccessful in synchronizing the resource state. +func UpdateFailed() Condition { + return Condition{ + Type: TypeUpToDate, + Status: corev1.ConditionFalse, + LastTransitionTime: metav1.Now(), + Reason: ReasonUpdateFailed, + } +} + +// PausedUnknown returns a condition that indicates the Observe +// method was not called because reconciliation is paused so the status is unknown. +func PausedUnknown() Condition { + return Condition{ + Type: TypeUpToDate, + Status: corev1.ConditionUnknown, + LastTransitionTime: metav1.Now(), + Reason: ReasonReconcilePaused, + } +} diff --git a/apis/common/v1/condition.go b/apis/common/v1/condition.go index c84c18f76..a32f2ea9c 100644 --- a/apis/common/v1/condition.go +++ b/apis/common/v1/condition.go @@ -134,3 +134,23 @@ func ReconcileError(err error) Condition { func ReconcilePaused() Condition { return common.ReconcilePaused() } + +// ObserveMatch returns a condition indicating that the managed resource desired state matches +// the external resource state. +func ObserveMatch() Condition { return common.ObserveMatch() } + +// PausedUnknown returns a condition that indicates reconciliation is paused and it is unknown if the desired +// state of the managed resource matches the external resource state. +func PausedUnknown() Condition { return common.PausedUnknown() } + +// UpdateRequested returns a condition that indicates a mismatch between the managed resource and the +// external resource was detected and an update of the external resource has been requested. +func UpdateRequested() Condition { return common.UpdateRequested() } + +// UpdateFailed returns a condition that indicates a mismatch between the managed resource and the +// external resource was detected and an updated of the external resource was attempted and failed. +func UpdateFailed() Condition { return common.UpdateFailed() } + +// UpdateRestricted returns a condition that indicates a mismatch between the managed resource and the +// external resource was detected but an Update was not attempted due to managementPolicy restrictions. +func UpdateRestricted() Condition { return common.UpdateRestricted() } diff --git a/pkg/reconciler/managed/reconciler.go b/pkg/reconciler/managed/reconciler.go index 8db657e5c..ace0990d6 100644 --- a/pkg/reconciler/managed/reconciler.go +++ b/pkg/reconciler/managed/reconciler.go @@ -939,7 +939,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu log.Debug("Reconciliation is paused either through the `spec.managementPolicies` or the pause annotation", "annotation", meta.AnnotationKeyReconciliationPaused) record.Event(managed, event.Normal(reasonReconciliationPaused, "Reconciliation is paused either through the `spec.managementPolicies` or the pause annotation", "annotation", meta.AnnotationKeyReconciliationPaused)) - status.MarkConditions(xpv1.ReconcilePaused()) + status.MarkConditions(xpv1.ReconcilePaused(), xpv1.PausedUnknown()) // if the pause annotation is removed or the management policies changed, we will have a chance to reconcile // again and resume and if status update fails, we will reconcile again to retry to update the status return reconcile.Result{}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) @@ -1436,7 +1436,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu // https://github.com/crossplane/crossplane/issues/289 reconcileAfter := r.pollIntervalHook(managed, r.pollInterval) log.Debug("External resource is up to date", "requeue-after", time.Now().Add(reconcileAfter)) - status.MarkConditions(xpv1.ReconcileSuccess()) + status.MarkConditions(xpv1.ReconcileSuccess(), xpv1.ObserveMatch()) r.metricRecorder.recordFirstTimeReady(managed) // record that we intentionally did not update the managed resource @@ -1456,7 +1456,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu if !policy.ShouldUpdate() { reconcileAfter := r.pollIntervalHook(managed, r.pollInterval) log.Debug("Skipping update due to managementPolicies. Reconciliation succeeded", "requeue-after", time.Now().Add(reconcileAfter)) - status.MarkConditions(xpv1.ReconcileSuccess()) + status.MarkConditions(xpv1.ReconcileSuccess(), xpv1.UpdateRestricted().WithMessage(observation.Diff)) return reconcile.Result{RequeueAfter: reconcileAfter}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) } @@ -1475,7 +1475,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu } record.Event(managed, event.Warning(reasonCannotUpdate, err)) - status.MarkConditions(xpv1.ReconcileError(errors.Wrap(err, errReconcileUpdate))) + status.MarkConditions(xpv1.ReconcileError(errors.Wrap(err, errReconcileUpdate)), xpv1.UpdateFailed().WithMessage(observation.Diff)) return reconcile.Result{Requeue: true}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) } @@ -1506,7 +1506,7 @@ func (r *Reconciler) Reconcile(ctx context.Context, req reconcile.Request) (resu reconcileAfter := r.pollIntervalHook(managed, r.pollInterval) log.Debug("Successfully requested update of external resource", "requeue-after", time.Now().Add(reconcileAfter)) record.Event(managed, event.Normal(reasonUpdated, "Successfully requested update of external resource")) - status.MarkConditions(xpv1.ReconcileSuccess()) + status.MarkConditions(xpv1.ReconcileSuccess(), xpv1.UpdateRequested().WithMessage(observation.Diff)) return reconcile.Result{RequeueAfter: reconcileAfter}, errors.Wrap(r.client.Status().Update(ctx, managed), errUpdateManagedStatus) } diff --git a/pkg/reconciler/managed/reconciler_legacy_test.go b/pkg/reconciler/managed/reconciler_legacy_test.go index fe4df5f14..c4d10655d 100644 --- a/pkg/reconciler/managed/reconciler_legacy_test.go +++ b/pkg/reconciler/managed/reconciler_legacy_test.go @@ -351,7 +351,7 @@ func TestReconciler(t *testing.T) { MockGet: legacyManagedMockGetFn(nil, 42), MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newLegacyManaged(42) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.ObserveMatch().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "A successful no-op reconcile should be reported as a conditioned status." @@ -1088,7 +1088,7 @@ func TestReconciler(t *testing.T) { MockGet: legacyManagedMockGetFn(nil, 42), MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newLegacyManaged(42) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.ObserveMatch().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "A successful no-op reconcile should be reported as a conditioned status." @@ -1253,7 +1253,7 @@ func TestReconciler(t *testing.T) { MockGet: legacyManagedMockGetFn(nil, 42), MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newLegacyManaged(42) - want.SetConditions(xpv1.ReconcileError(errors.Wrap(errBoom, errReconcileUpdate)).WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileError(errors.Wrap(errBoom, errReconcileUpdate)).WithObservedGeneration(42), xpv1.UpdateFailed().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "Errors while updating an external resource should be reported as a conditioned status." @@ -1354,7 +1354,7 @@ func TestReconciler(t *testing.T) { MockGet: legacyManagedMockGetFn(nil, 42), MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newLegacyManaged(42) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.UpdateRequested().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "A successful managed resource update should be reported as a conditioned status." @@ -1398,7 +1398,7 @@ func TestReconciler(t *testing.T) { MockGet: legacyManagedMockGetFn(nil, 42), MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newLegacyManaged(42) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.UpdateRequested().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "A successful managed resource update should be reported as a conditioned status." @@ -1450,7 +1450,7 @@ func TestReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newLegacyManaged(42) want.SetAnnotations(map[string]string{meta.AnnotationKeyReconciliationPaused: "true"}) - want.SetConditions(xpv1.ReconcilePaused().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcilePaused().WithObservedGeneration(42), xpv1.PausedUnknown().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := `If managed resource has the pause annotation with value "true", it should acquire "Synced" status condition with the status "False" and the reason "ReconcilePaused".` @@ -1480,7 +1480,7 @@ func TestReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newLegacyManaged(42) want.SetManagementPolicies(xpv1.ManagementPolicies{}) - want.SetConditions(xpv1.ReconcilePaused().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcilePaused().WithObservedGeneration(42), xpv1.PausedUnknown().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := `If managed resource has the pause annotation with value "true", it should acquire "Synced" status condition with the status "False" and the reason "ReconcilePaused".` @@ -1516,7 +1516,7 @@ func TestReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newLegacyManaged(42) want.SetAnnotations(map[string]string{meta.AnnotationKeyReconciliationPaused: "false"}) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.ObserveMatch().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := `Managed resource should acquire Synced=False/ReconcileSuccess status condition after a resume.` @@ -1778,7 +1778,7 @@ func TestReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newLegacyManaged(42) want.SetManagementPolicies(xpv1.ManagementPolicies{xpv1.ManagementActionObserve}) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42).WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42).WithObservedGeneration(42), xpv1.UpdateRestricted().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "With ObserveOnly, a successful managed resource observation should be reported as a conditioned status." @@ -1915,7 +1915,7 @@ func TestReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newLegacyManaged(42) want.SetManagementPolicies(xpv1.ManagementPolicies{xpv1.ManagementActionObserve, xpv1.ManagementActionLateInitialize, xpv1.ManagementActionCreate, xpv1.ManagementActionDelete}) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.UpdateRestricted().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := `Managed resource should acquire Synced=False/ReconcileSuccess status condition.` @@ -1966,7 +1966,7 @@ func TestReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newLegacyManaged(42) want.SetManagementPolicies(xpv1.ManagementPolicies{xpv1.ManagementActionAll}) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42).WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42).WithObservedGeneration(42), xpv1.UpdateRequested().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "A successful managed resource update should be reported as a conditioned status." @@ -2017,7 +2017,7 @@ func TestReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newLegacyManaged(42) want.SetManagementPolicies(xpv1.ManagementPolicies{xpv1.ManagementActionAll}) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.UpdateRequested().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "A successful managed resource update should be reported as a conditioned status." @@ -2069,7 +2069,7 @@ func TestReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newLegacyManaged(42) want.SetManagementPolicies(xpv1.ManagementPolicies{xpv1.ManagementActionObserve, xpv1.ManagementActionUpdate, xpv1.ManagementActionCreate, xpv1.ManagementActionDelete}) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.ObserveMatch().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "Errors updating a managed resource should be reported as a conditioned status." diff --git a/pkg/reconciler/managed/reconciler_modern_test.go b/pkg/reconciler/managed/reconciler_modern_test.go index 41709b2df..e9e2909f2 100644 --- a/pkg/reconciler/managed/reconciler_modern_test.go +++ b/pkg/reconciler/managed/reconciler_modern_test.go @@ -355,7 +355,7 @@ func TestModernReconciler(t *testing.T) { MockGet: modernManagedMockGetFn(nil, 42), MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newModernManaged(42) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.ObserveMatch().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "A successful no-op reconcile should be reported as a conditioned status." @@ -1094,7 +1094,7 @@ func TestModernReconciler(t *testing.T) { MockGet: modernManagedMockGetFn(nil, 42), MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newModernManaged(42) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.ObserveMatch().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "A successful no-op reconcile should be reported as a conditioned status." @@ -1259,7 +1259,7 @@ func TestModernReconciler(t *testing.T) { MockGet: modernManagedMockGetFn(nil, 42), MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newModernManaged(42) - want.SetConditions(xpv1.ReconcileError(errors.Wrap(errBoom, errReconcileUpdate)).WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileError(errors.Wrap(errBoom, errReconcileUpdate)).WithObservedGeneration(42), xpv1.UpdateFailed().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "Errors while updating an external resource should be reported as a conditioned status." @@ -1360,7 +1360,7 @@ func TestModernReconciler(t *testing.T) { MockGet: modernManagedMockGetFn(nil, 42), MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newModernManaged(42) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.UpdateRequested().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "A successful managed resource update should be reported as a conditioned status." @@ -1404,7 +1404,7 @@ func TestModernReconciler(t *testing.T) { MockGet: modernManagedMockGetFn(nil, 42), MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newModernManaged(42) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.UpdateRequested().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "A successful managed resource update should be reported as a conditioned status." @@ -1456,7 +1456,7 @@ func TestModernReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newModernManaged(42) want.SetAnnotations(map[string]string{meta.AnnotationKeyReconciliationPaused: "true"}) - want.SetConditions(xpv1.ReconcilePaused().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcilePaused().WithObservedGeneration(42), xpv1.PausedUnknown().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := `If managed resource has the pause annotation with value "true", it should acquire "Synced" status condition with the status "False" and the reason "ReconcilePaused".` @@ -1486,7 +1486,7 @@ func TestModernReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newModernManaged(42) want.SetManagementPolicies(xpv1.ManagementPolicies{}) - want.SetConditions(xpv1.ReconcilePaused().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcilePaused().WithObservedGeneration(42), xpv1.PausedUnknown().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := `If managed resource has the pause annotation with value "true", it should acquire "Synced" status condition with the status "False" and the reason "ReconcilePaused".` @@ -1522,7 +1522,7 @@ func TestModernReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newModernManaged(42) want.SetAnnotations(map[string]string{meta.AnnotationKeyReconciliationPaused: "false"}) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.ObserveMatch().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := `Managed resource should acquire Synced=False/ReconcileSuccess status condition after a resume.` @@ -1784,7 +1784,7 @@ func TestModernReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newModernManaged(42) want.SetManagementPolicies(xpv1.ManagementPolicies{xpv1.ManagementActionObserve}) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42).WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42).WithObservedGeneration(42), xpv1.UpdateRestricted().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "With ObserveOnly, a successful managed resource observation should be reported as a conditioned status." @@ -1921,7 +1921,7 @@ func TestModernReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newModernManaged(42) want.SetManagementPolicies(xpv1.ManagementPolicies{xpv1.ManagementActionObserve, xpv1.ManagementActionLateInitialize, xpv1.ManagementActionCreate, xpv1.ManagementActionDelete}) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.UpdateRestricted().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := `Managed resource should acquire Synced=False/ReconcileSuccess status condition.` @@ -1972,7 +1972,7 @@ func TestModernReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newModernManaged(42) want.SetManagementPolicies(xpv1.ManagementPolicies{xpv1.ManagementActionAll}) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42).WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42).WithObservedGeneration(42), xpv1.UpdateRequested().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "A successful managed resource update should be reported as a conditioned status." @@ -2023,7 +2023,7 @@ func TestModernReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newModernManaged(42) want.SetManagementPolicies(xpv1.ManagementPolicies{xpv1.ManagementActionAll}) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.UpdateRequested().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "A successful managed resource update should be reported as a conditioned status." @@ -2075,7 +2075,7 @@ func TestModernReconciler(t *testing.T) { MockStatusUpdate: test.MockSubResourceUpdateFn(func(_ context.Context, obj client.Object, _ ...client.SubResourceUpdateOption) error { want := newModernManaged(42) want.SetManagementPolicies(xpv1.ManagementPolicies{xpv1.ManagementActionObserve, xpv1.ManagementActionUpdate, xpv1.ManagementActionCreate, xpv1.ManagementActionDelete}) - want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42)) + want.SetConditions(xpv1.ReconcileSuccess().WithObservedGeneration(42), xpv1.ObserveMatch().WithObservedGeneration(42)) if diff := cmp.Diff(want, obj, test.EquateConditions()); diff != "" { reason := "Errors updating a managed resource should be reported as a conditioned status."