github.com/defensepoint-snyk-test/helm-new@v0.0.0-20211130153739-c57ea64d6603/cmd/helm/install_test.go (about) 1 /* 2 Copyright The Helm Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package main 18 19 import ( 20 "io" 21 "reflect" 22 "regexp" 23 "strings" 24 "testing" 25 26 "github.com/spf13/cobra" 27 "k8s.io/helm/pkg/helm" 28 ) 29 30 func TestInstall(t *testing.T) { 31 tests := []releaseCase{ 32 // Install, base case 33 { 34 name: "basic install", 35 args: []string{"testdata/testcharts/alpine"}, 36 flags: strings.Split("--name aeneas", " "), 37 expected: "aeneas", 38 resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}), 39 }, 40 // Install, no hooks 41 { 42 name: "install without hooks", 43 args: []string{"testdata/testcharts/alpine"}, 44 flags: strings.Split("--name aeneas --no-hooks", " "), 45 expected: "aeneas", 46 resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}), 47 }, 48 // Install, values from cli 49 { 50 name: "install with values", 51 args: []string{"testdata/testcharts/alpine"}, 52 flags: strings.Split("--name virgil --set foo=bar", " "), 53 resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil"}), 54 expected: "virgil", 55 }, 56 // Install, values from cli via multiple --set 57 { 58 name: "install with multiple values", 59 args: []string{"testdata/testcharts/alpine"}, 60 flags: strings.Split("--name virgil --set foo=bar --set bar=foo", " "), 61 resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil"}), 62 expected: "virgil", 63 }, 64 { 65 name: "install with multiple unordered list values", 66 args: []string{"testdata/testcharts/alpine"}, 67 flags: strings.Split("--name virgil --set foo[1].bar=baz,foo[0].baz=bar", " "), 68 resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil"}), 69 expected: "virgil", 70 }, 71 { 72 name: "install with values", 73 args: []string{"testdata/testcharts/alpine"}, 74 flags: strings.Split("--name virgil -f testdata/testcharts/alpine/extra_values.yaml", " "), 75 resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil"}), 76 expected: "virgil", 77 }, 78 // Install, values from multiple yaml 79 { 80 name: "install with values", 81 args: []string{"testdata/testcharts/alpine"}, 82 flags: strings.Split("--name virgil -f testdata/testcharts/alpine/extra_values.yaml -f testdata/testcharts/alpine/more_values.yaml", " "), 83 resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil"}), 84 expected: "virgil", 85 }, 86 // Install, no charts 87 { 88 name: "install with no chart specified", 89 args: []string{}, 90 err: true, 91 }, 92 // Install, re-use name 93 { 94 name: "install and replace release", 95 args: []string{"testdata/testcharts/alpine"}, 96 flags: strings.Split("--name aeneas --replace", " "), 97 expected: "aeneas", 98 resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "aeneas"}), 99 }, 100 // Install, with timeout 101 { 102 name: "install with a timeout", 103 args: []string{"testdata/testcharts/alpine"}, 104 flags: strings.Split("--name foobar --timeout 120", " "), 105 expected: "foobar", 106 resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "foobar"}), 107 }, 108 // Install, with wait 109 { 110 name: "install with a wait", 111 args: []string{"testdata/testcharts/alpine"}, 112 flags: strings.Split("--name apollo --wait", " "), 113 expected: "apollo", 114 resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "apollo"}), 115 }, 116 // Install, using the name-template 117 { 118 name: "install with name-template", 119 args: []string{"testdata/testcharts/alpine"}, 120 flags: []string{"--name-template", "{{lower \"FOOBAR\"}}"}, 121 expected: "foobar", 122 resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "foobar"}), 123 }, 124 { 125 name: "install with custom description", 126 args: []string{"testdata/testcharts/alpine"}, 127 flags: []string{"--name", "virgil", "--description", "foobar"}, 128 expected: "virgil", 129 resp: helm.ReleaseMock(&helm.MockReleaseOptions{Name: "virgil", Description: "foobar"}), 130 }, 131 // Install, perform chart verification along the way. 132 { 133 name: "install with verification, missing provenance", 134 args: []string{"testdata/testcharts/compressedchart-0.1.0.tgz"}, 135 flags: strings.Split("--verify --keyring testdata/helm-test-key.pub", " "), 136 err: true, 137 }, 138 { 139 name: "install with verification, directory instead of file", 140 args: []string{"testdata/testcharts/signtest"}, 141 flags: strings.Split("--verify --keyring testdata/helm-test-key.pub", " "), 142 err: true, 143 }, 144 { 145 name: "install with verification, valid", 146 args: []string{"testdata/testcharts/signtest-0.1.0.tgz"}, 147 flags: strings.Split("--verify --keyring testdata/helm-test-key.pub", " "), 148 }, 149 // Install, chart with missing dependencies in /charts 150 { 151 name: "install chart with missing dependencies", 152 args: []string{"testdata/testcharts/chart-missing-deps"}, 153 err: true, 154 }, 155 // Install, chart with bad requirements.yaml in /charts 156 { 157 name: "install chart with bad requirements.yaml", 158 args: []string{"testdata/testcharts/chart-bad-requirements"}, 159 err: true, 160 }, 161 // Install, using a bad release name 162 { 163 name: "install chart with release name using capitals", 164 args: []string{"testdata/testcharts/alpine"}, 165 flags: []string{"--name", "FOO"}, 166 err: true, 167 }, 168 { 169 name: "install chart with release name using periods", 170 args: []string{"testdata/testcharts/alpine"}, 171 flags: []string{"--name", "foo.bar"}, 172 err: true, 173 }, 174 { 175 name: "install chart with release name using underscores", 176 args: []string{"testdata/testcharts/alpine"}, 177 flags: []string{"--name", "foo_bar"}, 178 err: true, 179 }, 180 // Install, using a bad name-template 181 { 182 name: "install with name-template", 183 args: []string{"testdata/testcharts/alpine"}, 184 flags: []string{"--name-template", "{{UPPER \"foobar\"}}"}, 185 err: true, 186 }, 187 } 188 189 runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command { 190 return newInstallCmd(c, out) 191 }) 192 } 193 194 type nameTemplateTestCase struct { 195 tpl string 196 expected string 197 expectedErrorStr string 198 } 199 200 func TestNameTemplate(t *testing.T) { 201 testCases := []nameTemplateTestCase{ 202 // Just a straight up nop please 203 { 204 tpl: "foobar", 205 expected: "foobar", 206 expectedErrorStr: "", 207 }, 208 // Random numbers at the end for fun & profit 209 { 210 tpl: "foobar-{{randNumeric 6}}", 211 expected: "foobar-[0-9]{6}$", 212 expectedErrorStr: "", 213 }, 214 // Random numbers in the middle for fun & profit 215 { 216 tpl: "foobar-{{randNumeric 4}}-baz", 217 expected: "foobar-[0-9]{4}-baz$", 218 expectedErrorStr: "", 219 }, 220 // No such function 221 { 222 tpl: "foobar-{{randInt}}", 223 expected: "", 224 expectedErrorStr: "function \"randInt\" not defined", 225 }, 226 // Invalid template 227 { 228 tpl: "foobar-{{", 229 expected: "", 230 expectedErrorStr: "unexpected unclosed action", 231 }, 232 } 233 234 for _, tc := range testCases { 235 236 n, err := generateName(tc.tpl) 237 if err != nil { 238 if tc.expectedErrorStr == "" { 239 t.Errorf("Was not expecting error, but got: %v", err) 240 continue 241 } 242 re, compErr := regexp.Compile(tc.expectedErrorStr) 243 if compErr != nil { 244 t.Errorf("Expected error string failed to compile: %v", compErr) 245 continue 246 } 247 if !re.MatchString(err.Error()) { 248 t.Errorf("Error didn't match for %s expected %s but got %v", tc.tpl, tc.expectedErrorStr, err) 249 continue 250 } 251 } 252 if err == nil && tc.expectedErrorStr != "" { 253 t.Errorf("Was expecting error %s but didn't get an error back", tc.expectedErrorStr) 254 } 255 256 if tc.expected != "" { 257 re, err := regexp.Compile(tc.expected) 258 if err != nil { 259 t.Errorf("Expected string failed to compile: %v", err) 260 continue 261 } 262 if !re.MatchString(n) { 263 t.Errorf("Returned name didn't match for %s expected %s but got %s", tc.tpl, tc.expected, n) 264 } 265 } 266 } 267 } 268 269 func TestMergeValues(t *testing.T) { 270 nestedMap := map[string]interface{}{ 271 "foo": "bar", 272 "baz": map[string]string{ 273 "cool": "stuff", 274 }, 275 } 276 anotherNestedMap := map[string]interface{}{ 277 "foo": "bar", 278 "baz": map[string]string{ 279 "cool": "things", 280 "awesome": "stuff", 281 }, 282 } 283 flatMap := map[string]interface{}{ 284 "foo": "bar", 285 "baz": "stuff", 286 } 287 anotherFlatMap := map[string]interface{}{ 288 "testing": "fun", 289 } 290 291 testMap := mergeValues(flatMap, nestedMap) 292 equal := reflect.DeepEqual(testMap, nestedMap) 293 if !equal { 294 t.Errorf("Expected a nested map to overwrite a flat value. Expected: %v, got %v", nestedMap, testMap) 295 } 296 297 testMap = mergeValues(nestedMap, flatMap) 298 equal = reflect.DeepEqual(testMap, flatMap) 299 if !equal { 300 t.Errorf("Expected a flat value to overwrite a map. Expected: %v, got %v", flatMap, testMap) 301 } 302 303 testMap = mergeValues(nestedMap, anotherNestedMap) 304 equal = reflect.DeepEqual(testMap, anotherNestedMap) 305 if !equal { 306 t.Errorf("Expected a nested map to overwrite another nested map. Expected: %v, got %v", anotherNestedMap, testMap) 307 } 308 309 testMap = mergeValues(anotherFlatMap, anotherNestedMap) 310 expectedMap := map[string]interface{}{ 311 "testing": "fun", 312 "foo": "bar", 313 "baz": map[string]string{ 314 "cool": "things", 315 "awesome": "stuff", 316 }, 317 } 318 equal = reflect.DeepEqual(testMap, expectedMap) 319 if !equal { 320 t.Errorf("Expected a map with different keys to merge properly with another map. Expected: %v, got %v", expectedMap, testMap) 321 } 322 }