0b9450e356
The restore paths (RestoreFromRecoveryUnit + the RestoreApp fallback) repopulated Docker volume tars but NEVER replayed the captured <stack>-<dbtype>.sql dump, so DB-resident data (e.g. rows in a DB whose data dir is a bind mount) did not come back — the romm marker round-trip in the audit lost the row. New appbackup.ImportDump (read-side counterpart to DumpOne) replays a .sql/.sql.gz into the running DB using the live container's OWN discovered credentials (no env threading; reuses DiscoveredDB + getMariaDBPassword). backup.reimportDBDumps orchestrates it AFTER volume restore + stack bring-up, so the logical dump WINS over any volume-tar copy of the DB (operator-chosen precedence). pg_dump --clean --if-exists and mariadb-dump (default --add-drop-table) make replay idempotent; psql ON_ERROR_STOP=1 surfaces real import errors. Also: volume-restore per-volume failures and DB-import failures now SURFACE (the restore returns an error) instead of a swallowed WARN, so a failed data restore cannot read as success. Tests (restore_db_test.go, injectable discover/import seams): imports when dump+DB present, failure surfaces, no-dump skips discovery, dump-but-no-matching-DB is a non-fatal skip. Live DB round-trip to be validated post-deploy.
135 lines
4.4 KiB
Go
135 lines
4.4 KiB
Go
package backup
|
|
|
|
// This file bridges the backup package to internal/appbackup, where the
|
|
// self-contained app-data backup primitives (DB dump, Docker-volume archive
|
|
// discovery, keep-side path helpers) now live. The backup package keeps these
|
|
// names available — via type/const aliases and thin function forwarders — so
|
|
// the (still present) delete-side code and the both-side consumers (web, api,
|
|
// report) compile unchanged. Behaviour is identical: the forwarders call
|
|
// straight through to appbackup.
|
|
//
|
|
// Go has no function aliasing, so the functions are one-line forwarders while
|
|
// the types/consts use real aliases.
|
|
|
|
import (
|
|
"context"
|
|
"log"
|
|
|
|
"gitea.dooplex.hu/admin/felhom-controller/internal/appbackup"
|
|
)
|
|
|
|
// --- type aliases (appdata) ---
|
|
|
|
type StackDataProvider = appbackup.StackDataProvider
|
|
type StackSummary = appbackup.StackSummary
|
|
type AppBackupInfo = appbackup.AppBackupInfo
|
|
type AppDataPath = appbackup.AppDataPath
|
|
type AppDockerVolume = appbackup.AppDockerVolume
|
|
type RecoveryInfo = appbackup.RecoveryInfo
|
|
|
|
// --- type aliases (dbdump) ---
|
|
|
|
type DBType = appbackup.DBType
|
|
type DiscoveredDB = appbackup.DiscoveredDB
|
|
type DumpResult = appbackup.DumpResult
|
|
type DumpValidation = appbackup.DumpValidation
|
|
type DumpFileInfo = appbackup.DumpFileInfo
|
|
|
|
// --- const aliases ---
|
|
|
|
const (
|
|
DBTypePostgres = appbackup.DBTypePostgres
|
|
DBTypeMariaDB = appbackup.DBTypeMariaDB
|
|
)
|
|
|
|
// FelhomDataDir is the namespace directory on storage drives for all felhom-managed data.
|
|
const FelhomDataDir = appbackup.FelhomDataDir
|
|
|
|
// --- function forwarders (dbdump) ---
|
|
|
|
func DiscoverDatabases(ctx context.Context, logger *log.Logger, debug bool) ([]DiscoveredDB, error) {
|
|
return appbackup.DiscoverDatabases(ctx, logger, debug)
|
|
}
|
|
|
|
func DumpAll(ctx context.Context, dbs []DiscoveredDB, dumpDir string, logger *log.Logger, debug bool) []DumpResult {
|
|
return appbackup.DumpAll(ctx, dbs, dumpDir, logger, debug)
|
|
}
|
|
|
|
func DumpOne(ctx context.Context, db DiscoveredDB, dumpDir string, logger *log.Logger, debug bool) DumpResult {
|
|
return appbackup.DumpOne(ctx, db, dumpDir, logger, debug)
|
|
}
|
|
|
|
// ImportDump replays a captured .sql dump back into a running DB container (F17 restore path).
|
|
func ImportDump(ctx context.Context, db DiscoveredDB, dumpPath string, logger *log.Logger, debug bool) error {
|
|
return appbackup.ImportDump(ctx, db, dumpPath, logger, debug)
|
|
}
|
|
|
|
func ValidateDump(filePath string, dbType DBType) DumpValidation {
|
|
return appbackup.ValidateDump(filePath, dbType)
|
|
}
|
|
|
|
func ListDumpFiles(dumpDir string) ([]DumpFileInfo, error) {
|
|
return appbackup.ListDumpFiles(dumpDir)
|
|
}
|
|
|
|
// --- function forwarders (appdata) ---
|
|
|
|
func DiscoverAppData(provider StackDataProvider, discoveredDBs []DiscoveredDB) []AppBackupInfo {
|
|
return appbackup.DiscoverAppData(provider, discoveredDBs)
|
|
}
|
|
|
|
func ParseComposeNamedVolumes(composePath string) []AppDockerVolume {
|
|
return appbackup.ParseComposeNamedVolumes(composePath)
|
|
}
|
|
|
|
func ResolveDockerVolumeNames(composePath string) []string {
|
|
return appbackup.ResolveDockerVolumeNames(composePath)
|
|
}
|
|
|
|
func ParseComposeImages(composePath string) []string {
|
|
return appbackup.ParseComposeImages(composePath)
|
|
}
|
|
|
|
// humanizeBytes forwards to appbackup.HumanizeBytes; kept unexported so the
|
|
// many in-package call sites (backup.go, crossdrive.go, restore code) need no edit.
|
|
func humanizeBytes(b int64) string {
|
|
return appbackup.HumanizeBytes(b)
|
|
}
|
|
|
|
// --- function forwarders (paths) ---
|
|
//
|
|
// NOTE: the path helpers below take a felhom-data NAMESPACE ROOT, not a bare drive path. Use
|
|
// NamespaceRoot (or Manager.namespaceRoot / Manager.AppNamespaceRoot) to resolve the root first.
|
|
|
|
func NamespaceRoot(drivePath string, inGuestDrive bool) string {
|
|
return appbackup.NamespaceRoot(drivePath, inGuestDrive)
|
|
}
|
|
|
|
func PrimaryBackupPath(nsRoot string) string {
|
|
return appbackup.PrimaryBackupPath(nsRoot)
|
|
}
|
|
|
|
func AppDBDumpPath(nsRoot, stackName string) string {
|
|
return appbackup.AppDBDumpPath(nsRoot, stackName)
|
|
}
|
|
|
|
func AppVolumeDumpPath(nsRoot, stackName string) string {
|
|
return appbackup.AppVolumeDumpPath(nsRoot, stackName)
|
|
}
|
|
|
|
func RecoveryUnitPath(nsRoot, stackName string) string {
|
|
return appbackup.RecoveryUnitPath(nsRoot, stackName)
|
|
}
|
|
|
|
func RecoveryUnitComposePath(nsRoot, stackName string) string {
|
|
return appbackup.RecoveryUnitComposePath(nsRoot, stackName)
|
|
}
|
|
|
|
func RecoveryUnitManifestPath(nsRoot, stackName string) string {
|
|
return appbackup.RecoveryUnitManifestPath(nsRoot, stackName)
|
|
}
|
|
|
|
func AppDataDir(nsRoot, stackName string) string {
|
|
return appbackup.AppDataDir(nsRoot, stackName)
|
|
}
|