Files
docker-updater/config/config.go

106 lines
2.9 KiB
Go

package config
import (
"encoding/json"
"fmt"
"log/slog"
"os"
"github.com/robfig/cron/v3"
)
type (
Configuration struct {
GlobalContainerConfiguration ContainerConfiguration `json:"containers"`
DaemonConfiguration DaemonConfiguration `json:"daemon"`
}
DaemonConfiguration struct {
PullInterval uint `json:"pull_interval"`
}
ContainerConfiguration struct {
Enabled bool `json:"enabled"`
Schedule string `json:"schedule"`
}
)
func Load(configPath string) (Configuration, error) {
file, err := os.OpenFile(configPath, os.O_RDONLY, 0)
if err != nil {
slog.Warn("no configuration found, loading the default one", "thread", "main", "path", configPath)
return Default(), nil
}
defer file.Close()
var c map[string]any
d := json.NewDecoder(file)
if err := d.Decode(&c); err != nil {
return Configuration{}, fmt.Errorf("unable to parse the configuration file: %s", err)
}
return parseConfiguration(c)
}
func Default() Configuration {
return Configuration{
GlobalContainerConfiguration: ContainerConfiguration{
Enabled: false,
Schedule: "* * * * *",
},
DaemonConfiguration: DaemonConfiguration{
PullInterval: 2,
},
}
}
func parseConfiguration(currentConfig map[string]any) (Configuration, error) {
c := Default()
if defaultContainerConfiguration, ok := currentConfig["containers"]; ok {
if defaultContainerData, ok := defaultContainerConfiguration.(map[string]any); ok {
if schedule, ok := defaultContainerData["schedule"]; ok {
if data, ok := schedule.(string); ok {
c.GlobalContainerConfiguration.Schedule = data
} else {
return Configuration{}, fmt.Errorf("configuration parsing: invalid containers.schedule value, expected a string")
}
}
if enabled, ok := defaultContainerData["enabled"]; ok {
if data, ok := enabled.(bool); ok {
c.GlobalContainerConfiguration.Enabled = data
} else {
return Configuration{}, fmt.Errorf("configuration parsing: invalid containers.enabled value, expected a bool")
}
}
} else {
return Configuration{}, fmt.Errorf("configuration parsing: invalid containers section, expected an object")
}
}
if daemonConfiguration, ok := currentConfig["daemon"]; ok {
if daemonData, ok := daemonConfiguration.(map[string]any); ok {
if pullInterval, ok := daemonData["pull_interval"]; ok {
if data, ok := pullInterval.(uint); ok {
c.DaemonConfiguration.PullInterval = data
}
} else {
return Configuration{}, fmt.Errorf("configuration parsing: invalid daemon.pull_interval value, expected an unsigned integer")
}
} else {
return Configuration{}, fmt.Errorf("configuration parsing: invalid daemon section, expected an object")
}
}
return c, nil
}
func (c Configuration) Validate() error {
_, err := cron.ParseStandard(c.GlobalContainerConfiguration.Schedule)
if err != nil {
return fmt.Errorf("failed to validate: invalid schedule: %s", err)
}
return nil
}