spaceapid/config/config.go

105 lines
2.4 KiB
Go

package config
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"log"
"os"
"slices"
"strings"
"git.hamburg.ccc.de/ccchh/spaceapid/types"
)
const (
envConfigPath = "SPACEAPID_CONFIG_PATH"
)
type pathsT []string
func (p *pathsT) String() string {
return fmt.Sprint(*p)
}
func (p *pathsT) Set(s string) error {
*p = make(pathsT, 0)
for _, path := range strings.Split(s, ",") {
*p = append(*p, path)
}
return nil
}
var (
flagConfigPaths pathsT
)
func init() {
flag.Var(&flagConfigPaths, "c", "Comma-separated list of config file paths. Parsed in order of appearance. Values get overwritten by files parsed later.")
}
func getConfigPaths() (paths pathsT) {
// Get paths from env variable and if env var present override cli flags
configPath, ok := os.LookupEnv(envConfigPath)
if ok {
if configPath == "" {
log.Fatalln("Env variable", envConfigPath, "is present but empty.")
}
_ = flagConfigPaths.Set(configPath)
}
for _, path := range flagConfigPaths {
_, err := os.Stat(path)
if err != nil {
log.Fatalln("Config file", path, "doesn't exist or is not accessible, error:", err)
}
paths = append(paths, path)
}
// If paths is still empty we are missing something
if len(paths) == 0 {
log.Fatalln("Error: Neither env: ", envConfigPath, "nor cli flag was specified, unable to start without config.")
}
return
}
// ParseConfiguration returns the config from file
func ParseConfiguration() (conf SpaceapidConfig) {
log.Println("Parsing configuration files")
paths := getConfigPaths()
log.Println(paths)
for _, path := range paths {
// Read file
file, err := os.ReadFile(path)
if err != nil {
log.Fatalln("Failed reading file:", err)
}
// Parse JSON
dec := json.NewDecoder(bytes.NewReader(file))
dec.DisallowUnknownFields()
err = dec.Decode(&conf)
if err != nil {
log.Fatalln("Could not parse spaceapid config file:", err)
}
}
// Check if compatible with v14
if !slices.Contains(conf.Response.APICompatibility, "14") {
log.Fatalln("Provided file doesn't specify compatibility with API version 14")
}
// Initialize fields for environment sensors
conf.Response.Sensors = make(map[string][]types.EnvironmentSensor)
for key, sensorConfigs := range conf.Dynamic.Sensors {
conf.Response.Sensors[key] = make([]types.EnvironmentSensor, len(sensorConfigs))
for i, sensorConfig := range sensorConfigs {
conf.Response.Sensors[key][i] = sensorConfig.SensorData
}
}
return
}