Controllers: shared reconcile base, Ready=False on returned errors, parent watches #10

Open
opened 2026-10-09 12:43:03 +00:00 by niklas · 0 comments
Owner

Remaining consistency items from the Oct 2026 review (three controllers now, so this is smaller than it was):

  • setNotReady exists once per controller (setNotReady, setTeamNotReady, setNotReady in the alert source), plus the same Get/NotFound prologue, finalizer add, and if r.Recorder != nil guard. Extract a shared helper or a generic reconciler.
  • A transient failure returns (ctrl.Result{}, err) and leaves Ready at its previous value, so a CR can look healthy while it is failing (HTTP errors, Secret read/write). One wrapper should set Ready=False with an Error reason on any returned error.
  • Expected-outcome carriers databaseError, teamError, childError do the same job: unify.
  • TerdutAlertSource still polls its team every 15s (WaitingForTeam); TerdutTeam already watches its TerdutServer. Add a mapper watch on TerdutTeam.
  • Success reason is Adopted on all three kinds, though nothing is adopted any more: rename to Reconciled.
  • status.observedGeneration is written but read only by tests; set ObservedGeneration on each metav1.Condition instead and drop the field.
  • ReasonTeamAdopted/ReasonChildAdopted/ReasonAdopted collapse into one.
  • Credentials never rotate on a schedule: rotation is "delete the Secret". Decide whether that is enough and say so in DESIGN.md §6, or add a rotation annotation.
  • The duration CRD pattern is shared by two fields; keep them in sync via a shared constant.
Remaining consistency items from the Oct 2026 review (three controllers now, so this is smaller than it was): - `setNotReady` exists once per controller (`setNotReady`, `setTeamNotReady`, `setNotReady` in the alert source), plus the same Get/NotFound prologue, finalizer add, and `if r.Recorder != nil` guard. Extract a shared helper or a generic reconciler. - A transient failure returns `(ctrl.Result{}, err)` and leaves `Ready` at its previous value, so a CR can look healthy while it is failing (HTTP errors, Secret read/write). One wrapper should set `Ready=False` with an `Error` reason on any returned error. - Expected-outcome carriers `databaseError`, `teamError`, `childError` do the same job: unify. - `TerdutAlertSource` still polls its team every 15s (`WaitingForTeam`); `TerdutTeam` already watches its `TerdutServer`. Add a mapper watch on `TerdutTeam`. - Success reason is `Adopted` on all three kinds, though nothing is adopted any more: rename to `Reconciled`. - `status.observedGeneration` is written but read only by tests; set `ObservedGeneration` on each `metav1.Condition` instead and drop the field. - `ReasonTeamAdopted`/`ReasonChildAdopted`/`ReasonAdopted` collapse into one. - Credentials never rotate on a schedule: rotation is "delete the Secret". Decide whether that is enough and say so in DESIGN.md §6, or add a rotation annotation. - The duration CRD pattern is shared by two fields; keep them in sync via a shared constant.
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: niklas/terdut-operator#10