http-boot-server/bootserver/config/config.go
2024-04-30 18:43:01 +02:00

152 lines
3.8 KiB
Go

package config
import (
"encoding/json"
"errors"
"fmt"
"io/fs"
"os"
"github.com/sirupsen/logrus"
)
type ListeningMode int64
func (lm ListeningMode) String() string {
mapping := map[ListeningMode]string{
ModeNet: "net",
ModeUnix: "unix",
}
val := mapping[lm]
return val
}
func listeningModeFromString(rawVal string) (ListeningMode, error) {
mapping := map[string]ListeningMode{
"unix": ModeUnix,
"net": ModeNet,
}
if typedVal, ok := mapping[rawVal]; !ok {
return ModeNet, fmt.Errorf("invalid listening mode %s", rawVal)
} else {
return typedVal, nil
}
}
const (
ModeUnix ListeningMode = iota
ModeNet
)
type jsonConf struct {
Log struct {
Level string `json:"level"`
} `json:"log"`
Storage struct {
Path string `json:"path"`
TemplateDir string `json:"templatePath"`
StaticDir string `json:"staticPath"`
} `json:"storage"`
Server struct {
Host string `json:"host"`
Port int `json:"port"`
Mode string `json:"mode"`
SockPath string `json:"sock"`
PublicHost string `json:"public_host"`
} `json:"server"`
BootProvider struct {
Iface string `json:"interface"`
Port int `json:"port"`
McastGroup string `json:"multicast_group"`
SrcAddr string `json:"src_addr"`
} `json:"boot_provider"`
HomeAssistant struct {
Enabled bool `json:"enabled"`
Host string `json:"host"`
APIToken string `json:"token"`
} `json:"home_assistant"`
}
type AppConfig struct {
LogLevel logrus.Level
ServerMode ListeningMode
DataFilepath string
StaticDir string
Host string
PublicHost string
Port int
SockPath string
UPDMcastGroup string
UDPPort int
UDPIface string
UDPSrcAddr string
HomeAssistantEnabled bool
HomeAssistantHost string
HomeAssistantToken string
}
func parseLevel(lvlStr string) logrus.Level {
for _, lvl := range logrus.AllLevels {
if lvl.String() == lvlStr {
return lvl
}
}
return logrus.InfoLevel
}
func (ac *AppConfig) UnmarshalJSON(data []byte) error {
var jsonConf jsonConf
if err := json.Unmarshal(data, &jsonConf); err != nil {
return fmt.Errorf("failed to read JSON: %w", err)
}
ac.LogLevel = parseLevel(jsonConf.Log.Level)
lm, err := listeningModeFromString(jsonConf.Server.Mode)
if err != nil {
return fmt.Errorf("failed to parse server listening mode: %w", err)
}
ac.ServerMode = lm
ac.SockPath = jsonConf.Server.SockPath
ac.Host = jsonConf.Server.Host
ac.PublicHost = jsonConf.Server.PublicHost
ac.Port = jsonConf.Server.Port
ac.UPDMcastGroup = jsonConf.BootProvider.McastGroup
ac.UDPIface = jsonConf.BootProvider.Iface
ac.UDPPort = jsonConf.BootProvider.Port
ac.UDPSrcAddr = jsonConf.BootProvider.SrcAddr
ac.DataFilepath = jsonConf.Storage.Path
ac.StaticDir = jsonConf.Storage.StaticDir
ac.HomeAssistantEnabled = jsonConf.HomeAssistant.Enabled
ac.HomeAssistantHost = jsonConf.HomeAssistant.Host
ac.HomeAssistantToken = jsonConf.HomeAssistant.APIToken
return nil
}
var defaultConfig AppConfig = AppConfig{
LogLevel: logrus.InfoLevel,
ServerMode: ModeNet,
DataFilepath: "boot_options.json",
Host: "0.0.0.0",
PublicHost: "http://127.0.0.1:5000",
Port: 5000,
UPDMcastGroup: "ff02::abcd:1234",
UDPPort: 42,
UDPIface: "eth0",
StaticDir: "./static",
}
func New(filepath string) (*AppConfig, error) {
content, err := os.ReadFile(filepath)
if err != nil {
if errors.Is(err, fs.ErrNotExist) {
conf := defaultConfig
return &conf, nil
}
return nil, fmt.Errorf("failed to read config file %q: %w", filepath, err)
}
var conf AppConfig
if err := json.Unmarshal(content, &conf); err != nil {
return nil, fmt.Errorf("failed to parse config file: %w", err)
}
return &conf, nil
}