From 29f8a078bcd663fff9e5e4393be1b1c141dd89a2 Mon Sep 17 00:00:00 2001 From: Frederik Ring Date: Sun, 22 Aug 2021 14:00:21 +0200 Subject: [PATCH] implement deletion of local backups --- src/main.go | 38 +++++++++++++++++++++++++++++++-- test/compose/docker-compose.yml | 5 ++--- 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/main.go b/src/main.go index 93064d6..dfc68a6 100644 --- a/src/main.go +++ b/src/main.go @@ -8,6 +8,8 @@ import ( "os" "os/exec" "path" + "path/filepath" + "strconv" "strings" "time" @@ -134,7 +136,6 @@ func (s *script) stopContainers() error { fmt.Printf("Stopping %d out of %d running containers\n", len(containersToStop), len(allContainers)) if len(containersToStop) != 0 { - fmt.Println("Stopping containers") for _, container := range s.stoppedContainers { if err := s.cli.ContainerStop(s.ctx, container.ID, nil); err != nil { return fmt.Errorf("stopContainers: error stopping container %s: %w", container.Names[0], err) @@ -241,16 +242,49 @@ func (s *script) pruneOldBackups() error { if retention == "" { return nil } - + retentionDays, err := strconv.Atoi(retention) + if err != nil { + return fmt.Errorf("pruneOldBackups: error parsing BACKUP_RETENTION_DAYS as int: %w", err) + } sleepFor, err := time.ParseDuration(os.Getenv("BACKUP_PRUNING_LEEWAY")) if err != nil { return fmt.Errorf("pruneBackups: error parsing given leeway value: %w", err) } time.Sleep(sleepFor) + deadline := time.Now().AddDate(0, 0, -retentionDays) + if bucket := os.Getenv("AWS_S3_BUCKET_NAME"); bucket != "" { } if archive := os.Getenv("BACKUP_ARCHIVE"); archive != "" { + matches, err := filepath.Glob( + path.Join(archive, fmt.Sprintf("%s%s", os.Getenv("BACKUP_PRUNING_PREFIX"), "*")), + ) + if err != nil { + return fmt.Errorf("pruneOldBackups: error looking up matching files: %w", err) + } + + var candidates []os.FileInfo + for _, match := range matches { + fi, err := os.Stat(match) + if err != nil { + return fmt.Errorf("pruneOldBackups: error calling stat on file %s: %w", match, err) + } + + if fi.ModTime().Before(deadline) { + candidates = append(candidates, fi) + } + } + + if len(candidates) != len(matches) { + for _, candidate := range candidates { + if err := os.Remove(candidate.Name()); err != nil { + return fmt.Errorf("pruneOldBackups: error deleting file %s: %w", candidate.Name(), err) + } + } + } else if len(matches) != 0 { + fmt.Println("Refusing to delete all backups. Check your configuration.") + } } return nil } diff --git a/test/compose/docker-compose.yml b/test/compose/docker-compose.yml index c62747e..8d50737 100644 --- a/test/compose/docker-compose.yml +++ b/test/compose/docker-compose.yml @@ -23,12 +23,11 @@ services: AWS_ENDPOINT: minio:9000 AWS_ENDPOINT_PROTO: http AWS_S3_BUCKET_NAME: backup - BACKUP_FILENAME: test.tar.gz + # BACKUP_FILENAME: test.tar.gz BACKUP_CRON_EXPRESSION: 0 0 5 31 2 ? BACKUP_RETENTION_DAYS: ${BACKUP_RETENTION_DAYS:-7} - BACKUP_FORCE_PRUNE: ${BACKUP_FORCE_PRUNE:-} BACKUP_PRUNING_LEEWAY: 5s - BACKUP_PRUNING_PREFIX: test + # BACKUP_PRUNING_PREFIX: test volumes: - ./local:/archive - app_data:/backup/app_data:ro