Skip to content

Managed Resources are generating watch events on every poll interval due to missing observedGeneration in the Synced condition #902

@bobh66

Description

@bobh66

What happened?

Managed Resources are experiencing updates to the Last Transition Time on conditions that are otherwise equal. This appears to be caused by a missing observedGeneration attribute on one of the Synced conditions which is causing two otherwise identical conditions to appear to be different.

In apis/common/condition.go the Equal() method compares two conditions and assumes that the observedGeneration is set in both:

func (c Condition) Equal(other Condition) bool {
	return c.Type == other.Type &&
		c.Status == other.Status &&
		c.Reason == other.Reason &&
		c.Message == other.Message &&
		c.ObservedGeneration == other.ObservedGeneration
}

if one of the Synced conditions does not have the observedGeneration set then the method returns false, causing the condition to be updated with the same exact information but a later Last Transition Time. This causes watch events on the resource when there are no other changes to the resource.

Updating this code to:

func (c Condition) Equal(other Condition) bool {
	if c.ObservedGeneration == 0 || other.ObservedGeneration == 0 {
		return c.Type == other.Type &&
			c.Status == other.Status &&
			c.Reason == other.Reason &&
			c.Message == other.Message
	}
	return c.Type == other.Type &&
		c.Status == other.Status &&
		c.Reason == other.Reason &&
		c.Message == other.Message &&
		c.ObservedGeneration == other.ObservedGeneration
}

resolves the problem - the conditions are considered to be equal and the Last Transition Time is not updated, so the watch events do not happen.

How can we reproduce it?

Create any resource using provider-upjet-aws. Monitor the resource with a watch and observe that the
Synced conditions change every reconcile/poll interval without any other changes to the resource:

  - lastTransitionTime: "2026-01-14T22:24:42Z"
    observedGeneration: 2
    reason: ReconcileSuccess
    status: "True"
    type: Synced
---
  - lastTransitionTime: "2026-01-14T22:29:31Z"
    observedGeneration: 2
    reason: ReconcileSuccess
    status: "True"
    type: Synced
---
  - lastTransitionTime: "2026-01-14T22:34:27Z"
    observedGeneration: 2
    reason: ReconcileSuccess
    status: "True"
    type: Synced

This seems to imply that the Synced condition returned by the provider/upjet has no observedGenerated and is being replaced by the one generated by the managed reconciler when it calls ReconcileSuccess().

I was not able to find a way to ensure that the Synced condition returned by the provider to the managed reconciler would include the proper observedGeneration but the code change above does seem to resolve the problem.

What environment did it happen in?

Crossplane version: 2.1.3
provider-upjet-aws: 2.3.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    Status

    Done

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions