github.com/lyft/flytestdlib@v0.3.12-0.20210213045714-8cdd111ecda1/config/utils.go (about) 1 package config 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "reflect" 7 8 "github.com/pkg/errors" 9 10 stdLibErrs "github.com/lyft/flytestdlib/errors" 11 ) 12 13 // Uses Json marshal/unmarshal to make a deep copy of a config object. 14 func DeepCopyConfig(config Config) (Config, error) { 15 raw, err := json.Marshal(config) 16 if err != nil { 17 return nil, err 18 } 19 20 t := reflect.TypeOf(config) 21 ptrValue := reflect.New(t) 22 newObj := ptrValue.Interface() 23 if err = json.Unmarshal(raw, newObj); err != nil { 24 return nil, err 25 } 26 27 return ptrValue.Elem().Interface(), nil 28 } 29 30 func DeepEqual(config1, config2 Config) bool { 31 return reflect.DeepEqual(config1, config2) 32 } 33 34 func toInterface(config Config) (interface{}, error) { 35 raw, err := json.Marshal(config) 36 if err != nil { 37 return nil, err 38 } 39 40 var m interface{} 41 err = json.Unmarshal(raw, &m) 42 return m, err 43 } 44 45 // Builds a generic map out of the root section config and its sub-sections configs. 46 func AllConfigsAsMap(root Section) (m map[string]interface{}, err error) { 47 errs := stdLibErrs.ErrorCollection{} 48 allConfigs := make(map[string]interface{}, len(root.GetSections())) 49 if root.GetConfig() != nil { 50 rootConfig, err := toInterface(root.GetConfig()) 51 if !errs.Append(err) { 52 if asMap, isCasted := rootConfig.(map[string]interface{}); isCasted { 53 allConfigs = asMap 54 } else { 55 allConfigs[""] = rootConfig 56 } 57 } 58 } 59 60 for k, section := range root.GetSections() { 61 if _, alreadyExists := allConfigs[k]; alreadyExists { 62 errs.Append(errors.Wrap(ErrChildConfigOverridesConfig, 63 fmt.Sprintf("section key [%v] overrides an existing native config property", k))) 64 } 65 66 allConfigs[k], err = AllConfigsAsMap(section) 67 errs.Append(err) 68 } 69 70 return allConfigs, errs.ErrorOrDefault() 71 }