dogtamer/config/config.go
2021-09-14 22:51:36 +02:00

133 lines
2.9 KiB
Go

package config
import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"github.com/pelletier/go-toml"
)
var ErrNotFound = errors.New("no config file found")
type Config struct {
Hostname string `toml:"Hostname"`
RTMPListenAddr string `toml:"RTMPListenAddr"`
HTTPServerEnable bool `toml:"HTTPServerEnable"`
HTTPListenAddr string `toml:"HTTPListenAddr"`
HTTPAccessLogEnable bool `toml:"HTTPAccessLogEnable"`
LogLevel string `toml:"LogLevel"`
}
type InvalidValueError struct {
Key string
}
func (ive *InvalidValueError) Error() string {
return fmt.Sprintf("invalid value: config key %s has invalid value", ive.Key)
}
func FromReader(r io.Reader) (*Config, error) {
var c Config
// Set some defaults
c.RTMPListenAddr = ":5566"
c.HTTPServerEnable = false
c.HTTPListenAddr = ":8077"
c.LogLevel = "INFO"
c.Hostname = "localhost"
decoder := toml.NewDecoder(r)
if err := decoder.Decode(&c); err != nil {
return nil, fmt.Errorf("error parsing config file: %w", err)
}
return &c, c.Verify()
}
func (c *Config) Verify() error {
// Check that LogLevel is valid
switch c.LogLevel {
case "DEBUG", "INFO", "WARN", "ERROR":
default:
return &InvalidValueError{Key: "LogLevel"}
}
return nil
}
func (c *Config) UpdateFromEnv() error {
if hostname, found := os.LookupEnv("DOGTAMER_HOSTNAME"); found {
c.Hostname = hostname
}
if loglevel, found := os.LookupEnv("DOGTAMER_LOGLEVEL"); found {
c.LogLevel = loglevel
}
if listenAddr, found := os.LookupEnv("DOGTAMER_RTMPLISTENADDR"); found {
c.RTMPListenAddr = listenAddr
}
if httpEnable, found := os.LookupEnv("DOGTAMER_HTTPSERVERENABLE"); found {
switch strings.ToUpper(httpEnable) {
case "TRUE", "YES", "ENABLE":
c.HTTPServerEnable = true
}
}
if httpListenAddr, found := os.LookupEnv("DOGTAMER_HTTPLISTENADDR"); found {
c.HTTPListenAddr = httpListenAddr
}
if httpAccessLogEnable, found := os.LookupEnv("DOGTAMER_HTTPACCESSLOGENABLE"); found {
switch strings.ToUpper(httpAccessLogEnable) {
case "TRUE", "YES", "ENABLE":
c.HTTPAccessLogEnable = true
}
}
return c.Verify()
}
func FromFile(path string) (*Config, error) {
f, err := os.Open(path)
if err != nil {
return nil, fmt.Errorf("Error opening config file: %w", err)
}
return FromReader(f)
}
func FromDefaultLocations() (*Config, error) {
defaultLocations := []string{
"dogtamer.toml",
"/etc/dogtamer.toml",
}
baseConfigDir, err := os.UserConfigDir()
if err == nil {
userConfigFile := filepath.Join(baseConfigDir, "dogtamer", "dogtamer.toml")
defaultLocations = append(defaultLocations, userConfigFile)
}
for _, fname := range defaultLocations {
if _, err := os.Stat(fname); os.IsNotExist(err) {
continue
}
cfg, err := FromFile(fname)
if err != nil {
continue
}
return cfg, cfg.UpdateFromEnv()
}
cfg, err := FromReader(strings.NewReader(""))
if err == nil {
return cfg, ErrNotFound
}
return nil, ErrNotFound
}