Fix two preflight defects a live production rehearsal found
Ran the rehearsal read-only against a live production instance. It completed, and two preflight checks were wrong in ways a test instance could not have shown. 1. Store-backend detection missed the config entirely. A config generated by `stalwart --init` declares `type = "rocksdb"` inside a `[store.rocksdb]` section, which is what every test fixture here used. The production config has no section headers at all and declares `store.rocksdb.type = "rocksdb"` flat. Detection only matched a bare `type` key, so it reported "no known store backend type found in config" and left topology.store_backend empty. That mattered more than a warning suggests: backup.Run treated an unrecognized backend as a *skip*, so a real run would have continued with no filesystem or database backup at all - the single artifact that phase exists to produce, quietly absent. Flat dotted keys are now detected, and an unrecognized backend is a hard failure rather than a skip. 2. The cluster warning didn't say where it matched. It fires on any occurrence of "cluster" anywhere in the config, which is the correct bias - a missed cluster corrupts a shared store - but on the production config the only match was inside the value of an unrelated setting, leaving a whole config to search to establish that. It now names the location and distinguishes a match in the setting name from one in its value. Both verified against the real config: store-backend now reports "rocksdb (store.rocksdb)", and the cluster warning names the setting, making a false positive dismissible at a glance. No production data is in this commit: the fixtures use example.com and the flat-key shape only. Coverage numbers from that run matched the earlier scrubbed-corpus measurement exactly.
This commit is contained in:
@@ -67,8 +67,25 @@ func scanTOMLBackends(data []byte) ([]BackendMatch, error) {
|
||||
}
|
||||
if m := tomlKVRe.FindStringSubmatch(line); m != nil {
|
||||
key, value := m[1], strings.ToLower(m[2])
|
||||
if key == "type" && knownBackends[value] {
|
||||
if !knownBackends[value] {
|
||||
continue
|
||||
}
|
||||
// Two spellings, both real. A config written with sections
|
||||
// declares `type = "rocksdb"` under `[store.rocksdb]`; one
|
||||
// written flat declares `store.rocksdb.type = "rocksdb"` with
|
||||
// no sections at all. A real production instance uses the
|
||||
// second form exclusively - checking only for a bare `type`
|
||||
// key found nothing there, and an undetected backend makes the
|
||||
// backup phase skip the filesystem snapshot entirely.
|
||||
switch {
|
||||
case key == "type":
|
||||
matches = append(matches, BackendMatch{Path: section, Backend: value})
|
||||
case strings.HasSuffix(key, ".type"):
|
||||
path := strings.TrimSuffix(key, ".type")
|
||||
if section != "" {
|
||||
path = section + "." + path
|
||||
}
|
||||
matches = append(matches, BackendMatch{Path: path, Backend: value})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user