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 }