github.com/kubeshop/testkube@v1.17.23/pkg/helm/chart.go (about)

     1  package helm
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"regexp"
     8  
     9  	"gopkg.in/yaml.v2"
    10  )
    11  
    12  // HelmChart data structure based on map slice
    13  type HelmChart yaml.MapSlice
    14  
    15  // Read reads helm chart based on path
    16  func Read(filePath string) (helmChart HelmChart, err error) {
    17  	content, err := os.ReadFile(filePath)
    18  	if err != nil {
    19  		return helmChart, err
    20  	}
    21  
    22  	err = yaml.Unmarshal(content, &helmChart)
    23  	return
    24  }
    25  
    26  // Write writes content of HelmChart to given path
    27  func Write(filePath string, helmChart HelmChart) (err error) {
    28  
    29  	content, err := yaml.Marshal(helmChart)
    30  	if err != nil {
    31  		return err
    32  	}
    33  	return os.WriteFile(filePath, content, 0644)
    34  }
    35  
    36  // UpdateDependencyVersion updates version in HelmChart
    37  func UpdateDependencyVersion(in HelmChart, dependency, version string) (out HelmChart, err error) {
    38  	// go through SliceMap
    39  	for ci, i := range in {
    40  		if i.Key == "dependencies" {
    41  			deps, ok := i.Value.([]interface{})
    42  			if !ok {
    43  				return out, fmt.Errorf("dependencies key is not array")
    44  			}
    45  
    46  			for di, idep := range deps {
    47  				fields, ok := idep.(HelmChart)
    48  				if !ok {
    49  					return out, fmt.Errorf("invalid dependencies key values")
    50  				}
    51  
    52  				for _, f := range fields {
    53  					if f.Key == "name" && f.Value == dependency {
    54  						for fi, f := range fields {
    55  							if f.Key == "version" {
    56  								in[ci].Value.([]interface{})[di].(HelmChart)[fi].Value = version
    57  								return in, nil
    58  							}
    59  
    60  						}
    61  					}
    62  				}
    63  			}
    64  		}
    65  	}
    66  	return out, fmt.Errorf("dependency not found")
    67  }
    68  
    69  // GetDependencyVersion returns selected helm chart dependency version
    70  func GetDependencyVersion(helmChart HelmChart, dependency string) (string, error) {
    71  	for _, i := range helmChart {
    72  		if i.Key == "dependencies" {
    73  			deps, ok := i.Value.([]interface{})
    74  			if !ok {
    75  				return "", fmt.Errorf("dependencies key is not array")
    76  			}
    77  
    78  			for _, ifields := range deps {
    79  				fields, ok := ifields.(HelmChart)
    80  				if !ok {
    81  					return "", fmt.Errorf("invalid dependencies key values")
    82  				}
    83  
    84  				for _, f := range fields {
    85  					if f.Key == "name" && f.Value == dependency {
    86  						for _, f := range fields {
    87  							if f.Key == "version" {
    88  								return f.Value.(string), nil
    89  							}
    90  
    91  						}
    92  					}
    93  				}
    94  			}
    95  		}
    96  	}
    97  	return "", fmt.Errorf("version key not found in dependency " + dependency)
    98  }
    99  
   100  // GetVersion returns HelmChart version
   101  func GetVersion(helmChart HelmChart) string {
   102  	// go through SliceMap
   103  	for _, i := range helmChart {
   104  		if i.Key == "version" {
   105  			val, ok := i.Value.(string)
   106  			if ok {
   107  				return val
   108  			}
   109  		}
   110  	}
   111  
   112  	return "0.0.0"
   113  }
   114  
   115  // SaveString saves given key with passed value in HelmChart
   116  func SaveString(helmChart *HelmChart, key, value string) error {
   117  	for k := range *helmChart {
   118  		if (*helmChart)[k].Key == key {
   119  			(*helmChart)[k].Value = value
   120  			return nil
   121  		}
   122  	}
   123  
   124  	return fmt.Errorf("key %s not found in %+v", key, helmChart)
   125  }
   126  
   127  // GetChart returns Chart based on directory, locates chart automatically
   128  func GetChart(dir string) (helmChart HelmChart, chartPath string, err error) {
   129  	chartPath, err = Find(dir)
   130  	if err != nil {
   131  		return helmChart, chartPath, err
   132  	}
   133  
   134  	helmChart, err = Read(chartPath)
   135  	return helmChart, chartPath, err
   136  }
   137  
   138  // Find locates helm chart in given dir
   139  func Find(dir string) (chartPath string, err error) {
   140  	dirInfo, err := os.Stat(dir)
   141  	if err != nil {
   142  		return "", err
   143  	}
   144  	if !dirInfo.IsDir() {
   145  		return "", fmt.Errorf("passed '%s' path is not directory", dir)
   146  	}
   147  
   148  	err = filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
   149  		if info.IsDir() {
   150  			return nil
   151  		}
   152  
   153  		if info.Name() == "Chart.yaml" {
   154  			chartPath = path
   155  			return filepath.SkipDir
   156  		}
   157  
   158  		return nil
   159  	})
   160  
   161  	return
   162  }
   163  
   164  // UpdateValuesImageTag updates values.yaml image tag field
   165  func UpdateValuesImageTag(path, tag string) error {
   166  	input, err := os.ReadFile(path)
   167  	if err != nil {
   168  		return err
   169  	}
   170  
   171  	r := regexp.MustCompile(`tag: "[^"]+"`)
   172  	output := r.ReplaceAll(input, []byte(fmt.Sprintf(`tag: "%s"`, tag)))
   173  
   174  	return os.WriteFile(path, output, 0644)
   175  }