Context
Follow-up to #439, which tracked the schema-upgrade e2e gaps left open by #426.
#443 landed the test-only gaps that needed no operator change (schemaVersion: "auto", rollback within the safe window, multi-instance/HA rollout ordering, unpullable documentDBVersion). The remaining gaps from #439 were explicitly deferred because they all depend on one unmade decision: the operator has no update-path validation at all today. It runs a blanket ALTER EXTENSION documentdb UPDATE and relies entirely on PostgreSQL to resolve the path. Writing e2e tests for the failure modes first would just pin in whatever behavior falls out of that, so the contract needs to be ratified before the tests are meaningful.
This issue carries the design decision plus the work and tests that follow from it. Full write-up in this comment on #439.
Decision needed from maintainers
- Confirm multi-minor jumps are a supported path, not rejected. The
documentdb extension ships minors roughly monthly, at times bi-weekly. A user upgrading quarterly is already 3+ minors behind; twice-a-year is 6+. Adjacent-only (N → N+1) upgrades would mean 3–12 sequential rolling restarts to catch up, which in practice pushes users to never upgrade.
- Confirm the fail-fast contract: block + surface a status condition when no update path exists, rather than firing
ALTER EXTENSION and surfacing the raw PG error.
- Confirm placement: controller only, or also a static check in the validating webhook. The path check needs DB connectivity, so the controller (which already holds a SQL executor and cluster handle) is the pragmatic home; only cheap static parts could move to the webhook.
The risk being managed
A jump only works if the extension ships a continuous chain of documentdb--A--B.sql update scripts. If any release omits its script, ALTER EXTENSION UPDATE fails at execution time with a raw PG error (extension has no update path from X to Y), re-fires every reconcile, and the user gets a cryptic failure with no actionable status.
Proposed implementation
PostgreSQL exposes the update-path graph read-only:
SELECT path FROM pg_extension_update_paths('documentdb')
WHERE source = '0.109-0' AND target = '0.113-0';
- Path resolvable → non-NULL arrow-joined sequence.
- No path →
path IS NULL → fail-fast signal.
Hook this into documentdb_controller.go immediately before the SQLExecutor(... updateSQL) call. If no path exists: skip ALTER EXTENSION, emit a Warning event plus a SchemaUpgradeBlocked status condition (reason NoUpdatePath) naming the exact gap, and return cleanly without a crash-loop.
|
Today |
With preflight |
| When failure is learned |
After firing ALTER EXTENSION |
Before touching schema |
| Error quality |
Raw PG error in logs |
Actionable status condition + event |
| Visibility |
Operator logs only |
status.conditions on the CR |
| Loop behavior |
Errors every reconcile |
Clean stop |
Scope
Acceptance
The preflight is implemented and the three deferred e2e gaps from #439 are covered with appropriate labels/levels, or re-deferred with a documented rationale.
Follow-up to #439. Original coverage work in #426 and #443.
Context
Follow-up to #439, which tracked the schema-upgrade e2e gaps left open by #426.
#443 landed the test-only gaps that needed no operator change (
schemaVersion: "auto", rollback within the safe window, multi-instance/HA rollout ordering, unpullabledocumentDBVersion). The remaining gaps from #439 were explicitly deferred because they all depend on one unmade decision: the operator has no update-path validation at all today. It runs a blanketALTER EXTENSION documentdb UPDATEand relies entirely on PostgreSQL to resolve the path. Writing e2e tests for the failure modes first would just pin in whatever behavior falls out of that, so the contract needs to be ratified before the tests are meaningful.This issue carries the design decision plus the work and tests that follow from it. Full write-up in this comment on #439.
Decision needed from maintainers
documentdbextension ships minors roughly monthly, at times bi-weekly. A user upgrading quarterly is already 3+ minors behind; twice-a-year is 6+. Adjacent-only (N → N+1) upgrades would mean 3–12 sequential rolling restarts to catch up, which in practice pushes users to never upgrade.ALTER EXTENSIONand surfacing the raw PG error.The risk being managed
A jump only works if the extension ships a continuous chain of
documentdb--A--B.sqlupdate scripts. If any release omits its script,ALTER EXTENSION UPDATEfails at execution time with a raw PG error (extension has no update path from X to Y), re-fires every reconcile, and the user gets a cryptic failure with no actionable status.Proposed implementation
PostgreSQL exposes the update-path graph read-only:
path IS NULL→ fail-fast signal.Hook this into
documentdb_controller.goimmediately before theSQLExecutor(... updateSQL)call. If no path exists: skipALTER EXTENSION, emit aWarningevent plus aSchemaUpgradeBlockedstatus condition (reasonNoUpdatePath) naming the exact gap, and return cleanly without a crash-loop.ALTER EXTENSIONstatus.conditionson the CRScope
pg_extension_update_pathspreflight indocumentdb_controller.go, with theSchemaUpgradeBlocked/NoUpdatePathcondition and warning event.ALTER EXTENSION UPDATEfails) — deferred from e2e: expand schema-upgrade coverage — gaps not covered by #426 #439. With the preflight in place this is reachable deterministically via a broken/absent update path; assert the operator surfaces the condition, does not corrupt data, and does not crash-loop.Acceptance
The preflight is implemented and the three deferred e2e gaps from #439 are covered with appropriate labels/levels, or re-deferred with a documented rationale.
Follow-up to #439. Original coverage work in #426 and #443.