github.com/caicloud/helm@v2.5.0+incompatible/pkg/chartutil/requirements_test.go (about) 1 /* 2 Copyright 2016 The Kubernetes Authors All rights reserved. 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 */ 15 package chartutil 16 17 import ( 18 "sort" 19 "testing" 20 21 "strconv" 22 23 "k8s.io/helm/pkg/proto/hapi/chart" 24 ) 25 26 func TestLoadRequirements(t *testing.T) { 27 c, err := Load("testdata/frobnitz") 28 if err != nil { 29 t.Fatalf("Failed to load testdata: %s", err) 30 } 31 verifyRequirements(t, c) 32 } 33 34 func TestLoadRequirementsLock(t *testing.T) { 35 c, err := Load("testdata/frobnitz") 36 if err != nil { 37 t.Fatalf("Failed to load testdata: %s", err) 38 } 39 verifyRequirementsLock(t, c) 40 } 41 func TestRequirementsTagsNonValue(t *testing.T) { 42 c, err := Load("testdata/subpop") 43 if err != nil { 44 t.Fatalf("Failed to load testdata: %s", err) 45 } 46 // tags with no effect 47 v := &chart.Config{Raw: "tags:\n nothinguseful: false\n\n"} 48 // expected charts including duplicates in alphanumeric order 49 e := []string{"parentchart", "subchart1", "subcharta", "subchartb"} 50 51 verifyRequirementsEnabled(t, c, v, e) 52 } 53 func TestRequirementsTagsDisabledL1(t *testing.T) { 54 c, err := Load("testdata/subpop") 55 if err != nil { 56 t.Fatalf("Failed to load testdata: %s", err) 57 } 58 // tags disabling a group 59 v := &chart.Config{Raw: "tags:\n front-end: false\n\n"} 60 // expected charts including duplicates in alphanumeric order 61 e := []string{"parentchart"} 62 63 verifyRequirementsEnabled(t, c, v, e) 64 } 65 func TestRequirementsTagsEnabledL1(t *testing.T) { 66 c, err := Load("testdata/subpop") 67 if err != nil { 68 t.Fatalf("Failed to load testdata: %s", err) 69 } 70 // tags disabling a group and enabling a different group 71 v := &chart.Config{Raw: "tags:\n front-end: false\n\n back-end: true\n"} 72 // expected charts including duplicates in alphanumeric order 73 e := []string{"parentchart", "subchart2", "subchartb", "subchartc"} 74 75 verifyRequirementsEnabled(t, c, v, e) 76 } 77 78 func TestRequirementsTagsDisabledL2(t *testing.T) { 79 c, err := Load("testdata/subpop") 80 if err != nil { 81 t.Fatalf("Failed to load testdata: %s", err) 82 } 83 // tags disabling only children, children still enabled since tag front-end=true in values.yaml 84 v := &chart.Config{Raw: "tags:\n subcharta: false\n\n subchartb: false\n"} 85 // expected charts including duplicates in alphanumeric order 86 e := []string{"parentchart", "subchart1", "subcharta", "subchartb"} 87 88 verifyRequirementsEnabled(t, c, v, e) 89 } 90 func TestRequirementsTagsDisabledL1Mixed(t *testing.T) { 91 c, err := Load("testdata/subpop") 92 if err != nil { 93 t.Fatalf("Failed to load testdata: %s", err) 94 } 95 // tags disabling all parents/children with additional tag re-enabling a parent 96 v := &chart.Config{Raw: "tags:\n front-end: false\n\n subchart1: true\n\n back-end: false\n"} 97 // expected charts including duplicates in alphanumeric order 98 e := []string{"parentchart", "subchart1"} 99 100 verifyRequirementsEnabled(t, c, v, e) 101 } 102 func TestRequirementsConditionsNonValue(t *testing.T) { 103 c, err := Load("testdata/subpop") 104 if err != nil { 105 t.Fatalf("Failed to load testdata: %s", err) 106 } 107 // tags with no effect 108 v := &chart.Config{Raw: "subchart1:\n nothinguseful: false\n\n"} 109 // expected charts including duplicates in alphanumeric order 110 e := []string{"parentchart", "subchart1", "subcharta", "subchartb"} 111 112 verifyRequirementsEnabled(t, c, v, e) 113 } 114 func TestRequirementsConditionsEnabledL1Both(t *testing.T) { 115 c, err := Load("testdata/subpop") 116 if err != nil { 117 t.Fatalf("Failed to load testdata: %s", err) 118 } 119 // conditions enabling the parent charts, but back-end (b, c) is still disabled via values.yaml 120 v := &chart.Config{Raw: "subchart1:\n enabled: true\nsubchart2:\n enabled: true\n"} 121 // expected charts including duplicates in alphanumeric order 122 e := []string{"parentchart", "subchart1", "subchart2", "subcharta", "subchartb"} 123 124 verifyRequirementsEnabled(t, c, v, e) 125 } 126 func TestRequirementsConditionsDisabledL1Both(t *testing.T) { 127 c, err := Load("testdata/subpop") 128 if err != nil { 129 t.Fatalf("Failed to load testdata: %s", err) 130 } 131 // conditions disabling the parent charts, effectively disabling children 132 v := &chart.Config{Raw: "subchart1:\n enabled: false\nsubchart2:\n enabled: false\n"} 133 // expected charts including duplicates in alphanumeric order 134 e := []string{"parentchart"} 135 136 verifyRequirementsEnabled(t, c, v, e) 137 } 138 139 func TestRequirementsConditionsSecond(t *testing.T) { 140 c, err := Load("testdata/subpop") 141 if err != nil { 142 t.Fatalf("Failed to load testdata: %s", err) 143 } 144 // conditions a child using the second condition path of child's condition 145 v := &chart.Config{Raw: "subchart1:\n subcharta:\n enabled: false\n"} 146 // expected charts including duplicates in alphanumeric order 147 e := []string{"parentchart", "subchart1", "subchartb"} 148 149 verifyRequirementsEnabled(t, c, v, e) 150 } 151 func TestRequirementsCombinedDisabledL2(t *testing.T) { 152 c, err := Load("testdata/subpop") 153 if err != nil { 154 t.Fatalf("Failed to load testdata: %s", err) 155 } 156 // tags enabling a parent/child group with condition disabling one child 157 v := &chart.Config{Raw: "subchartc:\n enabled: false\ntags:\n back-end: true\n"} 158 // expected charts including duplicates in alphanumeric order 159 e := []string{"parentchart", "subchart1", "subchart2", "subcharta", "subchartb", "subchartb"} 160 161 verifyRequirementsEnabled(t, c, v, e) 162 } 163 func TestRequirementsCombinedDisabledL1(t *testing.T) { 164 c, err := Load("testdata/subpop") 165 if err != nil { 166 t.Fatalf("Failed to load testdata: %s", err) 167 } 168 // tags will not enable a child if parent is explicitly disabled with condition 169 v := &chart.Config{Raw: "subchart1:\n enabled: false\ntags:\n front-end: true\n"} 170 // expected charts including duplicates in alphanumeric order 171 e := []string{"parentchart"} 172 173 verifyRequirementsEnabled(t, c, v, e) 174 } 175 176 func verifyRequirementsEnabled(t *testing.T, c *chart.Chart, v *chart.Config, e []string) { 177 out := []*chart.Chart{} 178 err := ProcessRequirementsEnabled(c, v) 179 if err != nil { 180 t.Errorf("Error processing enabled requirements %v", err) 181 } 182 out = extractCharts(c, out) 183 // build list of chart names 184 p := []string{} 185 for _, r := range out { 186 p = append(p, r.Metadata.Name) 187 } 188 //sort alphanumeric and compare to expectations 189 sort.Strings(p) 190 if len(p) != len(e) { 191 t.Errorf("Error slice lengths do not match got %v, expected %v", len(p), len(e)) 192 return 193 } 194 for i := range p { 195 if p[i] != e[i] { 196 t.Errorf("Error slice values do not match got %v, expected %v", p[i], e[i]) 197 } 198 } 199 } 200 201 // extractCharts recursively searches chart dependencies returning all charts found 202 func extractCharts(c *chart.Chart, out []*chart.Chart) []*chart.Chart { 203 204 if len(c.Metadata.Name) > 0 { 205 out = append(out, c) 206 } 207 for _, d := range c.Dependencies { 208 out = extractCharts(d, out) 209 } 210 return out 211 } 212 func TestProcessRequirementsImportValues(t *testing.T) { 213 c, err := Load("testdata/subpop") 214 if err != nil { 215 t.Fatalf("Failed to load testdata: %s", err) 216 } 217 218 v := &chart.Config{Raw: ""} 219 220 e := make(map[string]string) 221 222 e["imported-chart1.SC1bool"] = "true" 223 e["imported-chart1.SC1float"] = "3.14" 224 e["imported-chart1.SC1int"] = "100" 225 e["imported-chart1.SC1string"] = "dollywood" 226 e["imported-chart1.SC1extra1"] = "11" 227 e["imported-chart1.SPextra1"] = "helm rocks" 228 e["imported-chart1.SC1extra1"] = "11" 229 230 e["imported-chartA.SCAbool"] = "false" 231 e["imported-chartA.SCAfloat"] = "3.1" 232 e["imported-chartA.SCAint"] = "55" 233 e["imported-chartA.SCAstring"] = "jabba" 234 e["imported-chartA.SPextra3"] = "1.337" 235 e["imported-chartA.SC1extra2"] = "1.337" 236 e["imported-chartA.SCAnested1.SCAnested2"] = "true" 237 238 e["imported-chartA-B.SCAbool"] = "false" 239 e["imported-chartA-B.SCAfloat"] = "3.1" 240 e["imported-chartA-B.SCAint"] = "55" 241 e["imported-chartA-B.SCAstring"] = "jabba" 242 243 e["imported-chartA-B.SCBbool"] = "true" 244 e["imported-chartA-B.SCBfloat"] = "7.77" 245 e["imported-chartA-B.SCBint"] = "33" 246 e["imported-chartA-B.SCBstring"] = "boba" 247 e["imported-chartA-B.SPextra5"] = "k8s" 248 e["imported-chartA-B.SC1extra5"] = "tiller" 249 250 e["overridden-chart1.SC1bool"] = "false" 251 e["overridden-chart1.SC1float"] = "3.141592" 252 e["overridden-chart1.SC1int"] = "99" 253 e["overridden-chart1.SC1string"] = "pollywog" 254 e["overridden-chart1.SPextra2"] = "42" 255 256 e["overridden-chartA.SCAbool"] = "true" 257 e["overridden-chartA.SCAfloat"] = "41.3" 258 e["overridden-chartA.SCAint"] = "808" 259 e["overridden-chartA.SCAstring"] = "jaberwocky" 260 e["overridden-chartA.SPextra4"] = "true" 261 262 e["overridden-chartA-B.SCAbool"] = "true" 263 e["overridden-chartA-B.SCAfloat"] = "41.3" 264 e["overridden-chartA-B.SCAint"] = "808" 265 e["overridden-chartA-B.SCAstring"] = "jaberwocky" 266 e["overridden-chartA-B.SCBbool"] = "false" 267 e["overridden-chartA-B.SCBfloat"] = "1.99" 268 e["overridden-chartA-B.SCBint"] = "77" 269 e["overridden-chartA-B.SCBstring"] = "jango" 270 e["overridden-chartA-B.SPextra6"] = "111" 271 e["overridden-chartA-B.SCAextra1"] = "23" 272 e["overridden-chartA-B.SCBextra1"] = "13" 273 e["overridden-chartA-B.SC1extra6"] = "77" 274 275 // `exports` style 276 e["SCBexported1B"] = "1965" 277 e["SC1extra7"] = "true" 278 e["SCBexported2A"] = "blaster" 279 e["global.SC1exported2.all.SC1exported3"] = "SC1expstr" 280 281 verifyRequirementsImportValues(t, c, v, e) 282 } 283 func verifyRequirementsImportValues(t *testing.T, c *chart.Chart, v *chart.Config, e map[string]string) { 284 285 err := ProcessRequirementsImportValues(c) 286 if err != nil { 287 t.Errorf("Error processing import values requirements %v", err) 288 } 289 cv := c.GetValues() 290 cc, err := ReadValues([]byte(cv.Raw)) 291 if err != nil { 292 t.Errorf("Error reading import values %v", err) 293 } 294 for kk, vv := range e { 295 pv, err := cc.PathValue(kk) 296 if err != nil { 297 t.Fatalf("Error retrieving import values table %v %v", kk, err) 298 return 299 } 300 301 switch pv.(type) { 302 case float64: 303 s := strconv.FormatFloat(pv.(float64), 'f', -1, 64) 304 if s != vv { 305 t.Errorf("Failed to match imported float value %v with expected %v", s, vv) 306 return 307 } 308 case bool: 309 b := strconv.FormatBool(pv.(bool)) 310 if b != vv { 311 t.Errorf("Failed to match imported bool value %v with expected %v", b, vv) 312 return 313 } 314 default: 315 if pv.(string) != vv { 316 t.Errorf("Failed to match imported string value %v with expected %v", pv, vv) 317 return 318 } 319 } 320 321 } 322 } 323 324 func TestGetAliasDependency(t *testing.T) { 325 c, err := Load("testdata/frobnitz") 326 if err != nil { 327 t.Fatalf("Failed to load testdata: %s", err) 328 } 329 req, err := LoadRequirements(c) 330 if err != nil { 331 t.Fatalf("Failed to load requirement for testdata: %s", err) 332 } 333 if len(req.Dependencies) == 0 { 334 t.Fatalf("There are no requirements to test") 335 } 336 337 // Success case 338 aliasChart := getAliasDependency(c.Dependencies, req.Dependencies[0]) 339 if aliasChart == nil { 340 t.Fatalf("Failed to get dependency chart for alias %s", req.Dependencies[0].Name) 341 } 342 if req.Dependencies[0].Alias != "" { 343 if aliasChart.Metadata.Name != req.Dependencies[0].Alias { 344 t.Fatalf("Dependency chart name should be %s but got %s", req.Dependencies[0].Alias, aliasChart.Metadata.Name) 345 } 346 } else if aliasChart.Metadata.Name != req.Dependencies[0].Name { 347 t.Fatalf("Dependency chart name should be %s but got %s", req.Dependencies[0].Name, aliasChart.Metadata.Name) 348 } 349 350 // Failure case 351 req.Dependencies[0].Name = "something-else" 352 if aliasChart := getAliasDependency(c.Dependencies, req.Dependencies[0]); aliasChart != nil { 353 t.Fatalf("expected no chart but got %s", aliasChart.Metadata.Name) 354 } 355 } 356 357 func TestDependentChartAliases(t *testing.T) { 358 c, err := Load("testdata/dependent-chart-alias") 359 if err != nil { 360 t.Fatalf("Failed to load testdata: %s", err) 361 } 362 363 if len(c.Dependencies) == 0 { 364 t.Fatal("There are no dependencies to run this test") 365 } 366 367 origLength := len(c.Dependencies) 368 if err := ProcessRequirementsEnabled(c, c.Values); err != nil { 369 t.Fatalf("Expected no errors but got %q", err) 370 } 371 372 if len(c.Dependencies) == origLength { 373 t.Fatal("Expected alias dependencies to be added, but did not got that") 374 } 375 376 reqmts, err := LoadRequirements(c) 377 if err != nil { 378 t.Fatalf("Cannot load requirements for test chart, %v", err) 379 } 380 381 // var expectedDependencyCharts int 382 // for _, reqmt := range reqmts.Dependencies { 383 // expectedDependencyCharts++ 384 // if len(reqmt.Alias) >= 0 { 385 // expectedDependencyCharts += len(reqmt.Alias) 386 // } 387 // } 388 if len(c.Dependencies) != len(reqmts.Dependencies) { 389 t.Fatalf("Expected number of chart dependencies %d, but got %d", len(reqmts.Dependencies), len(c.Dependencies)) 390 } 391 392 }