github.com/verrazzano/verrazzano@v1.7.0/pkg/yaml/replace_merge.go (about)

     1  // Copyright (c) 2021, 2022, Oracle and/or its affiliates.
     2  // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
     3  
     4  package yaml
     5  
     6  import (
     7  	"sigs.k8s.io/yaml"
     8  	"strings"
     9  )
    10  
    11  // ReplacementMerge merges the YAML files returns a YAML string.
    12  // The first YAML is overlayed by each subsequent YAML, lists are replaced
    13  func ReplacementMerge(yamls ...string) (string, error) {
    14  	if len(yamls) == 0 {
    15  		return "", nil
    16  	}
    17  	if len(yamls) == 1 {
    18  		return yamls[0], nil
    19  	}
    20  	var mBase = yamlMap{}
    21  	for _, yam := range yamls {
    22  		if len(mBase.yMap) == 0 {
    23  			if err := yaml.Unmarshal([]byte(yam), &mBase.yMap); err != nil {
    24  				return "", err
    25  			}
    26  			continue
    27  		}
    28  		var mOverlay = yamlMap{}
    29  		if err := yaml.Unmarshal([]byte(yam), &mOverlay.yMap); err != nil {
    30  			return "", err
    31  		}
    32  		if err := MergeMaps(mBase.yMap, mOverlay.yMap); err != nil {
    33  			return "", err
    34  		}
    35  	}
    36  	b, err := yaml.Marshal(&mBase.yMap)
    37  	if err != nil {
    38  		return "", err
    39  	}
    40  	return strings.TrimSpace(string(b)), nil
    41  }
    42  
    43  // mergeMaps 2 maps where mOverlay overrides mBase
    44  func MergeMaps(mBase map[string]interface{}, mOverlay map[string]interface{}) error {
    45  	for k, vOverlay := range mOverlay {
    46  		vBase, ok := mBase[k]
    47  		recursed := false
    48  		if ok {
    49  			// Both mBase and mOverlay have this key. If these are nested maps merge them
    50  			switch tBase := vBase.(type) {
    51  			case map[string]interface{}:
    52  				switch tOverlay := vOverlay.(type) {
    53  				case map[string]interface{}:
    54  					MergeMaps(tBase, tOverlay)
    55  					recursed = true
    56  				}
    57  			}
    58  		}
    59  		// Both values were not maps, put overlay entry into the base map
    60  		// This might be a new base entry or replaced by the mOverlay value
    61  		if !recursed {
    62  			mBase[k] = vOverlay
    63  		}
    64  	}
    65  	return nil
    66  }