Summary
WorkApplier.Apply caches the desired work hash and the existing work's generation to skip redundant updates via safeToSkipApply. However, metadata-only changes (labels, annotations) to a ManifestWork do not bump the generation field — only resourceVersion changes. This means safeToSkipApply returns true even when an external actor has modified labels/annotations that the applier owns, and ManifestWorkEqual is never called.
Steps to reproduce
- Use
WorkApplier.Apply to create a ManifestWork with labels (e.g. app.kubernetes.io/managed-by: my-addon)
- Externally modify one of those labels (e.g. change the value to
someone-else)
- Call
WorkApplier.Apply again with the same desired work
Expected: ManifestWorkEqual detects the label diff and patches the MW back to the desired state.
Actual: safeToSkipApply returns true (same desired hash, same generation), the comparison is skipped entirely, and the tampered label persists.
Analysis
The cache in workcache.go stores:
type cachedResource struct {
resourceHash string // hash of desired work
generation int64 // generation of existing work
}
safeToSkipApply matches when both the desired hash and generation are unchanged. Since label changes don't bump generation (only spec changes do), the cache never invalidates for metadata-only modifications.
This breaks the reconciliation contract — a controller using WorkApplier cannot restore its owned labels/annotations if an external actor tampers with them.
Environment
- sdk-go v1.3.0
- Discovered while integrating
WorkApplier into an OCM addon controller
Summary
WorkApplier.Applycaches the desired work hash and the existing work's generation to skip redundant updates viasafeToSkipApply. However, metadata-only changes (labels, annotations) to a ManifestWork do not bump thegenerationfield — onlyresourceVersionchanges. This meanssafeToSkipApplyreturns true even when an external actor has modified labels/annotations that the applier owns, andManifestWorkEqualis never called.Steps to reproduce
WorkApplier.Applyto create a ManifestWork with labels (e.g.app.kubernetes.io/managed-by: my-addon)someone-else)WorkApplier.Applyagain with the same desired workExpected:
ManifestWorkEqualdetects the label diff and patches the MW back to the desired state.Actual:
safeToSkipApplyreturns true (same desired hash, same generation), the comparison is skipped entirely, and the tampered label persists.Analysis
The cache in
workcache.gostores:safeToSkipApplymatches when both the desired hash and generation are unchanged. Since label changes don't bump generation (only spec changes do), the cache never invalidates for metadata-only modifications.This breaks the reconciliation contract — a controller using
WorkAppliercannot restore its owned labels/annotations if an external actor tampers with them.Environment
WorkApplierinto an OCM addon controller