diff --git a/README.md b/README.md index ad71151..ced6c9b 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,8 @@ go build ## Release History +* 0.2.1 + * CLI curator option for keeping n backups * 0.2.0 * Fix CLI help * add option for length factor in LIST command diff --git a/backup/zip_test.go b/backup/zip_test.go index 6c1e87c..2327285 100644 --- a/backup/zip_test.go +++ b/backup/zip_test.go @@ -63,13 +63,14 @@ func TestBlacklist(t *testing.T) { testCase string expectedResult bool }{ - {"suffixes", `.*\.exe`, "test.exe", true }, - {"suffixes", `.*\.exe`, "test.exe_", true }, - {"suffixes", `.*\.exe$`, "test.exe_", false }, - {"suffixes", `.*\.exe`, "full/path/to/test.exe", true }, - {"suffixes", `.*\.exe`, ".exe", true }, - {"suffixes", `.*\.exe`, "exe", false }, - {"folders", `.*/log/.*`, "/path/to/log/test.txt", true }, + {"suffixes", `.*\.exe`, "test.exe", true}, + {"suffixes", `.*\.exe`, "test.exe_", true}, + {"suffixes", `.*\.exe$`, "test.exe_", false}, + {"suffixes", `.*\.exe`, "full/path/to/test.exe", true}, + {"suffixes", `.*\.exe`, ".exe", true}, + {"suffixes", `.*\.exe`, "exe", false}, + {"folders", `.*/log/.*`, "/path/to/log/test.txt", true}, + {"folders", `/log/.*`, "/path/to/log/test.txt", true}, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { diff --git a/cli/action_curator.go b/cli/action_curator.go index 46d91d0..7235170 100644 --- a/cli/action_curator.go +++ b/cli/action_curator.go @@ -18,15 +18,18 @@ func NewCuratorAction() CliAction { func (a *actionCurator) Do(cfg *config.Config) { dbRepository := database.NewRepository(cfg.Curator.Database) - var t time.Time + var backupIter database.BackupIterator if cfg.Curator.OlderThanTime != nil { - t = *cfg.Curator.OlderThanTime + t := *cfg.Curator.OlderThanTime + backupIter = dbRepository.GetOlderThan(cfg.Curator.AWSVaultName, t) + } else if cfg.Curator.MaxAgeDays != 0 { + t := time.Now().Add(time.Hour * 24 * time.Duration(cfg.Curator.MaxAgeDays) * -1) + backupIter = dbRepository.GetOlderThan(cfg.Curator.AWSVaultName, t) } else { - t = time.Now().Add(time.Hour * 24 * time.Duration(cfg.Curator.MaxAgeDays) * -1) + backupIter = dbRepository.GetLast(cfg.Curator.AWSVaultName, cfg.Curator.KeepN) } - backupIter := dbRepository.GetOlderThan(cfg.Curator.AWSVaultName, t) backupIds := printBackups(backupIter, 1) if len(backupIds) == 0 { @@ -59,7 +62,7 @@ func (a *actionCurator) Validate(cfg *config.Config) { ValidateDatabase(&cfg.Curator.DatabaseConfig) ValidateAWS(&cfg.Curator.AwsGeneralConfig) - if cfg.Curator.OlderThanTime == nil && cfg.Curator.MaxAgeDays == 0 { - cfg.Curator.Fail("Even OlderThan or MaxAge must be given!") + if cfg.Curator.OlderThanTime == nil && cfg.Curator.MaxAgeDays == 0 && cfg.Curator.KeepN == 0 { + cfg.Curator.Fail("Even OlderThan, MaxAge or Keep must be given!") } } diff --git a/config/config.go b/config/config.go index 5bace10..1c04bd2 100644 --- a/config/config.go +++ b/config/config.go @@ -108,6 +108,7 @@ type CuratorConfig struct { OlderThanTime *time.Time `arg:"--older-than,env:OLDER_THAN,help:Backups which are older than this time."` MaxAgeDays int `arg:"--max-age,env:MAX_AGE,help:Backups which are older than x days."` + KeepN int `arg:"--keep,env:LAST,help:Keep only the last n backups."` argParser *arg.Parser `arg:"-"` } diff --git a/database/repository.go b/database/repository.go index cc4c5fa..68dd3d5 100644 --- a/database/repository.go +++ b/database/repository.go @@ -24,6 +24,7 @@ type Repository interface { GetBackupById(uint) *model.Backup GetBackupContentsById(uint) (*model.Backup, ContentIterator) GetOlderThan(string, time.Time) BackupIterator + GetLast(string, int) BackupIterator DeleteBackupById(uint) } @@ -92,6 +93,21 @@ func (r *repository) GetOlderThan(vault string, time time.Time) BackupIterator { return newBackupIterator(sqlRows, r.db) } +func (r *repository) GetLast(vault string, offset int) BackupIterator { + sqlRows, err := r.db. + Offset(offset).Limit(500). + Model(&model.Backup{}). + Where(model.ColumnBackupVault+" = ?", vault). + Order(model.ColumnCreatedAt + " DESC"). + Rows() + + if err != nil { + panic(errors.Wrap(err, "Error while creating rows")) + } + + return newBackupIterator(sqlRows, r.db) +} + func (r *repository) GetBackupById(id uint) *model.Backup { var backup model.Backup r.db.First(&backup, id)