github.com/argoproj/argo-cd/v3@v3.2.1/util/helm/helm_test.go (about)

     1  package helm
     2  
     3  import (
     4  	"path/filepath"
     5  	"testing"
     6  
     7  	"github.com/stretchr/testify/require"
     8  
     9  	"github.com/argoproj/argo-cd/v3/util/io/path"
    10  
    11  	"github.com/argoproj/gitops-engine/pkg/utils/kube"
    12  	"github.com/stretchr/testify/assert"
    13  	appsv1 "k8s.io/api/apps/v1"
    14  	corev1 "k8s.io/api/core/v1"
    15  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    16  	"k8s.io/apimachinery/pkg/runtime"
    17  )
    18  
    19  func template(h Helm, opts *TemplateOpts) ([]*unstructured.Unstructured, error) {
    20  	out, _, err := h.Template(opts)
    21  	if err != nil {
    22  		return nil, err
    23  	}
    24  	return kube.SplitYAML([]byte(out))
    25  }
    26  
    27  func TestHelmTemplateParams(t *testing.T) {
    28  	h, err := NewHelmApp("./testdata/minio", []HelmRepository{}, false, "", "", "", false)
    29  	require.NoError(t, err)
    30  	opts := TemplateOpts{
    31  		Name: "test",
    32  		Set: map[string]string{
    33  			"service.type": "LoadBalancer",
    34  			"service.port": "1234",
    35  		},
    36  		SetString: map[string]string{
    37  			"service.annotations.prometheus\\.io/scrape": "true",
    38  		},
    39  	}
    40  	objs, err := template(h, &opts)
    41  	require.NoError(t, err)
    42  	assert.Len(t, objs, 5)
    43  
    44  	for _, obj := range objs {
    45  		if obj.GetKind() != "Service" || obj.GetName() != "test-minio" {
    46  			continue
    47  		}
    48  		var svc corev1.Service
    49  		err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &svc)
    50  		require.NoError(t, err)
    51  		assert.Equal(t, corev1.ServiceTypeLoadBalancer, svc.Spec.Type)
    52  		assert.Equal(t, int32(1234), svc.Spec.Ports[0].TargetPort.IntVal)
    53  		assert.Equal(t, "true", svc.Annotations["prometheus.io/scrape"])
    54  	}
    55  }
    56  
    57  func TestHelmTemplateValues(t *testing.T) {
    58  	repoRoot := "./testdata/redis"
    59  	repoRootAbs, err := filepath.Abs(repoRoot)
    60  	require.NoError(t, err)
    61  	h, err := NewHelmApp(repoRootAbs, []HelmRepository{}, false, "", "", "", false)
    62  	require.NoError(t, err)
    63  	valuesPath, _, err := path.ResolveValueFilePathOrUrl(repoRootAbs, repoRootAbs, "values-production.yaml", nil)
    64  	require.NoError(t, err)
    65  	opts := TemplateOpts{
    66  		Name:   "test",
    67  		Values: []path.ResolvedFilePath{valuesPath},
    68  	}
    69  	objs, err := template(h, &opts)
    70  	require.NoError(t, err)
    71  	assert.Len(t, objs, 8)
    72  
    73  	for _, obj := range objs {
    74  		if obj.GetKind() == "Deployment" && obj.GetName() == "test-redis-slave" {
    75  			var dep appsv1.Deployment
    76  			err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &dep)
    77  			require.NoError(t, err)
    78  			assert.Equal(t, int32(3), *dep.Spec.Replicas)
    79  		}
    80  	}
    81  }
    82  
    83  func TestHelmGetParams(t *testing.T) {
    84  	repoRoot := "./testdata/redis"
    85  	repoRootAbs, err := filepath.Abs(repoRoot)
    86  	require.NoError(t, err)
    87  	h, err := NewHelmApp(repoRootAbs, nil, false, "", "", "", false)
    88  	require.NoError(t, err)
    89  	params, err := h.GetParameters(nil, repoRootAbs, repoRootAbs)
    90  	require.NoError(t, err)
    91  
    92  	slaveCountParam := params["cluster.slaveCount"]
    93  	assert.Equal(t, "1", slaveCountParam)
    94  }
    95  
    96  func TestHelmGetParamsValueFiles(t *testing.T) {
    97  	repoRoot := "./testdata/redis"
    98  	repoRootAbs, err := filepath.Abs(repoRoot)
    99  	require.NoError(t, err)
   100  	h, err := NewHelmApp(repoRootAbs, nil, false, "", "", "", false)
   101  	require.NoError(t, err)
   102  	valuesPath, _, err := path.ResolveValueFilePathOrUrl(repoRootAbs, repoRootAbs, "values-production.yaml", nil)
   103  	require.NoError(t, err)
   104  	params, err := h.GetParameters([]path.ResolvedFilePath{valuesPath}, repoRootAbs, repoRootAbs)
   105  	require.NoError(t, err)
   106  
   107  	slaveCountParam := params["cluster.slaveCount"]
   108  	assert.Equal(t, "3", slaveCountParam)
   109  }
   110  
   111  func TestHelmGetParamsValueFilesThatExist(t *testing.T) {
   112  	repoRoot := "./testdata/redis"
   113  	repoRootAbs, err := filepath.Abs(repoRoot)
   114  	require.NoError(t, err)
   115  	h, err := NewHelmApp(repoRootAbs, nil, false, "", "", "", false)
   116  	require.NoError(t, err)
   117  	valuesMissingPath, _, err := path.ResolveValueFilePathOrUrl(repoRootAbs, repoRootAbs, "values-missing.yaml", nil)
   118  	require.NoError(t, err)
   119  	valuesProductionPath, _, err := path.ResolveValueFilePathOrUrl(repoRootAbs, repoRootAbs, "values-production.yaml", nil)
   120  	require.NoError(t, err)
   121  	params, err := h.GetParameters([]path.ResolvedFilePath{valuesMissingPath, valuesProductionPath}, repoRootAbs, repoRootAbs)
   122  	require.NoError(t, err)
   123  
   124  	slaveCountParam := params["cluster.slaveCount"]
   125  	assert.Equal(t, "3", slaveCountParam)
   126  }
   127  
   128  func TestHelmTemplateReleaseNameOverwrite(t *testing.T) {
   129  	h, err := NewHelmApp("./testdata/redis", nil, false, "", "", "", false)
   130  	require.NoError(t, err)
   131  
   132  	objs, err := template(h, &TemplateOpts{Name: "my-release"})
   133  	require.NoError(t, err)
   134  	assert.Len(t, objs, 5)
   135  
   136  	for _, obj := range objs {
   137  		if obj.GetKind() == "StatefulSet" {
   138  			var stateful appsv1.StatefulSet
   139  			err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &stateful)
   140  			require.NoError(t, err)
   141  			assert.Equal(t, "my-release-redis-master", stateful.Name)
   142  		}
   143  	}
   144  }
   145  
   146  func TestHelmTemplateReleaseName(t *testing.T) {
   147  	h, err := NewHelmApp("./testdata/redis", nil, false, "", "", "", false)
   148  	require.NoError(t, err)
   149  	objs, err := template(h, &TemplateOpts{Name: "test"})
   150  	require.NoError(t, err)
   151  	assert.Len(t, objs, 5)
   152  
   153  	for _, obj := range objs {
   154  		if obj.GetKind() == "StatefulSet" {
   155  			var stateful appsv1.StatefulSet
   156  			err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &stateful)
   157  			require.NoError(t, err)
   158  			assert.Equal(t, "test-redis-master", stateful.Name)
   159  		}
   160  	}
   161  }
   162  
   163  func TestHelmArgCleaner(t *testing.T) {
   164  	for input, expected := range map[string]string{
   165  		`val`:        `val`,
   166  		`bar`:        `bar`,
   167  		`not, clean`: `not\, clean`,
   168  		`a\,b,c`:     `a\,b\,c`,
   169  		`{a,b,c}`:    `{a,b,c}`,
   170  		`,,,,,\,`:    `\,\,\,\,\,\,`,
   171  		`\,,\\,,`:    `\,\,\\,\,`,
   172  	} {
   173  		cleaned := cleanSetParameters(input)
   174  		assert.Equal(t, expected, cleaned)
   175  	}
   176  }
   177  
   178  func TestVersion(t *testing.T) {
   179  	ver, err := Version()
   180  	require.NoError(t, err)
   181  	assert.NotEmpty(t, ver)
   182  }
   183  
   184  func Test_flatVals(t *testing.T) {
   185  	t.Run("Map", func(t *testing.T) {
   186  		output := map[string]string{}
   187  
   188  		flatVals(map[string]any{"foo": map[string]any{"bar": "baz"}}, output)
   189  
   190  		assert.Equal(t, map[string]string{"foo.bar": "baz"}, output)
   191  	})
   192  	t.Run("Array", func(t *testing.T) {
   193  		output := map[string]string{}
   194  
   195  		flatVals(map[string]any{"foo": []any{"bar", "baz"}}, output)
   196  
   197  		assert.Equal(t, map[string]string{"foo[0]": "bar", "foo[1]": "baz"}, output)
   198  	})
   199  	t.Run("Val", func(t *testing.T) {
   200  		output := map[string]string{}
   201  
   202  		flatVals(map[string]any{"foo": 1}, output)
   203  
   204  		assert.Equal(t, map[string]string{"foo": "1"}, output)
   205  	})
   206  }
   207  
   208  func TestAPIVersions(t *testing.T) {
   209  	h, err := NewHelmApp("./testdata/api-versions", nil, false, "", "", "", false)
   210  	require.NoError(t, err)
   211  
   212  	objs, err := template(h, &TemplateOpts{})
   213  	require.NoError(t, err)
   214  	require.Len(t, objs, 1)
   215  	assert.Equal(t, "sample/v1", objs[0].GetAPIVersion())
   216  
   217  	objs, err = template(h, &TemplateOpts{APIVersions: []string{"sample/v2"}})
   218  	require.NoError(t, err)
   219  	require.Len(t, objs, 1)
   220  	assert.Equal(t, "sample/v2", objs[0].GetAPIVersion())
   221  }
   222  
   223  func TestKubeVersionWithSymbol(t *testing.T) {
   224  	h, err := NewHelmApp("./testdata/tests", nil, false, "", "", "", false)
   225  	require.NoError(t, err)
   226  
   227  	objs, err := template(h, &TemplateOpts{KubeVersion: "1.30.11+IKS"})
   228  	require.NoError(t, err)
   229  	require.Len(t, objs, 2)
   230  
   231  	for _, obj := range objs {
   232  		if obj.GetKind() != "ConfigMap" {
   233  			continue
   234  		}
   235  		var configMap corev1.ConfigMap
   236  		err := runtime.DefaultUnstructuredConverter.FromUnstructured(obj.Object, &configMap)
   237  		require.NoError(t, err)
   238  		if data, ok := configMap.Data["kubeVersion"]; ok {
   239  			assert.Equal(t, "v1.30.11+IKS", data)
   240  			return
   241  		}
   242  		t.Fatal("expected kubeVersion key not found in configMap")
   243  	}
   244  }
   245  
   246  func TestSkipCrds(t *testing.T) {
   247  	h, err := NewHelmApp("./testdata/crds", nil, false, "", "", "", false)
   248  	require.NoError(t, err)
   249  
   250  	objs, err := template(h, &TemplateOpts{SkipCrds: false})
   251  	require.NoError(t, err)
   252  	require.Len(t, objs, 1)
   253  
   254  	objs, err = template(h, &TemplateOpts{})
   255  	require.NoError(t, err)
   256  	require.Len(t, objs, 1)
   257  
   258  	objs, err = template(h, &TemplateOpts{SkipCrds: true})
   259  	require.NoError(t, err)
   260  	require.Empty(t, objs)
   261  }
   262  
   263  func TestSkipTests(t *testing.T) {
   264  	h, err := NewHelmApp("./testdata/tests", nil, false, "", "", "", false)
   265  	require.NoError(t, err)
   266  
   267  	objs, err := template(h, &TemplateOpts{SkipTests: false})
   268  	require.NoError(t, err)
   269  	require.Len(t, objs, 2)
   270  
   271  	objs, err = template(h, &TemplateOpts{})
   272  	require.NoError(t, err)
   273  	require.Len(t, objs, 2)
   274  
   275  	objs, err = template(h, &TemplateOpts{SkipTests: true})
   276  	require.NoError(t, err)
   277  	require.Empty(t, objs)
   278  }