From 3103fbde29c90e7a97f3e9d63019e626017c9f08 Mon Sep 17 00:00:00 2001 From: Ian Fijolek Date: Fri, 4 Nov 2022 14:31:54 -0700 Subject: [PATCH] Raise an error when an unknown job is requested Fixes #1 --- main.go | 70 ++++++++++++++++++++++++++++++++++++++-------------- main_test.go | 64 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 116 insertions(+), 18 deletions(-) diff --git a/main.go b/main.go index 21269e7..01b1e9f 100644 --- a/main.go +++ b/main.go @@ -1,6 +1,7 @@ package main import ( + "errors" "flag" "fmt" "log" @@ -15,7 +16,8 @@ import ( var ( // version of restic-scheduler being run. - version = "dev" + version = "dev" + ErrJobNotFound = errors.New("jobs not found") ) func ParseConfig(path string) ([]Job, error) { @@ -92,6 +94,12 @@ func ReadJobs(paths []string) ([]Job, error) { type Set map[string]bool +func (s Set) Contains(key string) bool { + _, contains := s[key] + + return contains +} + func NewSetFrom(l []string) Set { s := make(Set) for _, l := range l { @@ -101,30 +109,44 @@ func NewSetFrom(l []string) Set { return s } -func runBackupJobs(jobs []Job, names []string) error { +/// FilterJobs filters a list of jobs by a list of names +func FilterJobs(jobs []Job, names []string) ([]Job, error) { nameSet := NewSetFrom(names) - _, runAll := nameSet["all"] + if nameSet.Contains("all") { + return jobs, nil + } + filteredJobs := []Job{} for _, job := range jobs { - if _, found := nameSet[job.Name]; runAll || found { - if err := job.RunBackup(); err != nil { - return err - } + if nameSet.Contains(job.Name) { + filteredJobs = append(filteredJobs, job) + + delete(nameSet, job.Name) + } + } + + var err error + if len(nameSet) > 0 { + err = fmt.Errorf("%w: %v", ErrJobNotFound, nameSet) + } + + return filteredJobs, err +} + +func RunBackupJobs(jobs []Job) error { + for _, job := range jobs { + if err := job.RunBackup(); err != nil { + return err } } return nil } -func runRestoreJobs(jobs []Job, names []string) error { - nameSet := NewSetFrom(names) - _, runAll := nameSet["all"] - +func RunRestoreJobs(jobs []Job) error { for _, job := range jobs { - if _, found := nameSet[job.Name]; runAll || found { - if err := job.RunRestore(); err != nil { - return err - } + if err := job.RunRestore(); err != nil { + return err } } @@ -161,13 +183,25 @@ func main() { } // Run specified backup jobs - if err := runBackupJobs(jobs, strings.Split(*backup, ",")); err != nil { + backupJobNames := strings.Split(*backup, ",") + backupJobs, filterJobErr := FilterJobs(jobs, backupJobNames) + if err := RunBackupJobs(backupJobs); err != nil { log.Fatalf("Failed running backup jobs: %v", err) } + if filterJobErr != nil { + log.Fatalf("Unkown backup job: %v", err) + } + // Run specified restore jobs - if err := runRestoreJobs(jobs, strings.Split(*restore, ",")); err != nil { - log.Fatalf("Failed running backup jobs: %v", err) + restoreJobNames := strings.Split(*restore, ",") + restoreJobs, filterJobErr := FilterJobs(jobs, restoreJobNames) + if err := RunRestoreJobs(restoreJobs); err != nil { + log.Fatalf("Failed running restore jobs: %v", err) + } + + if filterJobErr != nil { + log.Fatalf("Unkown restore job: %v", err) } // Exit if only running once diff --git a/main_test.go b/main_test.go index f91a25f..17bdedc 100644 --- a/main_test.go +++ b/main_test.go @@ -1,8 +1,10 @@ package main_test import ( + "errors" "fmt" "os" + "reflect" "testing" main "git.iamthefij.com/iamthefij/restic-scheduler" @@ -38,3 +40,65 @@ func TestReadJobs(t *testing.T) { t.Error("Expected read jobs but found none") } } + +func TestRunJobs(t *testing.T) { + t.Parallel() + + validJob := main.Job{ + Name: "Valid job", + Schedule: "@daily", + Config: ValidResticConfig(), + Tasks: []main.JobTask{}, + Backup: main.BackupFilesTask{Paths: []string{"/test"}}, // nolint:exhaustivestruct + Forget: nil, + MySQL: []main.JobTaskMySQL{}, + Sqlite: []main.JobTaskSqlite{}, + } + + cases := []struct { + name string + jobs []main.Job + names []string + expected []main.Job + expectedError error + }{ + { + name: "Found job", + jobs: []main.Job{validJob}, + names: []string{"Valid job"}, + expected: []main.Job{validJob}, + expectedError: nil, + }, + { + name: "Run all", + jobs: []main.Job{validJob}, + names: []string{"all"}, + expected: []main.Job{validJob}, + expectedError: nil, + }, + { + name: "Extra, missing job", + jobs: []main.Job{validJob}, + names: []string{"Valid job", "Not Found"}, + expected: []main.Job{validJob}, + expectedError: main.ErrJobNotFound, + }, + } + + for _, c := range cases { + testCase := c + + t.Run(testCase.name+" backup", func(t *testing.T) { + t.Parallel() + + jobs, err := main.FilterJobs(testCase.jobs, testCase.names) + if !reflect.DeepEqual(jobs, testCase.expected) { + t.Errorf("expected %v but found %v", testCase.expected, jobs) + } + + if !errors.Is(err, testCase.expectedError) { + t.Errorf("expected %v but found %v", testCase.expectedError, err) + } + }) + } +}