You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Jobs migration (#223) merged to main in #459 on 2026-08-15. The feature/package-as-jobs branch has been deleted — base this work on main,
which now executes packages as Jobs.
Part of #223. Found by manual validation on 2026-08-12 (93caf2ac, kind v1.36.1, operator run locally), Case 7a of the Jobs validation plan.
What happens
A successful uninstall stage's Job and its pod are deleted the moment the uninstall completes, so the uninstall script's output is unrecoverable. Every other stage's Job and pod are retained until ttlSecondsAfterFinished.
Observed on a CR with two packages — cleanly (uninstall: {enabled: true, apply: true}) and stays (no uninstall block):
# after the uninstall completed:
job/case7-uninstall-stays-1-2-5-apply-… Complete 1/1 102s ← retained
job/case7-uninstall-stays-1-2-5-config-… Complete 1/1 84s ← retained
pod/case7-uninstall-stays-…-apply Completed 102s ← retained
# the cleanly uninstall Job and pod: gone, ~5s after they succeeded
Node state was correct throughout: cleanly|1.2.3 removed, stays|1.2.5 preserved, CR back to complete. The uninstall worked — only its evidence is gone.
An absent entry means "the stage should re-run", which is right for every stage except this one: a successful uninstall's success condition is that the entry is gone. So the sweep reads the completed uninstall as work to redo, and foreground-deletes the Job. Nothing re-runs (uninstall work is driven from node-state entries, and there is no longer one), so the only visible effect is the lost logs.
Scope
Only successful uninstalls. A failed one leaves the entry at erroring, so its Job is retained normally and the logs survive.
No functional impact on the lifecycle: no churn, no stuck stage, node state correct.
It does contradict the migration's stated contract — "finished work is retained instead of deleted on completion", the headline reason for moving to Jobs — for exactly one stage.
Options
Exempt StageUninstall from the absent-entry arm of the rerun predicate, so a processed uninstall Job lives out its success TTL like any other stage. Smallest change; the Job is inert either way.
Have the uninstall completion path leave a tombstone the predicate can read, rather than special-casing the stage.
Accept it and document that uninstall logs are not retained — defensible, since there is no state left to explain, but it should then be said out loud in docs/uninstall.md rather than discovered.
Option 1 unless someone wants the tombstone for other reasons.
Not covered
Whether the same applies to uninstall-interrupt. Untested — it would follow the same predicate, so probably yes.
Note
The Jobs migration (#223) merged to
mainin #459 on 2026-08-15. Thefeature/package-as-jobsbranch has been deleted — base this work onmain,which now executes packages as Jobs.
Part of #223. Found by manual validation on 2026-08-12 (
93caf2ac, kind v1.36.1, operator run locally), Case 7a of the Jobs validation plan.What happens
A successful uninstall stage's Job and its pod are deleted the moment the uninstall completes, so the uninstall script's output is unrecoverable. Every other stage's Job and pod are retained until
ttlSecondsAfterFinished.Observed on a CR with two packages —
cleanly(uninstall: {enabled: true, apply: true}) andstays(no uninstall block):Node state was correct throughout:
cleanly|1.2.3removed,stays|1.2.5preserved, CR back tocomplete. The uninstall worked — only its evidence is gone.Why
shouldDeleteFinishedJob(skyhook_controller.go) ends with:An absent entry means "the stage should re-run", which is right for every stage except this one: a successful uninstall's success condition is that the entry is gone. So the sweep reads the completed uninstall as work to redo, and foreground-deletes the Job. Nothing re-runs (uninstall work is driven from node-state entries, and there is no longer one), so the only visible effect is the lost logs.
Scope
erroring, so its Job is retained normally and the logs survive.Options
StageUninstallfrom the absent-entry arm of the rerun predicate, so a processed uninstall Job lives out its success TTL like any other stage. Smallest change; the Job is inert either way.docs/uninstall.mdrather than discovered.Option 1 unless someone wants the tombstone for other reasons.
Not covered
Whether the same applies to
uninstall-interrupt. Untested — it would follow the same predicate, so probably yes.