add assigned_central_version column to controllers_ctl

Allow controllers to advertise which central version (cv1, cv2, or all)
they are assigned to handle via a new configurable field. The value is
persisted to the database on each heartbeat and validated at startup
against the DB CHECK constraint.
This commit is contained in:
Grant Limberg 2026-03-17 16:30:25 -07:00
parent a840b94e0d
commit 2c57f85e25
6 changed files with 22 additions and 4 deletions

View file

@ -0,0 +1 @@
ALTER TABLE controllers_ctl DROP COLUMN IF EXISTS assigned_central_version;

View file

@ -0,0 +1 @@
ALTER TABLE controllers_ctl ADD COLUMN IF NOT EXISTS assigned_central_version text DEFAULT 'all' NOT NULL CONSTRAINT controllers_ctl_assigned_central_version_check CHECK (assigned_central_version IN ('cv1', 'cv2', 'all'));

View file

@ -63,6 +63,7 @@ CentralDB::CentralDB(
, _listenerMode(listenMode)
, _statusWriterMode(statusMode)
, _cc(cc)
, _assignedCentralVersion(cc->assignedCentralVersion)
, _pool()
, _myId(myId)
, _myAddress(myId.address())
@ -1130,12 +1131,13 @@ void CentralDB::heartbeat()
try {
pqxx::work w { *c->c };
w.exec(
"INSERT INTO controllers_ctl (id, hostname, last_heartbeat, public_identity, version) VALUES "
"($1, $2, TO_TIMESTAMP($3::double precision/1000), $4, $5) "
"INSERT INTO controllers_ctl (id, hostname, last_heartbeat, public_identity, version, assigned_central_version) VALUES "
"($1, $2, TO_TIMESTAMP($3::double precision/1000), $4, $5, $6) "
"ON CONFLICT (id) DO UPDATE SET hostname = EXCLUDED.hostname, last_heartbeat = "
"EXCLUDED.last_heartbeat, "
"public_identity = EXCLUDED.public_identity, version = EXCLUDED.version",
pqxx::params { controllerId, hostname, ts, publicIdentity, versionStr })
"public_identity = EXCLUDED.public_identity, version = EXCLUDED.version, "
"assigned_central_version = EXCLUDED.assigned_central_version",
pqxx::params { controllerId, hostname, ts, publicIdentity, versionStr, _assignedCentralVersion })
.no_rows();
w.commit();
}

View file

@ -106,6 +106,7 @@ class CentralDB : public DB {
ListenerMode _listenerMode;
StatusWriterMode _statusWriterMode;
const ControllerConfig* _cc;
std::string _assignedCentralVersion;
std::shared_ptr<ConnectionPool<PostgresConnection> > _pool;
const Identity _myId;

View file

@ -27,6 +27,7 @@ struct ControllerConfig {
bool ssoEnabled;
std::string listenMode;
std::string statusMode;
std::string assignedCentralVersion;
RedisConfig* redisConfig;
PubSubConfig* pubSubConfig;
BigTableConfig* bigTableConfig;
@ -35,6 +36,7 @@ struct ControllerConfig {
: ssoEnabled(false)
, listenMode("")
, statusMode("")
, assignedCentralVersion("all")
, redisConfig(nullptr)
, pubSubConfig(nullptr)
, bigTableConfig(nullptr)

View file

@ -1813,6 +1813,17 @@ class OneServiceImpl : public OneService {
if (cc.is_object()) {
_controllerConfig.listenMode = OSUtils::jsonString(cc["listenMode"], "pgsql");
_controllerConfig.statusMode = OSUtils::jsonString(cc["statusMode"], "pgsql");
// Valid values must match CHECK constraint in migration 0007_assigned_version
{
const std::string av = OSUtils::jsonString(cc["assignedCentralVersion"], "all");
if (av != "cv1" && av != "cv2" && av != "all") {
fprintf(
stderr,
"ERROR: assignedCentralVersion must be one of 'cv1', 'cv2', or 'all'" ZT_EOL_S);
exit(1);
}
_controllerConfig.assignedCentralVersion = av;
}
// redis settings
if (cc["redis"].is_object() && _rc == NULL) {