package config import ( "bytes" "encoding/json" "flag" "fmt" "log" "os" "slices" "strings" "gitlab.hamburg.ccc.de/ccchh/spaceapid/types" ) const ( envConfigPath = "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("Neither the env variable nor cli flag was specified, we are missing a config file.") } 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") } // Initialise 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 }