From 531cd286d87c8004b95bfd9b4512dffccc6d500d Mon Sep 17 00:00:00 2001 From: Gareth Date: Sun, 19 May 2024 15:52:16 -0700 Subject: [PATCH] feat: unified scheduling model (#282) --- backrest.go | 13 +- docs/content/2.docs/2.hooks.md | 4 +- gen/go/v1/config.pb.go | 752 +++++++++++------- internal/api/backresthandler.go | 15 +- internal/api/backresthandler_test.go | 29 +- internal/config/config_test.go | 42 +- internal/config/migrations/002schedules.go | 42 + internal/config/migrations/migrations.go | 1 + internal/config/validate.go | 24 +- internal/{config => env}/environment.go | 2 +- internal/hook/hookvars.go | 5 + internal/oplog/oplog.go | 7 +- internal/orchestrator/orchestrator.go | 20 +- internal/orchestrator/orchestrator_test.go | 6 +- internal/orchestrator/repo/repo_test.go | 2 +- internal/orchestrator/taskrunnerimpl.go | 7 + internal/orchestrator/tasks/task.go | 9 +- internal/orchestrator/tasks/taskbackup.go | 64 +- .../orchestrator/tasks/taskcollectgarbage.go | 6 +- internal/orchestrator/tasks/taskforget.go | 6 - internal/orchestrator/tasks/taskprune.go | 86 +- internal/protoutil/schedule.go | 61 ++ internal/resticinstaller/resticinstaller.go | 8 +- proto/v1/config.proto | 28 +- webui/gen/ts/v1/config_pb.ts | 141 +++- webui/src/api.ts | 1 + webui/src/components/OperationTree.tsx | 5 +- webui/src/components/ScheduleFormItem.tsx | 161 ++++ webui/src/views/AddPlanModal.tsx | 45 +- webui/src/views/AddRepoModal.tsx | 39 +- webui/src/views/PlanView.tsx | 14 - webui/src/views/RepoView.tsx | 29 +- 32 files changed, 1155 insertions(+), 519 deletions(-) create mode 100644 internal/config/migrations/002schedules.go rename internal/{config => env}/environment.go (99%) create mode 100644 internal/protoutil/schedule.go create mode 100644 webui/src/components/ScheduleFormItem.tsx diff --git a/backrest.go b/backrest.go index bc2d465..54a3d79 100644 --- a/backrest.go +++ b/backrest.go @@ -19,6 +19,7 @@ import ( "github.com/garethgeorge/backrest/internal/api" "github.com/garethgeorge/backrest/internal/auth" "github.com/garethgeorge/backrest/internal/config" + "github.com/garethgeorge/backrest/internal/env" "github.com/garethgeorge/backrest/internal/oplog" "github.com/garethgeorge/backrest/internal/orchestrator" "github.com/garethgeorge/backrest/internal/resticinstaller" @@ -64,7 +65,7 @@ func main() { var wg sync.WaitGroup // Create / load the operation log - oplogFile := path.Join(config.DataDir(), "oplog.boltdb") + oplogFile := path.Join(env.DataDir(), "oplog.boltdb") oplog, err := oplog.NewOpLog(oplogFile) if err != nil { if !errors.Is(err, bbolt.ErrTimeout) { @@ -76,7 +77,7 @@ func main() { defer oplog.Close() // Create rotating log storage - logStore := rotatinglog.NewRotatingLog(path.Join(config.DataDir(), "rotatinglogs"), 14) // 14 days of logs + logStore := rotatinglog.NewRotatingLog(path.Join(env.DataDir(), "rotatinglogs"), 14) // 14 days of logs if err != nil { zap.S().Fatalf("error creating rotating log storage: %v", err) } @@ -112,7 +113,7 @@ func main() { // Serve the HTTP gateway server := &http.Server{ - Addr: config.BindAddress(), + Addr: env.BindAddress(), Handler: h2c.NewHandler(mux, &http2.Server{}), // h2c is HTTP/2 without TLS for grpc-connect support. } @@ -146,7 +147,7 @@ func init() { func createConfigProvider() config.ConfigStore { return &config.CachingValidatingStore{ - ConfigStore: &config.JsonFileStore{Path: config.ConfigFilePath()}, + ConfigStore: &config.JsonFileStore{Path: env.ConfigFilePath()}, } } @@ -160,7 +161,7 @@ func onterm(s os.Signal, callback func()) { } func getSecret() []byte { - secretFile := path.Join(config.DataDir(), "jwt-secret") + secretFile := path.Join(env.DataDir(), "jwt-secret") data, err := os.ReadFile(secretFile) if err == nil { zap.L().Debug("loading auth secret from file") @@ -172,7 +173,7 @@ func getSecret() []byte { if n, err := rand.Read(secret); err != nil || n != 64 { zap.S().Fatalf("error generating secret: %v", err) } - if err := os.MkdirAll(config.DataDir(), 0700); err != nil { + if err := os.MkdirAll(env.DataDir(), 0700); err != nil { zap.S().Fatalf("error creating data directory: %v", err) } if err := os.WriteFile(secretFile, secret, 0600); err != nil { diff --git a/docs/content/2.docs/2.hooks.md b/docs/content/2.docs/2.hooks.md index 3576f3c..7e87d4c 100644 --- a/docs/content/2.docs/2.hooks.md +++ b/docs/content/2.docs/2.hooks.md @@ -35,12 +35,14 @@ Variables - `SnapshotId:string` - the snapshot ID associated with the operation or empty string if none is associated. - `SnapshotStats:restic.BackupProgressEntry` - summary of the current backup operation. This is a struct. See examples below for details. - `CurTime:time.Time` - the current time. This is a struct. Format as `{{ .FormatTime .CurTime }}`. +- `Duration:time.Duration` - the duration of the triggering operation. Format as `{{ .FormatDuration .Duration }}`. - `Error:string` - the error message if an error occurred, or empty string if successful. Functions - `.Summary` - prints a default summary of the current event. -- `.FormatTime