github.com/swisspost/terratest@v0.0.0-20230214120104-7ec6de2e1ae0/modules/helm/template.go (about)

     1  package helm
     2  
     3  import (
     4  	"encoding/json"
     5  	"path/filepath"
     6  	"strings"
     7  
     8  	"github.com/ghodss/yaml"
     9  	"github.com/gruntwork-io/go-commons/errors"
    10  	"github.com/stretchr/testify/require"
    11  
    12  	"github.com/gruntwork-io/terratest/modules/files"
    13  	"github.com/gruntwork-io/terratest/modules/testing"
    14  )
    15  
    16  // RenderTemplate runs `helm template` to render the template given the provided options and returns stdout/stderr from
    17  // the template command. If you pass in templateFiles, this will only render those templates. This function will fail
    18  // the test if there is an error rendering the template.
    19  func RenderTemplate(t testing.TestingT, options *Options, chartDir string, releaseName string, templateFiles []string, extraHelmArgs ...string) string {
    20  	out, err := RenderTemplateE(t, options, chartDir, releaseName, templateFiles, extraHelmArgs...)
    21  	require.NoError(t, err)
    22  	return out
    23  }
    24  
    25  // RenderTemplateE runs `helm template` to render the template given the provided options and returns stdout/stderr from
    26  // the template command. If you pass in templateFiles, this will only render those templates.
    27  func RenderTemplateE(t testing.TestingT, options *Options, chartDir string, releaseName string, templateFiles []string, extraHelmArgs ...string) (string, error) {
    28  	// First, verify the charts dir exists
    29  	absChartDir, err := filepath.Abs(chartDir)
    30  	if err != nil {
    31  		return "", errors.WithStackTrace(err)
    32  	}
    33  	if !files.FileExists(chartDir) {
    34  		return "", errors.WithStackTrace(ChartNotFoundError{chartDir})
    35  	}
    36  
    37  	// check chart dependencies
    38  	if _, err := RunHelmCommandAndGetOutputE(t, &Options{}, "dependency", "build", chartDir); err != nil {
    39  		return "", errors.WithStackTrace(err)
    40  	}
    41  
    42  	// Now construct the args
    43  	// We first construct the template args
    44  	args := []string{}
    45  	if options.KubectlOptions != nil && options.KubectlOptions.Namespace != "" {
    46  		args = append(args, "--namespace", options.KubectlOptions.Namespace)
    47  	}
    48  	args, err = getValuesArgsE(t, options, args...)
    49  	if err != nil {
    50  		return "", err
    51  	}
    52  	for _, templateFile := range templateFiles {
    53  		// validate this is a valid template file
    54  		absTemplateFile := filepath.Join(absChartDir, templateFile)
    55  		if !strings.HasPrefix(templateFile, "charts") && !files.FileExists(absTemplateFile) {
    56  			return "", errors.WithStackTrace(TemplateFileNotFoundError{Path: templateFile, ChartDir: absChartDir})
    57  		}
    58  
    59  		// Note: we only get the abs template file path to check it actually exists, but the `helm template` command
    60  		// expects the relative path from the chart.
    61  		args = append(args, "--show-only", templateFile)
    62  	}
    63  	// deal extraHelmArgs
    64  	args = append(args, extraHelmArgs...)
    65  
    66  	// ... and add the name and chart at the end as the command expects
    67  	args = append(args, releaseName, chartDir)
    68  
    69  	// Finally, call out to helm template command
    70  	return RunHelmCommandAndGetStdOutE(t, options, "template", args...)
    71  }
    72  
    73  // UnmarshalK8SYaml is the same as UnmarshalK8SYamlE, but will fail the test if there is an error.
    74  func UnmarshalK8SYaml(t testing.TestingT, yamlData string, destinationObj interface{}) {
    75  	require.NoError(t, UnmarshalK8SYamlE(t, yamlData, destinationObj))
    76  }
    77  
    78  // UnmarshalK8SYamlE can be used to take template outputs and unmarshal them into the corresponding client-go struct. For
    79  // example, suppose you render the template into a Deployment object. You can unmarshal the yaml as follows:
    80  //
    81  // var deployment appsv1.Deployment
    82  // UnmarshalK8SYamlE(t, renderedOutput, &deployment)
    83  //
    84  // At the end of this, the deployment variable will be populated.
    85  func UnmarshalK8SYamlE(t testing.TestingT, yamlData string, destinationObj interface{}) error {
    86  	// NOTE: the client-go library can only decode json, so we will first convert the yaml to json before unmarshaling
    87  	jsonData, err := yaml.YAMLToJSON([]byte(yamlData))
    88  	if err != nil {
    89  		return errors.WithStackTrace(err)
    90  	}
    91  	err = json.Unmarshal(jsonData, destinationObj)
    92  	if err != nil {
    93  		return errors.WithStackTrace(err)
    94  	}
    95  	return nil
    96  }