Files
backrest/internal/config/config.go

92 lines
1.8 KiB
Go

package config
import (
"errors"
"fmt"
"sync"
v1 "github.com/garethgeorge/backrest/gen/go/v1"
"github.com/garethgeorge/backrest/internal/config/migrations"
"go.uber.org/zap"
)
var ErrConfigNotFound = fmt.Errorf("config not found")
type ConfigStore interface {
Get() (*v1.Config, error)
Update(config *v1.Config) error
}
func NewDefaultConfig() *v1.Config {
return &v1.Config{
Instance: "",
Repos: []*v1.Repo{},
Plans: []*v1.Plan{},
}
}
type CachingValidatingStore struct {
ConfigStore
mu sync.Mutex
config *v1.Config
}
func (c *CachingValidatingStore) Get() (*v1.Config, error) {
c.mu.Lock()
defer c.mu.Unlock()
if c.config != nil {
return c.config, nil
}
config, err := c.ConfigStore.Get()
if err != nil {
if errors.Is(err, ErrConfigNotFound) {
c.config = NewDefaultConfig()
return c.config, nil
}
return c.config, err
}
// Check if we need to migrate
if config.Version < migrations.CurrentVersion {
zap.S().Infof("migrating config from version %d to %d", config.Version, migrations.CurrentVersion)
if err := migrations.ApplyMigrations(config); err != nil {
return nil, err
}
if config.Version != migrations.CurrentVersion {
return nil, fmt.Errorf("migration failed to update config to version %d", migrations.CurrentVersion)
}
// Write back the migrated config.
if err := c.ConfigStore.Update(config); err != nil {
return nil, err
}
}
// Validate the config
if err := ValidateConfig(config); err != nil {
return nil, err
}
c.config = config
return config, nil
}
func (c *CachingValidatingStore) Update(config *v1.Config) error {
c.mu.Lock()
defer c.mu.Unlock()
if err := ValidateConfig(config); err != nil {
return err
}
if err := c.ConfigStore.Update(config); err != nil {
return err
}
c.config = config
return nil
}