autobrr/internal/config/config.go
Ludvig Lundgren 91b094f4f4
feat(confg): reload on save and refactor logging (#275)
* feat(confg): reload on save

* refactor(logging): rework
2022-05-20 09:27:01 +02:00

192 lines
3.7 KiB
Go

package config
import (
"errors"
"log"
"os"
"path"
"path/filepath"
"sync"
"github.com/autobrr/autobrr/internal/domain"
"github.com/autobrr/autobrr/internal/logger"
"github.com/fsnotify/fsnotify"
"github.com/spf13/viper"
)
func writeConfig(configPath string, configFile string) error {
path := filepath.Join(configPath, configFile)
// check if configPath exists, if not create it
if _, err := os.Stat(configPath); errors.Is(err, os.ErrNotExist) {
err := os.MkdirAll(configPath, os.ModePerm)
if err != nil {
log.Println(err)
return err
}
}
// check if config exists, if not create it
if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
f, err := os.Create(path)
if err != nil { // perm 0666
// handle failed create
log.Printf("error creating file: %q", err)
return err
}
defer f.Close()
_, err = f.WriteString(`# config.toml
# Hostname / IP
#
# Default: "localhost"
#
host = "127.0.0.1"
# Port
#
# Default: 7474
#
port = 7474
# Base url
# Set custom baseUrl eg /autobrr/ to serve in subdirectory.
# Not needed for subdomain, or by accessing with the :port directly.
#
# Optional
#
#baseUrl = "/autobrr/"
# autobrr logs file
# If not defined, logs to stdout
#
# Optional
#
#logPath = "log/autobrr.log"
# Log level
#
# Default: "DEBUG"
#
# Options: "ERROR", "DEBUG", "INFO", "WARN"
#
logLevel = "DEBUG"
# Session secret
#
sessionSecret = "secret-session-key"`)
if err != nil {
log.Printf("error writing contents to file: %v %q", configPath, err)
return err
}
return f.Sync()
}
return nil
}
type Config interface {
DynamicReload(log logger.Logger)
}
type AppConfig struct {
Config *domain.Config
m sync.Mutex
}
func New(configPath string, version string) *AppConfig {
c := &AppConfig{}
c.defaults()
c.Config.Version = version
c.load(configPath)
return c
}
func (c *AppConfig) defaults() {
c.Config = &domain.Config{
Version: "dev",
Host: "localhost",
Port: 7474,
LogLevel: "TRACE",
LogPath: "",
BaseURL: "/",
SessionSecret: "secret-session-key",
CustomDefinitions: "",
DatabaseType: "sqlite",
PostgresHost: "",
PostgresPort: 0,
PostgresDatabase: "",
PostgresUser: "",
PostgresPass: "",
}
}
func (c *AppConfig) load(configPath string) {
// or use viper.SetDefault(val, def)
//viper.SetDefault("host", config.Host)
//viper.SetDefault("port", config.Port)
//viper.SetDefault("logLevel", config.LogLevel)
//viper.SetDefault("logPath", config.LogPath)
viper.SetConfigType("toml")
// clean trailing slash from configPath
configPath = path.Clean(configPath)
if configPath != "" {
//viper.SetConfigName("config")
// check if path and file exists
// if not, create path and file
err := writeConfig(configPath, "config.toml")
if err != nil {
log.Printf("write error: %q", err)
}
viper.SetConfigFile(path.Join(configPath, "config.toml"))
} else {
viper.SetConfigName("config")
// Search config in directories
viper.AddConfigPath(".")
viper.AddConfigPath("$HOME/.config/autobrr")
viper.AddConfigPath("$HOME/.autobrr")
}
// read config
if err := viper.ReadInConfig(); err != nil {
log.Printf("config read error: %q", err)
}
if err := viper.Unmarshal(&c.Config); err != nil {
log.Fatalf("Could not unmarshal config file: %v", viper.ConfigFileUsed())
}
}
func (c *AppConfig) DynamicReload(log logger.Logger) {
viper.OnConfigChange(func(e fsnotify.Event) {
c.m.Lock()
logLevel := viper.GetString("logLevel")
c.Config.LogLevel = logLevel
log.SetLogLevel(c.Config.LogLevel)
logPath := viper.GetString("logPath")
c.Config.LogPath = logPath
log.Debug().Msg("config file reloaded!")
c.m.Unlock()
})
viper.WatchConfig()
return
}