github.com/strongmonkey/helm@v2.7.2+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 "k8s.io/helm/pkg/version" 25 ) 26 27 func TestLoadRequirements(t *testing.T) { 28 c, err := Load("testdata/frobnitz") 29 if err != nil { 30 t.Fatalf("Failed to load testdata: %s", err) 31 } 32 verifyRequirements(t, c) 33 } 34 35 func TestLoadRequirementsLock(t *testing.T) { 36 c, err := Load("testdata/frobnitz") 37 if err != nil { 38 t.Fatalf("Failed to load testdata: %s", err) 39 } 40 verifyRequirementsLock(t, c) 41 } 42 func TestRequirementsTagsNonValue(t *testing.T) { 43 c, err := Load("testdata/subpop") 44 if err != nil { 45 t.Fatalf("Failed to load testdata: %s", err) 46 } 47 // tags with no effect 48 v := &chart.Config{Raw: "tags:\n nothinguseful: false\n\n"} 49 // expected charts including duplicates in alphanumeric order 50 e := []string{"parentchart", "subchart1", "subcharta", "subchartb"} 51 52 verifyRequirementsEnabled(t, c, v, e) 53 } 54 func TestRequirementsTagsDisabledL1(t *testing.T) { 55 c, err := Load("testdata/subpop") 56 if err != nil { 57 t.Fatalf("Failed to load testdata: %s", err) 58 } 59 // tags disabling a group 60 v := &chart.Config{Raw: "tags:\n front-end: false\n\n"} 61 // expected charts including duplicates in alphanumeric order 62 e := []string{"parentchart"} 63 64 verifyRequirementsEnabled(t, c, v, e) 65 } 66 func TestRequirementsTagsEnabledL1(t *testing.T) { 67 c, err := Load("testdata/subpop") 68 if err != nil { 69 t.Fatalf("Failed to load testdata: %s", err) 70 } 71 // tags disabling a group and enabling a different group 72 v := &chart.Config{Raw: "tags:\n front-end: false\n\n back-end: true\n"} 73 // expected charts including duplicates in alphanumeric order 74 e := []string{"parentchart", "subchart2", "subchartb", "subchartc"} 75 76 verifyRequirementsEnabled(t, c, v, e) 77 } 78 79 func TestRequirementsTagsDisabledL2(t *testing.T) { 80 c, err := Load("testdata/subpop") 81 if err != nil { 82 t.Fatalf("Failed to load testdata: %s", err) 83 } 84 // tags disabling only children, children still enabled since tag front-end=true in values.yaml 85 v := &chart.Config{Raw: "tags:\n subcharta: false\n\n subchartb: false\n"} 86 // expected charts including duplicates in alphanumeric order 87 e := []string{"parentchart", "subchart1", "subcharta", "subchartb"} 88 89 verifyRequirementsEnabled(t, c, v, e) 90 } 91 func TestRequirementsTagsDisabledL1Mixed(t *testing.T) { 92 c, err := Load("testdata/subpop") 93 if err != nil { 94 t.Fatalf("Failed to load testdata: %s", err) 95 } 96 // tags disabling all parents/children with additional tag re-enabling a parent 97 v := &chart.Config{Raw: "tags:\n front-end: false\n\n subchart1: true\n\n back-end: false\n"} 98 // expected charts including duplicates in alphanumeric order 99 e := []string{"parentchart", "subchart1"} 100 101 verifyRequirementsEnabled(t, c, v, e) 102 } 103 func TestRequirementsConditionsNonValue(t *testing.T) { 104 c, err := Load("testdata/subpop") 105 if err != nil { 106 t.Fatalf("Failed to load testdata: %s", err) 107 } 108 // tags with no effect 109 v := &chart.Config{Raw: "subchart1:\n nothinguseful: false\n\n"} 110 // expected charts including duplicates in alphanumeric order 111 e := []string{"parentchart", "subchart1", "subcharta", "subchartb"} 112 113 verifyRequirementsEnabled(t, c, v, e) 114 } 115 func TestRequirementsConditionsEnabledL1Both(t *testing.T) { 116 c, err := Load("testdata/subpop") 117 if err != nil { 118 t.Fatalf("Failed to load testdata: %s", err) 119 } 120 // conditions enabling the parent charts, but back-end (b, c) is still disabled via values.yaml 121 v := &chart.Config{Raw: "subchart1:\n enabled: true\nsubchart2:\n enabled: true\n"} 122 // expected charts including duplicates in alphanumeric order 123 e := []string{"parentchart", "subchart1", "subchart2", "subcharta", "subchartb"} 124 125 verifyRequirementsEnabled(t, c, v, e) 126 } 127 func TestRequirementsConditionsDisabledL1Both(t *testing.T) { 128 c, err := Load("testdata/subpop") 129 if err != nil { 130 t.Fatalf("Failed to load testdata: %s", err) 131 } 132 // conditions disabling the parent charts, effectively disabling children 133 v := &chart.Config{Raw: "subchart1:\n enabled: false\nsubchart2:\n enabled: false\n"} 134 // expected charts including duplicates in alphanumeric order 135 e := []string{"parentchart"} 136 137 verifyRequirementsEnabled(t, c, v, e) 138 } 139 140 func TestRequirementsConditionsSecond(t *testing.T) { 141 c, err := Load("testdata/subpop") 142 if err != nil { 143 t.Fatalf("Failed to load testdata: %s", err) 144 } 145 // conditions a child using the second condition path of child's condition 146 v := &chart.Config{Raw: "subchart1:\n subcharta:\n enabled: false\n"} 147 // expected charts including duplicates in alphanumeric order 148 e := []string{"parentchart", "subchart1", "subchartb"} 149 150 verifyRequirementsEnabled(t, c, v, e) 151 } 152 func TestRequirementsCombinedDisabledL2(t *testing.T) { 153 c, err := Load("testdata/subpop") 154 if err != nil { 155 t.Fatalf("Failed to load testdata: %s", err) 156 } 157 // tags enabling a parent/child group with condition disabling one child 158 v := &chart.Config{Raw: "subchartc:\n enabled: false\ntags:\n back-end: true\n"} 159 // expected charts including duplicates in alphanumeric order 160 e := []string{"parentchart", "subchart1", "subchart2", "subcharta", "subchartb", "subchartb"} 161 162 verifyRequirementsEnabled(t, c, v, e) 163 } 164 func TestRequirementsCombinedDisabledL1(t *testing.T) { 165 c, err := Load("testdata/subpop") 166 if err != nil { 167 t.Fatalf("Failed to load testdata: %s", err) 168 } 169 // tags will not enable a child if parent is explicitly disabled with condition 170 v := &chart.Config{Raw: "subchart1:\n enabled: false\ntags:\n front-end: true\n"} 171 // expected charts including duplicates in alphanumeric order 172 e := []string{"parentchart"} 173 174 verifyRequirementsEnabled(t, c, v, e) 175 } 176 177 func verifyRequirementsEnabled(t *testing.T, c *chart.Chart, v *chart.Config, e []string) { 178 out := []*chart.Chart{} 179 err := ProcessRequirementsEnabled(c, v) 180 if err != nil { 181 t.Errorf("Error processing enabled requirements %v", err) 182 } 183 out = extractCharts(c, out) 184 // build list of chart names 185 p := []string{} 186 for _, r := range out { 187 p = append(p, r.Metadata.Name) 188 } 189 //sort alphanumeric and compare to expectations 190 sort.Strings(p) 191 if len(p) != len(e) { 192 t.Errorf("Error slice lengths do not match got %v, expected %v", len(p), len(e)) 193 return 194 } 195 for i := range p { 196 if p[i] != e[i] { 197 t.Errorf("Error slice values do not match got %v, expected %v", p[i], e[i]) 198 } 199 } 200 } 201 202 // extractCharts recursively searches chart dependencies returning all charts found 203 func extractCharts(c *chart.Chart, out []*chart.Chart) []*chart.Chart { 204 205 if len(c.Metadata.Name) > 0 { 206 out = append(out, c) 207 } 208 for _, d := range c.Dependencies { 209 out = extractCharts(d, out) 210 } 211 return out 212 } 213 func TestProcessRequirementsImportValues(t *testing.T) { 214 c, err := Load("testdata/subpop") 215 if err != nil { 216 t.Fatalf("Failed to load testdata: %s", err) 217 } 218 219 v := &chart.Config{Raw: ""} 220 221 e := make(map[string]string) 222 223 e["imported-chart1.SC1bool"] = "true" 224 e["imported-chart1.SC1float"] = "3.14" 225 e["imported-chart1.SC1int"] = "100" 226 e["imported-chart1.SC1string"] = "dollywood" 227 e["imported-chart1.SC1extra1"] = "11" 228 e["imported-chart1.SPextra1"] = "helm rocks" 229 e["imported-chart1.SC1extra1"] = "11" 230 231 e["imported-chartA.SCAbool"] = "false" 232 e["imported-chartA.SCAfloat"] = "3.1" 233 e["imported-chartA.SCAint"] = "55" 234 e["imported-chartA.SCAstring"] = "jabba" 235 e["imported-chartA.SPextra3"] = "1.337" 236 e["imported-chartA.SC1extra2"] = "1.337" 237 e["imported-chartA.SCAnested1.SCAnested2"] = "true" 238 239 e["imported-chartA-B.SCAbool"] = "false" 240 e["imported-chartA-B.SCAfloat"] = "3.1" 241 e["imported-chartA-B.SCAint"] = "55" 242 e["imported-chartA-B.SCAstring"] = "jabba" 243 244 e["imported-chartA-B.SCBbool"] = "true" 245 e["imported-chartA-B.SCBfloat"] = "7.77" 246 e["imported-chartA-B.SCBint"] = "33" 247 e["imported-chartA-B.SCBstring"] = "boba" 248 e["imported-chartA-B.SPextra5"] = "k8s" 249 e["imported-chartA-B.SC1extra5"] = "tiller" 250 251 e["overridden-chart1.SC1bool"] = "false" 252 e["overridden-chart1.SC1float"] = "3.141592" 253 e["overridden-chart1.SC1int"] = "99" 254 e["overridden-chart1.SC1string"] = "pollywog" 255 e["overridden-chart1.SPextra2"] = "42" 256 257 e["overridden-chartA.SCAbool"] = "true" 258 e["overridden-chartA.SCAfloat"] = "41.3" 259 e["overridden-chartA.SCAint"] = "808" 260 e["overridden-chartA.SCAstring"] = "jaberwocky" 261 e["overridden-chartA.SPextra4"] = "true" 262 263 e["overridden-chartA-B.SCAbool"] = "true" 264 e["overridden-chartA-B.SCAfloat"] = "41.3" 265 e["overridden-chartA-B.SCAint"] = "808" 266 e["overridden-chartA-B.SCAstring"] = "jaberwocky" 267 e["overridden-chartA-B.SCBbool"] = "false" 268 e["overridden-chartA-B.SCBfloat"] = "1.99" 269 e["overridden-chartA-B.SCBint"] = "77" 270 e["overridden-chartA-B.SCBstring"] = "jango" 271 e["overridden-chartA-B.SPextra6"] = "111" 272 e["overridden-chartA-B.SCAextra1"] = "23" 273 e["overridden-chartA-B.SCBextra1"] = "13" 274 e["overridden-chartA-B.SC1extra6"] = "77" 275 276 // `exports` style 277 e["SCBexported1B"] = "1965" 278 e["SC1extra7"] = "true" 279 e["SCBexported2A"] = "blaster" 280 e["global.SC1exported2.all.SC1exported3"] = "SC1expstr" 281 282 verifyRequirementsImportValues(t, c, v, e) 283 } 284 func verifyRequirementsImportValues(t *testing.T, c *chart.Chart, v *chart.Config, e map[string]string) { 285 286 err := ProcessRequirementsImportValues(c) 287 if err != nil { 288 t.Errorf("Error processing import values requirements %v", err) 289 } 290 cv := c.GetValues() 291 cc, err := ReadValues([]byte(cv.Raw)) 292 if err != nil { 293 t.Errorf("Error reading import values %v", err) 294 } 295 for kk, vv := range e { 296 pv, err := cc.PathValue(kk) 297 if err != nil { 298 t.Fatalf("Error retrieving import values table %v %v", kk, err) 299 return 300 } 301 302 switch pv.(type) { 303 case float64: 304 s := strconv.FormatFloat(pv.(float64), 'f', -1, 64) 305 if s != vv { 306 t.Errorf("Failed to match imported float value %v with expected %v", s, vv) 307 return 308 } 309 case bool: 310 b := strconv.FormatBool(pv.(bool)) 311 if b != vv { 312 t.Errorf("Failed to match imported bool value %v with expected %v", b, vv) 313 return 314 } 315 default: 316 if pv.(string) != vv { 317 t.Errorf("Failed to match imported string value %v with expected %v", pv, vv) 318 return 319 } 320 } 321 322 } 323 } 324 325 func TestGetAliasDependency(t *testing.T) { 326 c, err := Load("testdata/frobnitz") 327 if err != nil { 328 t.Fatalf("Failed to load testdata: %s", err) 329 } 330 req, err := LoadRequirements(c) 331 if err != nil { 332 t.Fatalf("Failed to load requirement for testdata: %s", err) 333 } 334 if len(req.Dependencies) == 0 { 335 t.Fatalf("There are no requirements to test") 336 } 337 338 // Success case 339 aliasChart := getAliasDependency(c.Dependencies, req.Dependencies[0]) 340 if aliasChart == nil { 341 t.Fatalf("Failed to get dependency chart for alias %s", req.Dependencies[0].Name) 342 } 343 if req.Dependencies[0].Alias != "" { 344 if aliasChart.Metadata.Name != req.Dependencies[0].Alias { 345 t.Fatalf("Dependency chart name should be %s but got %s", req.Dependencies[0].Alias, aliasChart.Metadata.Name) 346 } 347 } else if aliasChart.Metadata.Name != req.Dependencies[0].Name { 348 t.Fatalf("Dependency chart name should be %s but got %s", req.Dependencies[0].Name, aliasChart.Metadata.Name) 349 } 350 351 if req.Dependencies[0].Version != "" { 352 if !version.IsCompatibleRange(req.Dependencies[0].Version, aliasChart.Metadata.Version) { 353 t.Fatalf("Dependency chart version is not in the compatible range") 354 } 355 356 } 357 358 // Failure case 359 req.Dependencies[0].Name = "something-else" 360 if aliasChart := getAliasDependency(c.Dependencies, req.Dependencies[0]); aliasChart != nil { 361 t.Fatalf("expected no chart but got %s", aliasChart.Metadata.Name) 362 } 363 364 req.Dependencies[0].Version = "something else which is not in the compatible range" 365 if version.IsCompatibleRange(req.Dependencies[0].Version, aliasChart.Metadata.Version) { 366 t.Fatalf("Dependency chart version which is not in the compatible range should cause a failure other than a success ") 367 } 368 369 } 370 371 func TestDependentChartAliases(t *testing.T) { 372 c, err := Load("testdata/dependent-chart-alias") 373 if err != nil { 374 t.Fatalf("Failed to load testdata: %s", err) 375 } 376 377 if len(c.Dependencies) == 0 { 378 t.Fatal("There are no dependencies to run this test") 379 } 380 381 origLength := len(c.Dependencies) 382 if err := ProcessRequirementsEnabled(c, c.Values); err != nil { 383 t.Fatalf("Expected no errors but got %q", err) 384 } 385 386 if len(c.Dependencies) == origLength { 387 t.Fatal("Expected alias dependencies to be added, but did not got that") 388 } 389 390 reqmts, err := LoadRequirements(c) 391 if err != nil { 392 t.Fatalf("Cannot load requirements for test chart, %v", err) 393 } 394 395 if len(c.Dependencies) != len(reqmts.Dependencies) { 396 t.Fatalf("Expected number of chart dependencies %d, but got %d", len(reqmts.Dependencies), len(c.Dependencies)) 397 } 398 399 } 400 401 func TestDependentChartWithSubChartsAbsentInRequirements(t *testing.T) { 402 c, err := Load("testdata/dependent-chart-no-requirements-yaml") 403 if err != nil { 404 t.Fatalf("Failed to load testdata: %s", err) 405 } 406 407 if len(c.Dependencies) != 2 { 408 t.Fatalf("Expected 2 dependencies for this chart, but got %d", len(c.Dependencies)) 409 } 410 411 origLength := len(c.Dependencies) 412 if err := ProcessRequirementsEnabled(c, c.Values); err != nil { 413 t.Fatalf("Expected no errors but got %q", err) 414 } 415 416 if len(c.Dependencies) != origLength { 417 t.Fatal("Expected no changes in dependencies to be, but did something got changed") 418 } 419 420 } 421 422 func TestDependentChartsWithSubchartsAllSpecifiedInRequirements(t *testing.T) { 423 c, err := Load("testdata/dependent-chart-with-all-in-requirements-yaml") 424 if err != nil { 425 t.Fatalf("Failed to load testdata: %s", err) 426 } 427 428 if len(c.Dependencies) == 0 { 429 t.Fatal("There are no dependencies to run this test") 430 } 431 432 origLength := len(c.Dependencies) 433 if err := ProcessRequirementsEnabled(c, c.Values); err != nil { 434 t.Fatalf("Expected no errors but got %q", err) 435 } 436 437 if len(c.Dependencies) != origLength { 438 t.Fatal("Expected no changes in dependencies to be, but did something got changed") 439 } 440 441 reqmts, err := LoadRequirements(c) 442 if err != nil { 443 t.Fatalf("Cannot load requirements for test chart, %v", err) 444 } 445 446 if len(c.Dependencies) != len(reqmts.Dependencies) { 447 t.Fatalf("Expected number of chart dependencies %d, but got %d", len(reqmts.Dependencies), len(c.Dependencies)) 448 } 449 450 } 451 452 func TestDependentChartsWithSomeSubchartsSpecifiedInRequirements(t *testing.T) { 453 c, err := Load("testdata/dependent-chart-with-mixed-requirements-yaml") 454 if err != nil { 455 t.Fatalf("Failed to load testdata: %s", err) 456 } 457 458 if len(c.Dependencies) == 0 { 459 t.Fatal("There are no dependencies to run this test") 460 } 461 462 origLength := len(c.Dependencies) 463 if err := ProcessRequirementsEnabled(c, c.Values); err != nil { 464 t.Fatalf("Expected no errors but got %q", err) 465 } 466 467 if len(c.Dependencies) != origLength { 468 t.Fatal("Expected no changes in dependencies to be, but did something got changed") 469 } 470 471 reqmts, err := LoadRequirements(c) 472 if err != nil { 473 t.Fatalf("Cannot load requirements for test chart, %v", err) 474 } 475 476 if len(c.Dependencies) <= len(reqmts.Dependencies) { 477 t.Fatalf("Expected more dependencies than specified in requirements.yaml(%d), but got %d", len(reqmts.Dependencies), len(c.Dependencies)) 478 } 479 480 }