github.com/crspeller/mattermost-server@v0.0.0-20190328001957-a200beb3d111/config/environment.go (about) 1 // Copyright (c) 2019-present Mattermost, Inc. All Rights Reserved. 2 // See License.txt for license information. 3 4 package config 5 6 import ( 7 "reflect" 8 9 "github.com/crspeller/mattermost-server/model" 10 ) 11 12 // removeEnvOverrides returns a new config without the given environment overrides. 13 // If a config variable has an environment override, that variable is set to the value that was 14 // read from the store. 15 func removeEnvOverrides(cfg, cfgWithoutEnv *model.Config, envOverrides map[string]interface{}) *model.Config { 16 paths := getPaths(envOverrides) 17 newCfg := cfg.Clone() 18 for _, path := range paths { 19 originalVal := getVal(cfgWithoutEnv, path) 20 getVal(newCfg, path).Set(originalVal) 21 } 22 return newCfg 23 } 24 25 // getPaths turns a nested map into a slice of paths describing the keys of the map. Eg: 26 // map[string]map[string]map[string]bool{"this":{"is first":{"path":true}, "is second":{"path":true}))) is turned into: 27 // [][]string{{"this", "is first", "path"}, {"this", "is second", "path"}} 28 func getPaths(m map[string]interface{}) [][]string { 29 return getPathsRec(m, nil) 30 } 31 32 // getPathsRec assembles the paths (see `getPaths` above) 33 func getPathsRec(src interface{}, curPath []string) [][]string { 34 if srcMap, ok := src.(map[string]interface{}); ok { 35 paths := [][]string{} 36 for k, v := range srcMap { 37 paths = append(paths, getPathsRec(v, append(curPath, k))...) 38 } 39 return paths 40 } 41 42 return [][]string{curPath} 43 } 44 45 // getVal walks `src` (here it starts with a model.Config, then recurses into its leaves) 46 // and returns the reflect.Value of the leaf at the end `path` 47 func getVal(src interface{}, path []string) reflect.Value { 48 var val reflect.Value 49 if reflect.ValueOf(src).Kind() == reflect.Ptr { 50 val = reflect.ValueOf(src).Elem().FieldByName(path[0]) 51 } else { 52 val = reflect.ValueOf(src).FieldByName(path[0]) 53 } 54 if val.Kind() == reflect.Ptr { 55 val = val.Elem() 56 } 57 if val.Kind() == reflect.Struct { 58 return getVal(val.Interface(), path[1:]) 59 } 60 return val 61 }