feat(directory): LDAP replication status + per-spoke detail on the Multi-Site modal
The modal previously showed zero LDAP replication status -- no ServerID, no MMR active/inactive indicator, nothing -- and only aggregate counts, never per-spoke detail (no-inbound flag, relay note, assigned ldapServerId). An operator had no way to tell whether replication was actually configured/working without SSHing in. Added utils/ldap_replication.js's currentSlapdServerId(), which reads the ACTUAL running ServerID straight from this node's own slapd.conf -- distinct from what GET /ldap-peers / /ldap-replication-config currently ADVERTISE for it, which can genuinely disagree right after a promotion or a new spoke joining (OpenLDAP's static config only reloads at process start). GET /directory-admin/site-status now surfaces both plus a `stale` flag, and a full spokes list (not just a count) with each one's endpoint, LDAP ServerID, and relay path. directory.ejs renders this as an "LDAP Replication (MMR)" status row (ServerID, peer count, a "needs setup.sh re-run" warning when stale) and a Registered Spokes table. Verified two ways: real running containers via docker-compose.multisite-e2e.yml (new site-status assertions), and an actual browser session against the promoted node -- screenshotted the rendered modal showing the real registered spoke with its assigned ldapServerId and the correctly-surfaced "not configured (standalone)" MMR state (this test node never ran site-ldap-register.js against it, so the mismatch itself is the expected, documented behavior).
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
// OpenLDAP multi-master replication (docs/replication.md) config derivation,
|
||||
// shared between routes/api_site.js (the spoke-facing side: assigns a
|
||||
// ServerID at registration, serves GET /api/site/ldap-peers) and
|
||||
@@ -41,4 +43,26 @@ function ldapHostFor(endpoint) {
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { MAX_LDAP_SERVER_ID, nextFreeLdapServerId, ldapHostFor };
|
||||
const SLAPD_CONF_PATH = process.env.SLAPD_CONF_PATH || '/etc/openldap/slapd.conf';
|
||||
|
||||
// The ServerID this node's OpenLDAP is ACTUALLY running with right now, read
|
||||
// straight from slapd.conf (the same file docker-entrypoint.sh writes
|
||||
// `ServerID <n>` into). This can genuinely differ from what
|
||||
// GET /ldap-peers / /ldap-replication-config currently ADVERTISE for this
|
||||
// node -- OpenLDAP's static slapd.conf is only read at process start, so a
|
||||
// promotion or a new spoke joining doesn't retroactively change what's
|
||||
// already running until `setup.sh` restarts the container. Surfaced on the
|
||||
// Multi-Site modal so an operator can see "configured X, but slapd is still
|
||||
// running Y" instead of assuming replication is live because the API says so.
|
||||
function currentSlapdServerId() {
|
||||
let contents;
|
||||
try {
|
||||
contents = fs.readFileSync(SLAPD_CONF_PATH, 'utf8');
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
const m = contents.match(/^ServerID\s+(\d+)/m);
|
||||
return m ? Number(m[1]) : null;
|
||||
}
|
||||
|
||||
module.exports = { MAX_LDAP_SERVER_ID, nextFreeLdapServerId, ldapHostFor, currentSlapdServerId };
|
||||
|
||||
Reference in New Issue
Block a user