diff --git a/cmd/cron.go b/cmd/cron.go new file mode 100644 index 0000000..c3eecb0 --- /dev/null +++ b/cmd/cron.go @@ -0,0 +1,36 @@ +/* +Copyright © 2021 NAME HERE + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +package cmd + +import ( + "github.com/cupcakearmy/autorestic/internal" + "github.com/spf13/cobra" +) + +// cronCmd represents the cron command +var cronCmd = &cobra.Command{ + Use: "cron", + Short: "Run cron job for automated backups", + Long: `Intended to be mainly triggered by an automated system like systemd or crontab. For each location checks if a cron backup is due and runs it.`, + Run: func(cmd *cobra.Command, args []string) { + err := internal.RunCron() + cobra.CheckErr(err) + }, +} + +func init() { + rootCmd.AddCommand(cronCmd) +} diff --git a/go.mod b/go.mod index b0202ff..6befd16 100644 --- a/go.mod +++ b/go.mod @@ -6,6 +6,7 @@ require ( github.com/blang/semver/v4 v4.0.0 github.com/buger/goterm v1.0.0 github.com/mitchellh/go-homedir v1.1.0 + github.com/robfig/cron v1.2.0 github.com/spf13/cobra v1.1.3 github.com/spf13/viper v1.7.1 ) diff --git a/go.sum b/go.sum index 314d040..e27c519 100644 --- a/go.sum +++ b/go.sum @@ -151,6 +151,8 @@ github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y8 github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= +github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= +github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= diff --git a/internal/cron.go b/internal/cron.go new file mode 100644 index 0000000..1aa576f --- /dev/null +++ b/internal/cron.go @@ -0,0 +1,12 @@ +package internal + +func RunCron() error { + c := GetConfig() + for _, l := range c.Locations { + err := l.RunCron() + if err != nil { + return err + } + } + return nil +} diff --git a/internal/location.go b/internal/location.go index 181e12b..898fd01 100644 --- a/internal/location.go +++ b/internal/location.go @@ -5,6 +5,10 @@ import ( "io/ioutil" "os" "path/filepath" + "time" + + "github.com/cupcakearmy/autorestic/internal/lock" + "github.com/robfig/cron" ) type HookArray = []string @@ -163,3 +167,26 @@ func (l Location) Restore(to, from string, force bool) error { } return nil } + +func (l Location) RunCron() error { + if l.Cron == "" { + return nil + } + + schedule, err := cron.ParseStandard(l.Cron) + if err != nil { + return err + } + last := lock.GetCron("test") + fmt.Println(last) + next := schedule.Next(time.Unix(last, 0)) + fmt.Println(next) + now := time.Now() + if now.After(next) { + fmt.Println("Running") + lock.SetCron("test", now.Unix()) + } else { + fmt.Println("Not due yet") + } + return nil +} diff --git a/internal/lock/lock.go b/internal/lock/lock.go index b90ddbd..d2f7d9c 100644 --- a/internal/lock/lock.go +++ b/internal/lock/lock.go @@ -28,7 +28,7 @@ func getLock() *viper.Viper { return lock } -func set(locked bool) error { +func setLock(locked bool) error { lock := getLock() if locked { running := lock.GetBool("running") @@ -43,10 +43,20 @@ func set(locked bool) error { return nil } +func GetCron(location string) int64 { + lock := getLock() + return lock.GetInt64("cron." + location) +} + +func SetCron(location string, value int64) { + lock.Set("cron."+location, value) + lock.WriteConfigAs(file) +} + func Lock() error { - return set(true) + return setLock(true) } func Unlock() error { - return set(false) + return setLock(false) }