R-102 phase 1.1: split the recovery-unit path helpers, zero behaviour change
Every unit path helper took (nsRoot, stackName) and joined backups/primary/<stack>/... . That hard-coded 'primary' is the mechanism of R-102: Tier-2 mirrors the whole unit directory to <dest>/backups/secondary/<stack>/recovery-unit/ every night, and because no reader could NAME a unit outside backups/primary/, that mirror has been captured for months and read by nothing. Adds four unit-directory-relative primitives - UnitComposeDir, UnitManifestFile, UnitDBDumpDir, UnitVolumeDumpDir - each taking the recovery-unit DIRECTORY itself. The four existing (nsRoot, stackName) helpers become thin wrappers over them and keep their exact signatures and their exact return values; every current caller compiles untouched. ONE implementation, two callers - the rule restoreDockerVolumesFrom already follows in this repo. TestR102_PathWrappersAreByteIdenticalToToday pins the wrappers against hand-written literals (not re-derived from the helpers under test). Red-proof: UnitComposeDir join changed to 'compose2' -> the test fails on all three fixtures.
This commit is contained in:
@@ -77,25 +77,60 @@ func RecoveryUnitPath(nsRoot, stackName string) string {
|
||||
return filepath.Join(nsRoot, "backups", "primary", stackName)
|
||||
}
|
||||
|
||||
// UNIT-DIRECTORY-RELATIVE HELPERS (R-102). The four below take THE RECOVERY-UNIT DIRECTORY ITSELF
|
||||
// and know only the unit's internal layout. The `(nsRoot, stackName)` helpers that follow are thin
|
||||
// wrappers over them, and every existing caller keeps its exact signature and its exact result.
|
||||
//
|
||||
// They exist because the `(nsRoot, stackName)` form resolves through RecoveryUnitPath, which joins
|
||||
// `backups/primary/<stack>` — a hard-coded `primary` that was the MECHANISM of R-102. Tier-2 mirrors
|
||||
// the whole unit directory to `<dest>/backups/secondary/<stack>/recovery-unit/`, and because every
|
||||
// reader of a unit could only name a `primary` path, that mirror was captured nightly for months and
|
||||
// read by nothing. The unit's INTERNAL layout is identical wherever the directory sits, so the fix is
|
||||
// to let a reader name the directory rather than re-derive it.
|
||||
//
|
||||
// ONE implementation, two callers — the same rule as backup.restoreDockerVolumesFrom. Do not add a
|
||||
// second copy of a join: a duplicated layout constant is how the two sides drift apart.
|
||||
|
||||
// UnitComposeDir returns the compose/config capture dir within a recovery-unit DIRECTORY
|
||||
// (docker-compose.yml + .felhom.yml + app.yaml carrying the portable secret class).
|
||||
func UnitComposeDir(unitDir string) string {
|
||||
return filepath.Join(unitDir, "compose")
|
||||
}
|
||||
|
||||
// UnitManifestFile returns the manifest.json path within a recovery-unit DIRECTORY.
|
||||
func UnitManifestFile(unitDir string) string {
|
||||
return filepath.Join(unitDir, "manifest.json")
|
||||
}
|
||||
|
||||
// UnitDBDumpDir returns the DB dump directory within a recovery-unit DIRECTORY.
|
||||
func UnitDBDumpDir(unitDir string) string {
|
||||
return filepath.Join(unitDir, "db-dumps")
|
||||
}
|
||||
|
||||
// UnitVolumeDumpDir returns the Docker-volume dump-tar directory within a recovery-unit DIRECTORY.
|
||||
func UnitVolumeDumpDir(unitDir string) string {
|
||||
return filepath.Join(unitDir, "volume-dumps")
|
||||
}
|
||||
|
||||
// RecoveryUnitComposePath returns the compose/config capture dir within an app's recovery unit
|
||||
// (docker-compose.yml + .felhom.yml + secret-stripped app.yaml).
|
||||
func RecoveryUnitComposePath(nsRoot, stackName string) string {
|
||||
return filepath.Join(RecoveryUnitPath(nsRoot, stackName), "compose")
|
||||
return UnitComposeDir(RecoveryUnitPath(nsRoot, stackName))
|
||||
}
|
||||
|
||||
// RecoveryUnitManifestPath returns the manifest.json path within an app's recovery unit.
|
||||
func RecoveryUnitManifestPath(nsRoot, stackName string) string {
|
||||
return filepath.Join(RecoveryUnitPath(nsRoot, stackName), "manifest.json")
|
||||
return UnitManifestFile(RecoveryUnitPath(nsRoot, stackName))
|
||||
}
|
||||
|
||||
// AppDBDumpPath returns the DB dump directory for an app under a felhom-data namespace root.
|
||||
func AppDBDumpPath(nsRoot, stackName string) string {
|
||||
return filepath.Join(RecoveryUnitPath(nsRoot, stackName), "db-dumps")
|
||||
return UnitDBDumpDir(RecoveryUnitPath(nsRoot, stackName))
|
||||
}
|
||||
|
||||
// AppVolumeDumpPath returns the Docker-volume dump-tar directory for an app under a namespace root.
|
||||
func AppVolumeDumpPath(nsRoot, stackName string) string {
|
||||
return filepath.Join(RecoveryUnitPath(nsRoot, stackName), "volume-dumps")
|
||||
return UnitVolumeDumpDir(RecoveryUnitPath(nsRoot, stackName))
|
||||
}
|
||||
|
||||
// AppDataDir returns the app data directory under a felhom-data namespace root. The final segment
|
||||
|
||||
Reference in New Issue
Block a user