github.com/drud/ddev@v1.21.5-alpha1.0.20230226034409-94fcc4b94453/pkg/ddevapp/config_merge.go (about)

     1  package ddevapp
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/drud/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, then just load it on top of 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  }