github.com/ddev/ddev@v1.23.2-0.20240519125000-d824ffe36ff3/pkg/ddevapp/config_merge.go (about) 1 package ddevapp 2 3 import ( 4 "fmt" 5 "github.com/ddev/ddev/pkg/util" 6 "github.com/imdario/mergo" 7 "strings" 8 ) 9 10 // mergeAdditionalConfigIntoApp takes the provided yaml `config.*.yaml` and merges 11 // it into "app" 12 func (app *DdevApp) mergeAdditionalConfigIntoApp(configPath string) error { 13 newConfig := DdevApp{} 14 err := newConfig.LoadConfigYamlFile(configPath) 15 if err != nil { 16 return err 17 } 18 19 // If override_config is set in the config.*.yaml, load it on top of the app. 20 // Otherwise (the normal default case) merge. 21 if newConfig.OverrideConfig { 22 err = app.LoadConfigYamlFile(configPath) 23 if err != nil { 24 return err 25 } 26 } else { 27 err = mergo.Merge(app, newConfig, mergo.WithAppendSlice, mergo.WithOverride) 28 if err != nil { 29 return err 30 } 31 } 32 33 // We don't need this set; it's only a flag to determine behavior above 34 app.OverrideConfig = false 35 36 // Make sure we don't have absolutely identical items in our resultant arrays 37 for _, arr := range []*[]string{&app.WebImageExtraPackages, &app.DBImageExtraPackages, &app.AdditionalHostnames, &app.AdditionalFQDNs, &app.OmitContainers} { 38 *arr = util.SliceToUniqueSlice(arr) 39 } 40 41 for _, arr := range []*[]string{&app.WebEnvironment} { 42 *arr = EnvToUniqueEnv(arr) 43 } 44 45 return nil 46 } 47 48 // EnvToUniqueEnv() makes sure that only the last occurrence of an env (NAME=val) 49 // slice is actually retained. 50 func EnvToUniqueEnv(inSlice *[]string) []string { 51 mapStore := map[string]string{} 52 newSlice := []string{} 53 54 for _, s := range *inSlice { 55 // config.yaml vars look like ENV1=val1 and ENV2=val2 56 // Split them and then make sure the last one wins 57 k, v, found := strings.Cut(s, "=") 58 // If we didn't find the "=" delimiter, it wasn't an env 59 if !found { 60 continue 61 } 62 mapStore[k] = v 63 } 64 for k, v := range mapStore { 65 newSlice = append(newSlice, fmt.Sprintf("%s=%v", k, v)) 66 } 67 if len(newSlice) == 0 { 68 return nil 69 } 70 return newSlice 71 }