mirror of
https://github.com/garethgeorge/backrest.git
synced 2026-08-27 11:26:28 +00:00
feat: keep a rolling backup of the last 10 config versions
This commit is contained in:
@@ -7,12 +7,17 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
v1 "github.com/garethgeorge/backrest/gen/go/v1"
|
||||
"github.com/natefinch/atomic"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
)
|
||||
|
||||
var (
|
||||
configKeepVersions = 10
|
||||
)
|
||||
|
||||
type JsonFileStore struct {
|
||||
Path string
|
||||
mu sync.Mutex
|
||||
@@ -49,17 +54,22 @@ func (f *JsonFileStore) Update(config *v1.Config) error {
|
||||
Multiline: true,
|
||||
}.Marshal(config)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to marshal config: %w", err)
|
||||
return fmt.Errorf("marshal config: %w", err)
|
||||
}
|
||||
|
||||
err = os.MkdirAll(filepath.Dir(f.Path), 0755)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create config directory: %w", err)
|
||||
return fmt.Errorf("create config directory: %w", err)
|
||||
}
|
||||
|
||||
// backup the old config file
|
||||
if err := f.makeBackup(); err != nil {
|
||||
return fmt.Errorf("backup config file: %w", err)
|
||||
}
|
||||
|
||||
err = atomic.WriteFile(f.Path, bytes.NewReader(data))
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to write config file: %w", err)
|
||||
return fmt.Errorf("write config file: %w", err)
|
||||
}
|
||||
|
||||
// only the user running backrest should be able to read the config.
|
||||
@@ -69,3 +79,37 @@ func (f *JsonFileStore) Update(config *v1.Config) error {
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *JsonFileStore) makeBackup() error {
|
||||
curConfig, err := os.ReadFile(f.Path)
|
||||
if err != nil {
|
||||
if errors.Is(err, os.ErrNotExist) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// backup the current config file
|
||||
backupName := fmt.Sprintf("%s.bak.%s", f.Path, time.Now().Format("2006-01-02-15-04-05"))
|
||||
if err := atomic.WriteFile(backupName, bytes.NewBuffer(curConfig)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.Chmod(backupName, 0600); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// only keep the last 10 versions
|
||||
files, err := filepath.Glob(f.Path + ".bak.*")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(files) > configKeepVersions {
|
||||
for _, file := range files[:len(files)-configKeepVersions] {
|
||||
if err := os.Remove(file); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user