Delete types/v14.go, replace with v15.go.
Rename internal types to not include message version.
I don't currently see the need to support multiple message
versions that have incompatible layouts.
v15 is backwards compatible with v14, so the config example now
specifies both.
Rename the "response" field in the config file to "static" as
dynamic/static makes more sense from the user's perspective.
(Internally it's still SpaceapidConfig.{Dynamic,Response}
to align with type names and usage.)
104 lines
2.5 KiB
Go
104 lines
2.5 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("Config files:", 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)
|
|
}
|
|
}
|
|
|
|
// Sanity check: Config should declare compatibility with current SpaceAPI message version
|
|
if !slices.Contains(conf.Response.APICompatibility, types.CurrentMessageVersion) {
|
|
log.Fatalln("Provided config doesn't specify compatibility with current API version", types.CurrentMessageVersion)
|
|
}
|
|
|
|
// 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
|
|
}
|