Skip to content

feat: Make Ready the summary of every other condition - #74

Merged
as51340 merged 1 commit into
mainfrom
feat/ready-summary-condition
Oct 14, 2026
Merged

as51340 merged 1 commit into
mainfrom
feat/ready-summary-condition

Conversation

@as51340

@as51340 as51340 commented Oct 14, 2026

Copy link
Copy Markdown
Contributor

Why

Ready was True as soon as a MAIN was elected, so it stayed True through a roll, a scale-down, a resize or a rejected license. For a custom resource, kstatus (sigs.k8s.io/cli-utils, which Flux health checks use) checks observedGeneration, then Reconciling/Stalled, then Ready, and treats everything else as Current. We set neither of the first two, so a GitOps step waiting on a MemgraphCluster passed while the operator was still working. Strimzi's and CloudNativePG's Ready mean "reconciled and healthy". This change makes ours mean that too, keeping four condition types.

What

Ready is now the summary:

Ready When
True / Reconciled A MAIN is serving behind a reachable leader, and LicenseApplied, Converged and Updated are all True for the current generation
False / the serving reason The cluster doesn't serve: NoMainElected, WorkloadsNotReady, CoordinatorUnreachable, NoCoordinatorLeader, ApplyFailed (same reasons as before)
False / borrowed reason It serves, but the first of LicenseApplied → Converged → Updated that isn't True supplies the reason, with a message such as Converged: Retiring data instance instance_2
Unknown / Reconciling One of those is True only for an older generation, or hasn't been decided yet
  • The serving verdict is pass-local. It's recorded where Ready used to be set (servingOrNot, notServingCondition) under an internal Serving type. summarizeReady folds it into Ready at the end of Reconcile and removes it, so it never reaches the API. A pass that ends before observing the cluster (a deferred shrink, a StatefulSet being recreated) keeps a not-serving Ready as it was.
  • status.main still names the serving MAIN throughout, so "serving but not done" stays visible without a fifth condition.
  • API: ReasonReconciled added; ReasonMainElected removed (it only described the serving verdict now). The CRD schema is unchanged, so no chart bump.
  • Docs: README (READY column, and the quickstart now waits on Ready), docs/external-access.md, docs/flags.md, docs/monitoring.md, and a CLAUDE.md conventions bullet.

Behavior change: anyone treating Ready=True as "a MAIN is up" should read status.main instead. It's acceptable on v1alpha1, but it's a change.

Testing

  • Pure specs for readyCondition: all-True, not serving beats everything, license → membership → roll precedence, a stale True gives Unknown, and the no-observation fallback both ways.
  • Envtest: the ten specs that asserted "Ready stays True while X" now assert a MAIN still serves and Ready=False with X's reason (expectServingButNotReady). The bootstrap spec expects Ready=True/Reconciled.
  • The suite now creates the default license Secret every cluster reads, as a README install has. Without it LicenseApplied is pending and Ready could never be True. License specs use Secrets of their own.
  • make test, make lint, make chart-verify. The e2e suite only reads pod readiness, so it's unaffected.

Ready was True as soon as a MAIN was elected, so it stayed True through a
roll, a scale-down, a resize or a rejected license. kstatus, and with it Flux
health checks, decides on Ready alone for a custom resource, so a GitOps step
waiting on a MemgraphCluster passed while the operator was still working.

Ready is now True only when the cluster serves (a MAIN behind a reachable
coordinator leader) and LicenseApplied, Converged and Updated are all True
for the current generation. Otherwise it carries the reason of the first
thing that is not, in that order: not serving (NoMainElected,
WorkloadsNotReady, CoordinatorUnreachable, NoCoordinatorLeader, ApplyFailed),
then the license, membership, and the roll, its message naming the condition
the reason came from. A True decided for an older generation makes it
Unknown/Reconciling. The new True reason is Reconciled; MainElected is gone
from the API.

Whether the cluster serves is now a pass-local verdict, recorded where Ready
used to be set and folded into Ready by summarizeReady at the end of
Reconcile, so it never reaches the API. A pass that ends before it observes
the cluster keeps a not-serving Ready. status.main still says a MAIN is
serving throughout.

The envtest suite now creates the default license Secret every cluster reads,
as an install following the README has, since without it LicenseApplied is
pending and Ready can never be True. The quickstart waits on Ready.
@as51340 as51340 self-assigned this Oct 14, 2026
@as51340
as51340 merged commit 3789e50 into main Oct 14, 2026
6 checks passed
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.

1 participant