38 lines
1.5 KiB
Go
38 lines
1.5 KiB
Go
package backup
|
|
|
|
// R-49, operator ruling D21 = B (2026-10-22): a template may mark a named volume `excluded` (a pure cache the app
|
|
// rebuilds by itself — Immich's machine-learning model cache, 62 % of its off-site copy). Such a volume is never
|
|
// dumped, so it is in no recovery unit: not on the drive's copy, not on the second drive, not off-site. Its last tar
|
|
// is removed by DumpAppVolumes' stale-tar clean-up. A restore then finds no tar for it and leaves the volume as the
|
|
// app makes it (Immich downloads its models again). The rule and its guards: appbackup.ExcludedDockerVolumes.
|
|
|
|
// volumeExclusionProvider is implemented by the production stack adapter (cmd/controller); test fakes need not.
|
|
type volumeExclusionProvider interface {
|
|
GetExcludedDockerVolumes(name string) []string
|
|
}
|
|
|
|
// dumpableVolumes is the stack's named Docker volumes minus the ones its template excludes.
|
|
func (m *Manager) dumpableVolumes(stackName string) []string {
|
|
all := m.stackProvider.GetDockerVolumes(stackName)
|
|
ex, ok := m.stackProvider.(volumeExclusionProvider)
|
|
if !ok || len(all) == 0 {
|
|
return all
|
|
}
|
|
skip := map[string]bool{}
|
|
for _, v := range ex.GetExcludedDockerVolumes(stackName) {
|
|
skip[v] = true
|
|
}
|
|
if len(skip) == 0 {
|
|
return all
|
|
}
|
|
out := make([]string, 0, len(all))
|
|
for _, v := range all {
|
|
if skip[v] {
|
|
m.logger.Printf("[INFO] [backup] Volume %s/%s is excluded by the template (a cache the app rebuilds) — not dumped (R-49)", stackName, v)
|
|
continue
|
|
}
|
|
out = append(out, v)
|
|
}
|
|
return out
|
|
}
|