github.com/amy/helm@v2.7.2+incompatible/cmd/helm/install_test.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors All rights reserved. 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 28 "k8s.io/helm/pkg/helm" 29 ) 30 31 func TestInstall(t *testing.T) { 32 tests := []releaseCase{ 33 // Install, base case 34 { 35 name: "basic install", 36 args: []string{"testdata/testcharts/alpine"}, 37 flags: strings.Split("--name aeneas", " "), 38 expected: "aeneas", 39 resp: releaseMock(&releaseOptions{name: "aeneas"}), 40 }, 41 // Install, no hooks 42 { 43 name: "install without hooks", 44 args: []string{"testdata/testcharts/alpine"}, 45 flags: strings.Split("--name aeneas --no-hooks", " "), 46 expected: "juno", 47 resp: releaseMock(&releaseOptions{name: "juno"}), 48 }, 49 // Install, values from cli 50 { 51 name: "install with values", 52 args: []string{"testdata/testcharts/alpine"}, 53 flags: strings.Split("--set foo=bar", " "), 54 resp: releaseMock(&releaseOptions{name: "virgil"}), 55 expected: "virgil", 56 }, 57 // Install, values from cli via multiple --set 58 { 59 name: "install with multiple values", 60 args: []string{"testdata/testcharts/alpine"}, 61 flags: strings.Split("--set foo=bar", "--set bar=foo"), 62 resp: releaseMock(&releaseOptions{name: "virgil"}), 63 expected: "virgil", 64 }, 65 // Install, values from yaml 66 { 67 name: "install with values", 68 args: []string{"testdata/testcharts/alpine"}, 69 flags: strings.Split("-f testdata/testcharts/alpine/extra_values.yaml", " "), 70 resp: releaseMock(&releaseOptions{name: "virgil"}), 71 expected: "virgil", 72 }, 73 // Install, values from multiple yaml 74 { 75 name: "install with values", 76 args: []string{"testdata/testcharts/alpine"}, 77 flags: strings.Split("-f testdata/testcharts/alpine/extra_values.yaml -f testdata/testcharts/alpine/more_values.yaml", " "), 78 resp: releaseMock(&releaseOptions{name: "virgil"}), 79 expected: "virgil", 80 }, 81 // Install, no charts 82 { 83 name: "install with no chart specified", 84 args: []string{}, 85 err: true, 86 }, 87 // Install, re-use name 88 { 89 name: "install and replace release", 90 args: []string{"testdata/testcharts/alpine"}, 91 flags: strings.Split("--name aeneas --replace", " "), 92 expected: "aeneas", 93 resp: releaseMock(&releaseOptions{name: "aeneas"}), 94 }, 95 // Install, with timeout 96 { 97 name: "install with a timeout", 98 args: []string{"testdata/testcharts/alpine"}, 99 flags: strings.Split("--timeout 120", " "), 100 expected: "foobar", 101 resp: releaseMock(&releaseOptions{name: "foobar"}), 102 }, 103 // Install, with wait 104 { 105 name: "install with a wait", 106 args: []string{"testdata/testcharts/alpine"}, 107 flags: strings.Split("--wait", " "), 108 expected: "apollo", 109 resp: releaseMock(&releaseOptions{name: "apollo"}), 110 }, 111 // Install, using the name-template 112 { 113 name: "install with name-template", 114 args: []string{"testdata/testcharts/alpine"}, 115 flags: []string{"--name-template", "{{upper \"foobar\"}}"}, 116 expected: "FOOBAR", 117 resp: releaseMock(&releaseOptions{name: "FOOBAR"}), 118 }, 119 // Install, perform chart verification along the way. 120 { 121 name: "install with verification, missing provenance", 122 args: []string{"testdata/testcharts/compressedchart-0.1.0.tgz"}, 123 flags: strings.Split("--verify --keyring testdata/helm-test-key.pub", " "), 124 err: true, 125 }, 126 { 127 name: "install with verification, directory instead of file", 128 args: []string{"testdata/testcharts/signtest"}, 129 flags: strings.Split("--verify --keyring testdata/helm-test-key.pub", " "), 130 err: true, 131 }, 132 { 133 name: "install with verification, valid", 134 args: []string{"testdata/testcharts/signtest-0.1.0.tgz"}, 135 flags: strings.Split("--verify --keyring testdata/helm-test-key.pub", " "), 136 }, 137 // Install, chart with missing dependencies in /charts 138 { 139 name: "install chart with missing dependencies", 140 args: []string{"testdata/testcharts/chart-missing-deps"}, 141 err: true, 142 }, 143 // Install, chart with bad requirements.yaml in /charts 144 { 145 name: "install chart with bad requirements.yaml", 146 args: []string{"testdata/testcharts/chart-bad-requirements"}, 147 err: true, 148 }, 149 } 150 151 runReleaseCases(t, tests, func(c *helm.FakeClient, out io.Writer) *cobra.Command { 152 return newInstallCmd(c, out) 153 }) 154 } 155 156 type nameTemplateTestCase struct { 157 tpl string 158 expected string 159 expectedErrorStr string 160 } 161 162 func TestNameTemplate(t *testing.T) { 163 testCases := []nameTemplateTestCase{ 164 // Just a straight up nop please 165 { 166 tpl: "foobar", 167 expected: "foobar", 168 expectedErrorStr: "", 169 }, 170 // Random numbers at the end for fun & profit 171 { 172 tpl: "foobar-{{randNumeric 6}}", 173 expected: "foobar-[0-9]{6}$", 174 expectedErrorStr: "", 175 }, 176 // Random numbers in the middle for fun & profit 177 { 178 tpl: "foobar-{{randNumeric 4}}-baz", 179 expected: "foobar-[0-9]{4}-baz$", 180 expectedErrorStr: "", 181 }, 182 // No such function 183 { 184 tpl: "foobar-{{randInt}}", 185 expected: "", 186 expectedErrorStr: "function \"randInt\" not defined", 187 }, 188 // Invalid template 189 { 190 tpl: "foobar-{{", 191 expected: "", 192 expectedErrorStr: "unexpected unclosed action", 193 }, 194 } 195 196 for _, tc := range testCases { 197 198 n, err := generateName(tc.tpl) 199 if err != nil { 200 if tc.expectedErrorStr == "" { 201 t.Errorf("Was not expecting error, but got: %v", err) 202 continue 203 } 204 re, compErr := regexp.Compile(tc.expectedErrorStr) 205 if compErr != nil { 206 t.Errorf("Expected error string failed to compile: %v", compErr) 207 continue 208 } 209 if !re.MatchString(err.Error()) { 210 t.Errorf("Error didn't match for %s expected %s but got %v", tc.tpl, tc.expectedErrorStr, err) 211 continue 212 } 213 } 214 if err == nil && tc.expectedErrorStr != "" { 215 t.Errorf("Was expecting error %s but didn't get an error back", tc.expectedErrorStr) 216 } 217 218 if tc.expected != "" { 219 re, err := regexp.Compile(tc.expected) 220 if err != nil { 221 t.Errorf("Expected string failed to compile: %v", err) 222 continue 223 } 224 if !re.MatchString(n) { 225 t.Errorf("Returned name didn't match for %s expected %s but got %s", tc.tpl, tc.expected, n) 226 } 227 } 228 } 229 } 230 231 func TestMergeValues(t *testing.T) { 232 nestedMap := map[string]interface{}{ 233 "foo": "bar", 234 "baz": map[string]string{ 235 "cool": "stuff", 236 }, 237 } 238 anotherNestedMap := map[string]interface{}{ 239 "foo": "bar", 240 "baz": map[string]string{ 241 "cool": "things", 242 "awesome": "stuff", 243 }, 244 } 245 flatMap := map[string]interface{}{ 246 "foo": "bar", 247 "baz": "stuff", 248 } 249 anotherFlatMap := map[string]interface{}{ 250 "testing": "fun", 251 } 252 253 testMap := mergeValues(flatMap, nestedMap) 254 equal := reflect.DeepEqual(testMap, nestedMap) 255 if !equal { 256 t.Errorf("Expected a nested map to overwrite a flat value. Expected: %v, got %v", nestedMap, testMap) 257 } 258 259 testMap = mergeValues(nestedMap, flatMap) 260 equal = reflect.DeepEqual(testMap, flatMap) 261 if !equal { 262 t.Errorf("Expected a flat value to overwrite a map. Expected: %v, got %v", flatMap, testMap) 263 } 264 265 testMap = mergeValues(nestedMap, anotherNestedMap) 266 equal = reflect.DeepEqual(testMap, anotherNestedMap) 267 if !equal { 268 t.Errorf("Expected a nested map to overwrite another nested map. Expected: %v, got %v", anotherNestedMap, testMap) 269 } 270 271 testMap = mergeValues(anotherFlatMap, anotherNestedMap) 272 expectedMap := map[string]interface{}{ 273 "testing": "fun", 274 "foo": "bar", 275 "baz": map[string]string{ 276 "cool": "things", 277 "awesome": "stuff", 278 }, 279 } 280 equal = reflect.DeepEqual(testMap, expectedMap) 281 if !equal { 282 t.Errorf("Expected a map with different keys to merge properly with another map. Expected: %v, got %v", expectedMap, testMap) 283 } 284 }