R-1252 (P2): a rejected or absent backup block never deletes second-drive copies — reconcile only on a valid classification; a rejected block is said on the app's status and once a day to the operator (backup_run_failures); kept copies stay kept (H2); Remove drops the kept records it deleted (H9). Commit only.
gates / gates (push) Successful in 1m18s
gates / gates (push) Successful in 1m18s
This commit is contained in:
@@ -92,6 +92,9 @@ type Metadata struct {
|
||||
// block (sets this back to nil + logs one ERROR) on any validation defect, so a bad catalog push
|
||||
// degrades to legacy loudly rather than partially classifying. Consumed by Task 3/4 — INERT today.
|
||||
Backup *appbackup.BackupSpec `yaml:"backup,omitempty" json:"backup,omitempty"`
|
||||
// BackupRejected (R-1252) is why LoadMetadata rejected the backup block ("" = not rejected). Never read from the
|
||||
// file: the second-drive copy must tell a REJECTED block (keep every copy, alarm) from an absent one.
|
||||
BackupRejected string `yaml:"-" json:"-"`
|
||||
// DataPaths is the customer-facing folder ANNOTATION (R-75): role + Hungarian label over paths
|
||||
// that must ALREADY exist as compose binds. It never declares a path. Validated in LoadMetadata
|
||||
// with the Fork-3 asymmetry — a malformed PATH rejects the whole block, an unknown ROLE drops
|
||||
@@ -551,9 +554,11 @@ func loadMetadata(stackDir string, validateBackup bool) Metadata {
|
||||
if composeErr != nil {
|
||||
log.Printf("[ERROR] [stacks] .felhom.yml backup block rejected in %s: docker-compose.yml unreadable: %v", stackDir, composeErr)
|
||||
meta.Backup = nil
|
||||
meta.BackupRejected = "docker-compose.yml unreadable: " + composeErr.Error()
|
||||
} else if err := appbackup.ValidateBackupSpec(meta.Backup, binds); err != nil {
|
||||
log.Printf("[ERROR] [stacks] .felhom.yml backup block rejected in %s: %v", stackDir, err)
|
||||
meta.Backup = nil
|
||||
meta.BackupRejected = err.Error()
|
||||
}
|
||||
}
|
||||
// data_paths (R-75) rides the same choke point, with its own asymmetric rules: a malformed
|
||||
@@ -597,6 +602,15 @@ func (m *Manager) ClassifiedBinds(name string) ([]appbackup.ClassifiedBind, bool
|
||||
return appbackup.ClassifyBinds(meta.Backup, binds)
|
||||
}
|
||||
|
||||
// BackupBlockRejected (R-1252) is why this app's backup block was rejected, or "" when it is valid or absent.
|
||||
func (m *Manager) BackupBlockRejected(name string) string {
|
||||
stack, ok := m.GetStack(name)
|
||||
if !ok || name == SambaStackName {
|
||||
return ""
|
||||
}
|
||||
return LoadMetadata(filepath.Dir(stack.ComposePath)).BackupRejected
|
||||
}
|
||||
|
||||
// ExcludedDockerVolumes returns the Docker names of the stack's named volumes its template excludes from every app-data backup
|
||||
// (R-49, D21 = B; appbackup.ExcludedDockerVolumes), and a sentence per template entry that was ignored.
|
||||
func (m *Manager) ExcludedDockerVolumes(name string) ([]string, []string) {
|
||||
|
||||
Reference in New Issue
Block a user