package dockeragent import ( "context" "strings" "time" "github.com/docker/docker/api/types/container" ) // cleanupOrphanedBackups searches for and removes any Pulse backup containers // (created during updates) that are older than 15 minutes. func (a *Agent) cleanupOrphanedBackups(ctx context.Context) { a.logger.Debug().Msg("Checking for orphaned backup containers") // List all containers (including stopped ones) list, err := a.docker.ContainerList(ctx, container.ListOptions{ All: true, }) if err != nil { a.logger.Warn().Err(err).Msg("Failed to list containers for cleanup") return } for _, c := range list { // Check if it's a backup container // Name format: originalName + "_pulse_backup_" + timestamp isBackup := false for _, name := range c.Names { if strings.Contains(name, "_pulse_backup_") { isBackup = true break } } if !isBackup { continue } // Check age based on the timestamp in the name, not the container's creation date // (Renaming a container does not change its creation date) parts := strings.Split(c.Names[0], "_pulse_backup_") if len(parts) < 2 { continue } timestampStr := parts[len(parts)-1] backupTime, err := time.Parse("20060102_150405", timestampStr) if err != nil { // If we can't parse the timestamp, fall back to creation date as a safety created := time.Unix(c.Created, 0) if time.Since(created) < 15*time.Minute { continue } backupTime = created } if time.Since(backupTime) > 15*time.Minute { a.logger.Info(). Str("container", c.Names[0]). Time("backupTime", backupTime). Msg("Removing orphaned backup container") if err := a.docker.ContainerRemove(ctx, c.ID, container.RemoveOptions{Force: true}); err != nil { a.logger.Warn().Err(err).Str("id", c.ID).Msg("Failed to remove orphaned backup container") } } } }