package config import ( "errors" "fmt" "io/ioutil" "os" "os/user" "path/filepath" "reflect" "github.com/creasty/defaults" "gopkg.in/yaml.v3" "scm.yoorie.de/go-lib/util" ) func GetConfigurationFiles(appName string) []string { // First checking local config executablePath, _ := os.Executable() fname := filepath.Base(executablePath) fext := filepath.Ext(executablePath) fdir := filepath.Dir(executablePath) fnameWoExt := fname[0 : len(fname)-len(fext)] ymlExts := [2]string{".yml", ".yaml"} fileNames := make([]string, 0, 4) for _, ext := range ymlExts { fileNames = append(fileNames, filepath.Join(fdir, fnameWoExt+ext)) } usr, _ := user.Current() fileNames = append(fileNames, filepath.Join(usr.HomeDir, "."+appName, "config")) // Check for global config fileNames = append(fileNames, util.GetGlobalConfigurationFile(appName, "config")) return fileNames } func GetConfigurationFile(appName string) string { // First checking local config files := GetConfigurationFiles(appName) for _, localConfigFile := range files { if util.FileExists(localConfigFile) { return localConfigFile } } return "" } func LoadConfiguration[T any](config T) error { return LoadConfigurationFromFile(config, "") } func IsStructPointer[T any](config T) bool { value := reflect.ValueOf(config) return value.Type().Kind() == reflect.Pointer && reflect.Indirect(value).Type().Kind() == reflect.Struct } func LoadConfigurationFromFile[T any](config T, configFile string) error { if !IsStructPointer(config) { genericType := reflect.TypeOf(config) return errors.New(fmt.Sprintf("Type: %s.%s is not a struct pointer", genericType.PkgPath(), genericType.Name())) } defaults.Set(config) if configFile != "" { if !util.FileExists(configFile) { return errors.New(fmt.Sprintf("given configuration file %s cannot be found", configFile)) } } else { if method := reflect.ValueOf(config).MethodByName("appName"); !method.IsNil() { result := method.String() if result != "" { configFile = GetConfigurationFile(result) } } } if configFile == "" { return nil } ymldata, err := ioutil.ReadFile(configFile) if err != nil { return errors.New(fmt.Sprintf("cannot read configuration file %s. %v", configFile, err)) } err = yaml.Unmarshal(ymldata, config) if err != nil { return errors.New(fmt.Sprintf("error unmarshalling configuration data: %v", err)) } return nil }