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