postgresql
PostgreSQL: an application controller type, version 1. A controller of this type is written under controllers.application with type: postgresql.
Its connectivity test identifies the system it reaches by postgres:<system identifier>@<host>:<port>: the system identifier names the cluster, which a primary and its standbys share, so that a second controller for the same system is warned of.
Connection
In the controller’s connection:
host(string, required): the server’s name or address, reached over SQL from the site’s orchestratorsport(int, default5432): the server’s portdatabase(string, defaultpostgres): the database qfence’s own connection uses for what concerns the whole server: replication state, settings, the list of databasesserver_certificate_sha256(string): the SHA-256 fingerprint of the certificate the server presents, pinned at registration: the connectivity test shows it until it is set. TLS is requirednext_server_certificate_sha256(string): the SHA-256 fingerprint of the certificate that will replace the pinned one, trusted as it is: pin it before the server changes certificates, so the change leaves no gapcluster_manager(string, defaultnone, one ofnone,patroni,repmgr): the cluster manager that runs this server, if any. Where one runs, qfence only observes: it never fences or promotes a server a manager would undo or race (ADR 0013 §5)connect_timeout(duration, default10s): how long connecting and the TLS handshake may take; each call is bounded by its own deadlinemax_connections(int, default2): connections qfence keeps open to each database it uses; more calls wait within their deadline
Auth methods
The controller’s auth.method is one of these. A field marked secret comes only from the secret auth.credentials_ref names; the others are set in auth.config, or in that secret.
basic
A role and its password, sent only over the pinned TLS connection. The role is never superuser (ADR 0013 §7).
username(string, required): the role qfence logs in as, e.g. qfencepassword(string, required, secret)
mtls
A role and the client certificate it logs in with (pg_hba.conf method cert). The role is never superuser (ADR 0013 §7).
username(string, required): the role qfence logs in as, e.g. qfencetls_cert(pem, required, secret)tls_key(pem, required, secret)
Capabilities
The controller enables each it uses in its capabilities list.
db.health
Run the binding’s query in a read-only transaction in the database: HEALTHY when it succeeds, and at the owner site only on a writable primary; UNHEALTHY when the server refuses or fails it, or at the owner is read-only or in recovery; UNKNOWN when the server does not answer.
Category: observation; bound as health; resource database.
Per binding, in its params:
query(string, defaultselect 1): one SQL statement, run in a read-only transaction: it passes when it runs without an error
Validation checks: tls.pinned, privileges.
replica.lag
Ready while the server is a standby and its lag, counted from what the primary last reported, is within max_replication_lag. Once the primary is gone the lag keeps growing from its last message: the bound on what a promotion could lose. Lag that cannot be read is not ready. The binding’s database only names the server.
Category: observation; bound as readiness; resource database.
Per binding, in its params:
max_replication_lag(duration, required): the most lag that still allows promotion, e.g. 30s
Validation checks: tls.pinned, privileges, rewind-ready, same-cluster, wal-receiver-timeout.
db.readonly
Make the server refuse writes: default_transaction_read_only on in its configuration (ALTER SYSTEM, then a reload), and every application session ended. FENCED while that holds and no application session holds a transaction ID; it survives a restart. Unfence resets it. Soft: a session can still BEGIN READ WRITE until the server stops, so it never proves a site. Withdrawn where a cluster manager runs. The binding’s database only names the server.
Category: actuator; bound as fence; fencing level application; resource database.
Validation checks: tls.pinned, privileges, no-cluster-manager.
db.promote
Promote the standby with pg_promote, waiting for it, then reset any read-only setting it inherited. Refused unless its lag, measured as replica.lag measures it, is within max_replication_lag or the data loss an operator accepted for this failover; a server already promoted reports success. Withdrawn where a cluster manager runs. The binding’s database only names the server.
Category: actuator; bound as switchover; resource database.
Per binding, in its params:
max_replication_lag(duration, required): the most lag that still allows promotion, as for replica.lag, e.g. 30s
Strategies, which a binding picks with its strategy param:
graceful: make the old primary read-only and verify it, wait until this standby has replayed every byte of its WAL, then fence it and promote: no committed transaction is lostfence-then-promote: fence the old primary and promote, as a failover does
Validation checks: tls.pinned, privileges, no-cluster-manager.
databases.list
The server’s databases that accept connections, by name, with their owner.
Category: discovery; resource database.
Validation checks: tls.pinned.
Addresses
Every address the type contacts. A secret’s scope (-scope-host) is checked against each that receives credentials.
connection.host(portconnection.port, receives credentials): the server, over SQL