github.com/verrazzano/verrazzano@v1.7.0/pkg/yaml/strategic_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  	"errors"
     8  	"k8s.io/apimachinery/pkg/util/strategicpatch"
     9  	"os"
    10  	"path/filepath"
    11  	"sigs.k8s.io/yaml"
    12  	"strings"
    13  )
    14  
    15  type PatchStrategy interface{}
    16  
    17  type yamlMap struct {
    18  	yMap map[string]interface{}
    19  }
    20  
    21  // StrategicMergeFiles merges the YAML files returns a YAML string.
    22  // The first file is overlayed by each subsequent file
    23  // The strategy is a JSON annotated structure that represents the YAML structure
    24  func StrategicMergeFiles(strategy PatchStrategy, yamlFiles ...string) (string, error) {
    25  	var yamls []string
    26  	for _, f := range yamlFiles {
    27  		yam, err := os.ReadFile(filepath.Join(f))
    28  		if err != nil {
    29  			return "", err
    30  		}
    31  		yamls = append(yamls, string(yam))
    32  	}
    33  	return StrategicMerge(strategy, yamls...)
    34  }
    35  
    36  // StrategicMerge merges the YAML files returns a YAML string.
    37  // The first YAML is overlayed by each subsequent YAML
    38  // The strategy is a JSON annotated structure that represents the YAML structure
    39  func StrategicMerge(strategy PatchStrategy, yamls ...string) (string, error) {
    40  	if len(yamls) == 0 {
    41  		return "", errors.New("At least 1 YAML file is required")
    42  	}
    43  	if len(yamls) == 1 {
    44  		return yamls[0], nil
    45  	}
    46  
    47  	var mergedJSON []byte
    48  	for _, yam := range yamls {
    49  		// First time through create the base JSON
    50  		overlayYAML := strings.TrimSpace(yam)
    51  		overlayJSON, err := yaml.YAMLToJSON([]byte(overlayYAML))
    52  		if err != nil {
    53  			return "", err
    54  		}
    55  		if len(mergedJSON) == 0 {
    56  			mergedJSON = overlayJSON
    57  			continue
    58  		}
    59  		mergedJSON, err = strategicpatch.StrategicMergePatch(mergedJSON, overlayJSON, strategy)
    60  		if err != nil {
    61  			return "", err
    62  		}
    63  	}
    64  	mergedYaml, err := yaml.JSONToYAML(mergedJSON)
    65  	if err != nil {
    66  		return "", err
    67  	}
    68  	return strings.TrimSpace(string(mergedYaml)), nil
    69  }