Skip to content

fix(controller): resolve owners by controller reference and sort Jobs - #73

Merged
slauger merged 1 commit into
developfrom
fix/owner-resolution
Sep 6, 2026
Merged

slauger merged 1 commit into
developfrom
fix/owner-resolution

Conversation

@slauger

@slauger slauger commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Summary

Three correctness problems in the path that decides which workload to act on. All three can make the operator scale down the wrong thing, which is the worst outcome this operator has, since it never scales anything back up.

  • OwnerReferences[0] is not necessarily the controller. At most one reference carries controller: true and the ordering is not defined, so an object with an extra non-controller owner could resolve to the wrong parent or to nothing at all. Now uses metav1.GetControllerOf at all three levels.
  • The owner UID was never verified. A ReplicaSet or Job deleted and recreated under the same name would be acted on despite not owning the pod. A mismatch is now treated as "no owner" rather than as a match.
  • "Newest Job" was the last element of an unsorted List. That only held while CronJob's <name>-<unixminutes> suffixes all had the same digit count and the server returned them in name order. Sorted by creation timestamp now.

The fixtures had to become realistic first. They set neither controller: true nor matching UIDs, both of which real Kubernetes always does, so the corrected code initially failed nine tests. That is worth noting rather than hiding: the tests were passing because they modelled a state the cluster does not produce, which is the same reason the duration bug in #64 went unnoticed.

Closes #65

Test plan

  • Three new tests, one per fix: a pod whose first owner reference is a non-controller ConfigMap still resolves to its Deployment; a pod whose ReplicaSet was recreated under the same name resolves to nothing; and a CronJob whose Jobs are seeded newest-first still evaluates the newest by timestamp, which in that fixture is the healthy one.
  • make ci passes; coverage 61.2 percent.
  • Two unparam findings surfaced while adding fixtures. Rather than silence them, the constant CronJob name moved into a testCronJobName constant and the redundant parameters are gone.

Three correctness problems in the path that decides which workload to
act on, all of which could make the operator scale down the wrong thing.

resolveOwnerWorkload read OwnerReferences[0]. At most one reference has
controller: true and the ordering is not defined, so an object carrying
an extra non-controller owner could resolve to the wrong parent or to
nothing. Uses metav1.GetControllerOf now, at all three levels.

The owner UID was never compared. A ReplicaSet or Job deleted and
recreated under the same name would be acted on despite not owning the
pod. A mismatch is now treated as no owner.

allReplicasFailing took the newest Job of a CronJob as the last element
of an unsorted List. That only worked while the unix-minute suffixes had
a stable digit count. Sorted by creation timestamp instead.

The test fixtures set neither controller: true nor matching UIDs, which
real Kubernetes always does, so they had to become realistic before the
fixes could pass. Adds cases for a non-controller reference listed
first, a stale reference, and Jobs returned out of order.

Closes #65

Signed-off-by: Simon Lauger <simon@lauger.de>
@slauger
slauger merged commit cf06fd2 into develop Sep 6, 2026
14 checks passed
@slauger
slauger deleted the fix/owner-resolution branch September 6, 2026 09:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fix(controller): owner resolution picks the wrong reference and the wrong Job

1 participant