backup: Prune old backups

This commit updates the backup command to prune old backups.
This commit is contained in:
Tom Wiesing 2022-09-08 14:31:51 +02:00
parent 437f499fb4
commit 4bffc9e92a
No known key found for this signature in database
3 changed files with 52 additions and 1 deletions

View file

@ -15,6 +15,7 @@ import (
var Backup wisski_distillery.Command = backup{}
type backup struct {
NoPrune bool `short:"no" long:"no-prune" description:"Do not prune older backup archives"`
StagingOnly bool `short:"s" long:"staging-only" description:"Do not package into a backup archive, but only create a staging directory"`
Positionals struct {
Dest string `positional-arg-name:"DEST" description:"Destination path to write backup archive to. Defaults to the snapshots/archives/ directory"`
@ -40,6 +41,12 @@ func (bk backup) Run(context wisski_distillery.Context) error {
dis := context.Environment
var err error
if !bk.NoPrune {
defer logging.LogOperation(func() error {
return dis.PruneBackups(context.IOStream)
}, context.IOStream, "Pruning old backups")
}
// determine the target path for the archive
var sPath string
if !bk.StagingOnly {

44
env/backup.go vendored
View file

@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"sync"
"time"
"github.com/FAU-CDI/wisski-distillery/internal/fsx"
"github.com/FAU-CDI/wisski-distillery/internal/logging"
@ -187,3 +188,46 @@ func (backup Backup) WriteReport(io stream.IOStream) error {
return err
}, io, "Writing backup report")
}
// ShouldPrune determines if a file with the provided modtime
func (dis *Distillery) ShouldPrune(modtime time.Time) bool {
return time.Since(modtime) > time.Duration(dis.Config.MaxBackupAge)*24*time.Hour
}
// PruneBackups prunes all backups older than the maximum backup age
func (dis *Distillery) PruneBackups(io stream.IOStream) error {
sPath := dis.SnapshotsArchivePath()
// list all the files
entries, err := os.ReadDir(sPath)
if err != nil {
return err
}
for _, entry := range entries {
// skip directories
if entry.IsDir() {
continue
}
// grab info about the file
info, err := entry.Info()
if err != nil {
return err
}
// check if it should be pruned!
if !dis.ShouldPrune(info.ModTime()) {
continue
}
// assemble path, and then remove the file!
path := filepath.Join(sPath, entry.Name())
io.Printf("Removing %s cause it is older than %d days", path, dis.Config.MaxBackupAge)
if err := os.Remove(path); err != nil {
return err
}
}
return nil
}

View file

@ -39,7 +39,7 @@ type Config struct {
// This email address can be configured here.
CertbotEmail string `env:"CERTBOT_EMAIL" default:"" validator:"is_valid_email"`
// Maximum age for backup
// Maximum age for backup in days
MaxBackupAge int `env:"MAX_BACKUP_AGE" default:"" validator:"is_valid_number"`
// Each Drupal instance requires a corresponding system user, database users and databases.