mirror of
https://github.com/helm/helm.git
synced 2026-08-06 16:11:25 +00:00
Merge pull request #4983 from adamreese/dev-v3-ref-tests
ref(pkg/chartutil): simplify chart dependency unit tests
This commit is contained in:
@@ -171,10 +171,7 @@ func (o *templateOptions) run(out io.Writer) error {
|
||||
if err := yaml.Unmarshal(config, &m); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chartutil.ProcessDependencyEnabled(c, m); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := chartutil.ProcessDependencyImportValues(c); err != nil {
|
||||
if err := chartutil.ProcessDependencies(c, m); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -25,8 +25,15 @@ import (
|
||||
"k8s.io/helm/pkg/version"
|
||||
)
|
||||
|
||||
// ProcessDependencyConditions disables charts based on condition path value in values
|
||||
func ProcessDependencyConditions(reqs []*chart.Dependency, cvals Values) {
|
||||
func ProcessDependencies(c *chart.Chart, v Values) error {
|
||||
if err := processDependencyEnabled(c, v); err != nil {
|
||||
return err
|
||||
}
|
||||
return processDependencyImportValues(c)
|
||||
}
|
||||
|
||||
// processDependencyConditions disables charts based on condition path value in values
|
||||
func processDependencyConditions(reqs []*chart.Dependency, cvals Values) {
|
||||
if reqs == nil {
|
||||
return
|
||||
}
|
||||
@@ -66,8 +73,8 @@ func ProcessDependencyConditions(reqs []*chart.Dependency, cvals Values) {
|
||||
}
|
||||
}
|
||||
|
||||
// ProcessDependencyTags disables charts based on tags in values
|
||||
func ProcessDependencyTags(reqs []*chart.Dependency, cvals Values) {
|
||||
// processDependencyTags disables charts based on tags in values
|
||||
func processDependencyTags(reqs []*chart.Dependency, cvals Values) {
|
||||
if reqs == nil {
|
||||
return
|
||||
}
|
||||
@@ -99,34 +106,32 @@ func ProcessDependencyTags(reqs []*chart.Dependency, cvals Values) {
|
||||
}
|
||||
}
|
||||
|
||||
func getAliasDependency(charts []*chart.Chart, aliasChart *chart.Dependency) *chart.Chart {
|
||||
var chartFound chart.Chart
|
||||
for _, existingChart := range charts {
|
||||
if existingChart == nil {
|
||||
func getAliasDependency(charts []*chart.Chart, dep *chart.Dependency) *chart.Chart {
|
||||
for _, c := range charts {
|
||||
if c == nil {
|
||||
continue
|
||||
}
|
||||
if existingChart.Metadata == nil {
|
||||
if c.Name() != dep.Name {
|
||||
continue
|
||||
}
|
||||
if existingChart.Metadata.Name != aliasChart.Name {
|
||||
if !version.IsCompatibleRange(dep.Version, c.Metadata.Version) {
|
||||
continue
|
||||
}
|
||||
if !version.IsCompatibleRange(aliasChart.Version, existingChart.Metadata.Version) {
|
||||
continue
|
||||
|
||||
out := *c
|
||||
md := *c.Metadata
|
||||
out.Metadata = &md
|
||||
|
||||
if dep.Alias != "" {
|
||||
md.Name = dep.Alias
|
||||
}
|
||||
chartFound = *existingChart
|
||||
newMetadata := *existingChart.Metadata
|
||||
if aliasChart.Alias != "" {
|
||||
newMetadata.Name = aliasChart.Alias
|
||||
}
|
||||
chartFound.Metadata = &newMetadata
|
||||
return &chartFound
|
||||
return &out
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ProcessDependencyEnabled removes disabled charts from dependencies
|
||||
func ProcessDependencyEnabled(c *chart.Chart, v map[string]interface{}) error {
|
||||
// processDependencyEnabled removes disabled charts from dependencies
|
||||
func processDependencyEnabled(c *chart.Chart, v map[string]interface{}) error {
|
||||
if c.Metadata.Dependencies == nil {
|
||||
return nil
|
||||
}
|
||||
@@ -137,17 +142,14 @@ func ProcessDependencyEnabled(c *chart.Chart, v map[string]interface{}) error {
|
||||
// However, if the dependency is already specified in Chart.yaml
|
||||
// we should not add it, as it would be anyways processed from Chart.yaml
|
||||
|
||||
for _, existingDependency := range c.Dependencies() {
|
||||
var dependencyFound bool
|
||||
Loop:
|
||||
for _, existing := range c.Dependencies() {
|
||||
for _, req := range c.Metadata.Dependencies {
|
||||
if existingDependency.Metadata.Name == req.Name && version.IsCompatibleRange(req.Version, existingDependency.Metadata.Version) {
|
||||
dependencyFound = true
|
||||
break
|
||||
if existing.Name() == req.Name && version.IsCompatibleRange(req.Version, existing.Metadata.Version) {
|
||||
continue Loop
|
||||
}
|
||||
}
|
||||
if !dependencyFound {
|
||||
chartDependencies = append(chartDependencies, existingDependency)
|
||||
}
|
||||
chartDependencies = append(chartDependencies, existing)
|
||||
}
|
||||
|
||||
for _, req := range c.Metadata.Dependencies {
|
||||
@@ -170,8 +172,8 @@ func ProcessDependencyEnabled(c *chart.Chart, v map[string]interface{}) error {
|
||||
return err
|
||||
}
|
||||
// flag dependencies as enabled/disabled
|
||||
ProcessDependencyTags(c.Metadata.Dependencies, cvals)
|
||||
ProcessDependencyConditions(c.Metadata.Dependencies, cvals)
|
||||
processDependencyTags(c.Metadata.Dependencies, cvals)
|
||||
processDependencyConditions(c.Metadata.Dependencies, cvals)
|
||||
// make a map of charts to remove
|
||||
rm := map[string]struct{}{}
|
||||
for _, r := range c.Metadata.Dependencies {
|
||||
@@ -191,7 +193,7 @@ func ProcessDependencyEnabled(c *chart.Chart, v map[string]interface{}) error {
|
||||
|
||||
// recursively call self to process sub dependencies
|
||||
for _, t := range cd {
|
||||
if err := ProcessDependencyEnabled(t, cvals); err != nil {
|
||||
if err := processDependencyEnabled(t, cvals); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@@ -276,11 +278,11 @@ func processImportValues(c *chart.Chart) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// ProcessDependencyImportValues imports specified chart values from child to parent.
|
||||
func ProcessDependencyImportValues(c *chart.Chart) error {
|
||||
// processDependencyImportValues imports specified chart values from child to parent.
|
||||
func processDependencyImportValues(c *chart.Chart) error {
|
||||
for _, d := range c.Dependencies() {
|
||||
// recurse
|
||||
if err := ProcessDependencyImportValues(d); err != nil {
|
||||
if err := processDependencyImportValues(d); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,141 +16,134 @@ package chartutil
|
||||
|
||||
import (
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"strconv"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"testing"
|
||||
|
||||
"k8s.io/helm/pkg/chart"
|
||||
"k8s.io/helm/pkg/chart/loader"
|
||||
"k8s.io/helm/pkg/version"
|
||||
)
|
||||
|
||||
func TestLoadDependency(t *testing.T) {
|
||||
c, err := loader.Load("testdata/frobnitz")
|
||||
func loadChart(t *testing.T, path string) *chart.Chart {
|
||||
c, err := loader.Load(path)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load testdata: %s", err)
|
||||
t.Fatalf("failed to load testdata: %s", err)
|
||||
}
|
||||
verifyDependency(t, c)
|
||||
return c
|
||||
}
|
||||
|
||||
func TestLoadChartLock(t *testing.T) {
|
||||
c, err := loader.Load("testdata/frobnitz")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load testdata: %s", err)
|
||||
func TestLoadDependency(t *testing.T) {
|
||||
tests := []*chart.Dependency{
|
||||
{Name: "alpine", Version: "0.1.0", Repository: "https://example.com/charts"},
|
||||
{Name: "mariner", Version: "4.3.2", Repository: "https://example.com/charts"},
|
||||
}
|
||||
verifyChartLock(t, c)
|
||||
|
||||
check := func(deps []*chart.Dependency) {
|
||||
if len(deps) != 2 {
|
||||
t.Errorf("expected 2 dependencies, got %d", len(deps))
|
||||
}
|
||||
for i, tt := range tests {
|
||||
if deps[i].Name != tt.Name {
|
||||
t.Errorf("expected dependency named %q, got %q", tt.Name, deps[i].Name)
|
||||
}
|
||||
if deps[i].Version != tt.Version {
|
||||
t.Errorf("expected dependency named %q to have version %q, got %q", tt.Name, tt.Version, deps[i].Version)
|
||||
}
|
||||
if deps[i].Repository != tt.Repository {
|
||||
t.Errorf("expected dependency named %q to have repository %q, got %q", tt.Name, tt.Repository, deps[i].Repository)
|
||||
}
|
||||
}
|
||||
}
|
||||
c := loadChart(t, "testdata/frobnitz")
|
||||
check(c.Metadata.Dependencies)
|
||||
check(c.Lock.Dependencies)
|
||||
}
|
||||
|
||||
func TestDependencyEnabled(t *testing.T) {
|
||||
type M = map[string]interface{}
|
||||
tests := []struct {
|
||||
name string
|
||||
v []byte
|
||||
v M
|
||||
e []string // expected charts including duplicates in alphanumeric order
|
||||
}{{
|
||||
"tags with no effect",
|
||||
[]byte("tags:\n nothinguseful: false\n\n"),
|
||||
[]string{"parentchart", "subchart1", "subcharta", "subchartb"},
|
||||
}, {
|
||||
"tags with no effect",
|
||||
[]byte("tags:\n nothinguseful: false\n\n"),
|
||||
[]string{"parentchart", "subchart1", "subcharta", "subchartb"},
|
||||
M{"tags": M{"nothinguseful": false}},
|
||||
[]string{"parentchart", "parentchart.subchart1", "parentchart.subchart1.subcharta", "parentchart.subchart1.subchartb"},
|
||||
}, {
|
||||
"tags disabling a group",
|
||||
[]byte("tags:\n front-end: false\n\n"),
|
||||
M{"tags": M{"front-end": false}},
|
||||
[]string{"parentchart"},
|
||||
}, {
|
||||
"tags disabling a group and enabling a different group",
|
||||
[]byte("tags:\n front-end: false\n\n back-end: true\n"),
|
||||
[]string{"parentchart", "subchart2", "subchartb", "subchartc"},
|
||||
M{"tags": M{"front-end": false, "back-end": true}},
|
||||
[]string{"parentchart", "parentchart.subchart2", "parentchart.subchart2.subchartb", "parentchart.subchart2.subchartc"},
|
||||
}, {
|
||||
"tags disabling only children, children still enabled since tag front-end=true in values.yaml",
|
||||
[]byte("tags:\n subcharta: false\n\n subchartb: false\n"),
|
||||
[]string{"parentchart", "subchart1", "subcharta", "subchartb"},
|
||||
M{"tags": M{"subcharta": false, "subchartb": false}},
|
||||
[]string{"parentchart", "parentchart.subchart1", "parentchart.subchart1.subcharta", "parentchart.subchart1.subchartb"},
|
||||
}, {
|
||||
"tags disabling all parents/children with additional tag re-enabling a parent",
|
||||
[]byte("tags:\n front-end: false\n\n subchart1: true\n\n back-end: false\n"),
|
||||
[]string{"parentchart", "subchart1"},
|
||||
}, {
|
||||
"tags with no effect",
|
||||
[]byte("subchart1:\n nothinguseful: false\n\n"),
|
||||
[]string{"parentchart", "subchart1", "subcharta", "subchartb"},
|
||||
M{"tags": M{"front-end": false, "subchart1": true, "back-end": false}},
|
||||
[]string{"parentchart", "parentchart.subchart1"},
|
||||
}, {
|
||||
"conditions enabling the parent charts, but back-end (b, c) is still disabled via values.yaml",
|
||||
[]byte("subchart1:\n enabled: true\nsubchart2:\n enabled: true\n"),
|
||||
[]string{"parentchart", "subchart1", "subchart2", "subcharta", "subchartb"},
|
||||
M{"subchart1": M{"enabled": true}, "subchart2": M{"enabled": true}},
|
||||
[]string{"parentchart", "parentchart.subchart1", "parentchart.subchart1.subcharta", "parentchart.subchart1.subchartb", "parentchart.subchart2"},
|
||||
}, {
|
||||
"conditions disabling the parent charts, effectively disabling children",
|
||||
[]byte("subchart1:\n enabled: false\nsubchart2:\n enabled: false\n"),
|
||||
M{"subchart1": M{"enabled": false}, "subchart2": M{"enabled": false}},
|
||||
[]string{"parentchart"},
|
||||
}, {
|
||||
"conditions a child using the second condition path of child's condition",
|
||||
[]byte("subchart1:\n subcharta:\n enabled: false\n"),
|
||||
[]string{"parentchart", "subchart1", "subchartb"},
|
||||
M{"subchart1": M{"subcharta": M{"enabled": false}}},
|
||||
[]string{"parentchart", "parentchart.subchart1", "parentchart.subchart1.subchartb"},
|
||||
}, {
|
||||
"tags enabling a parent/child group with condition disabling one child",
|
||||
[]byte("subchartc:\n enabled: false\ntags:\n back-end: true\n"),
|
||||
[]string{"parentchart", "subchart1", "subchart2", "subcharta", "subchartb", "subchartb"},
|
||||
M{"subchartc": M{"enabled": false}, "tags": M{"back-end": true}},
|
||||
[]string{"parentchart", "parentchart.subchart1", "parentchart.subchart1.subcharta", "parentchart.subchart1.subchartb", "parentchart.subchart2", "parentchart.subchart2.subchartb"},
|
||||
}, {
|
||||
"tags will not enable a child if parent is explicitly disabled with condition",
|
||||
[]byte("subchart1:\n enabled: false\ntags:\n front-end: true\n"),
|
||||
M{"subchart1": M{"enabled": false}, "tags": M{"front-end": true}},
|
||||
[]string{"parentchart"},
|
||||
}}
|
||||
|
||||
for _, tc := range tests {
|
||||
c, err := loader.Load("testdata/subpop")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load testdata: %s", err)
|
||||
}
|
||||
c := loadChart(t, "testdata/subpop")
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
verifyDependencyEnabled(t, c, tc.v, tc.e)
|
||||
if err := processDependencyEnabled(c, tc.v); err != nil {
|
||||
t.Fatalf("error processing enabled dependencies %v", err)
|
||||
}
|
||||
|
||||
names := extractChartNames(c)
|
||||
if len(names) != len(tc.e) {
|
||||
t.Fatalf("slice lengths do not match got %v, expected %v", len(names), len(tc.e))
|
||||
}
|
||||
for i := range names {
|
||||
if names[i] != tc.e[i] {
|
||||
t.Fatalf("slice values do not match got %v, expected %v", names, tc.e)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func verifyDependencyEnabled(t *testing.T, c *chart.Chart, v []byte, e []string) {
|
||||
var m map[string]interface{}
|
||||
yaml.Unmarshal(v, &m)
|
||||
if err := ProcessDependencyEnabled(c, m); err != nil {
|
||||
t.Errorf("Error processing enabled dependencies %v", err)
|
||||
}
|
||||
|
||||
out := extractCharts(c, nil)
|
||||
// build list of chart names
|
||||
var p []string
|
||||
for _, r := range out {
|
||||
p = append(p, r.Name())
|
||||
}
|
||||
//sort alphanumeric and compare to expectations
|
||||
sort.Strings(p)
|
||||
if len(p) != len(e) {
|
||||
t.Errorf("Error slice lengths do not match got %v, expected %v", len(p), len(e))
|
||||
return
|
||||
}
|
||||
for i := range p {
|
||||
if p[i] != e[i] {
|
||||
t.Errorf("Error slice values do not match got %v, expected %v", p[i], e[i])
|
||||
// extractCharts recursively searches chart dependencies returning all charts found
|
||||
func extractChartNames(c *chart.Chart) []string {
|
||||
var out []string
|
||||
var fn func(c *chart.Chart)
|
||||
fn = func(c *chart.Chart) {
|
||||
out = append(out, c.ChartPath())
|
||||
for _, d := range c.Dependencies() {
|
||||
fn(d)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// extractCharts recursively searches chart dependencies returning all charts found
|
||||
func extractCharts(c *chart.Chart, out []*chart.Chart) []*chart.Chart {
|
||||
if len(c.Name()) > 0 {
|
||||
out = append(out, c)
|
||||
}
|
||||
for _, d := range c.Dependencies() {
|
||||
out = extractCharts(d, out)
|
||||
}
|
||||
fn(c)
|
||||
sort.Strings(out)
|
||||
return out
|
||||
}
|
||||
|
||||
func TestProcessDependencyImportValues(t *testing.T) {
|
||||
c, err := loader.Load("testdata/subpop")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load testdata: %s", err)
|
||||
}
|
||||
c := loadChart(t, "testdata/subpop")
|
||||
|
||||
e := make(map[string]string)
|
||||
|
||||
@@ -213,71 +206,57 @@ func TestProcessDependencyImportValues(t *testing.T) {
|
||||
e["SCBexported2A"] = "blaster"
|
||||
e["global.SC1exported2.all.SC1exported3"] = "SC1expstr"
|
||||
|
||||
verifyDependencyImportValues(t, c, e)
|
||||
}
|
||||
|
||||
func verifyDependencyImportValues(t *testing.T, c *chart.Chart, e map[string]string) {
|
||||
if err := ProcessDependencyImportValues(c); err != nil {
|
||||
t.Fatalf("Error processing import values dependencies %v", err)
|
||||
if err := processDependencyImportValues(c); err != nil {
|
||||
t.Fatalf("processing import values dependencies %v", err)
|
||||
}
|
||||
cc := Values(c.Values)
|
||||
for kk, vv := range e {
|
||||
pv, err := cc.PathValue(kk)
|
||||
if err != nil {
|
||||
t.Fatalf("Error retrieving import values table %v %v", kk, err)
|
||||
return
|
||||
t.Fatalf("retrieving import values table %v %v", kk, err)
|
||||
}
|
||||
|
||||
switch pv.(type) {
|
||||
case float64:
|
||||
s := strconv.FormatFloat(pv.(float64), 'f', -1, 64)
|
||||
if s != vv {
|
||||
t.Errorf("Failed to match imported float value %v with expected %v", s, vv)
|
||||
return
|
||||
if s := strconv.FormatFloat(pv.(float64), 'f', -1, 64); s != vv {
|
||||
t.Errorf("failed to match imported float value %v with expected %v", s, vv)
|
||||
}
|
||||
case bool:
|
||||
b := strconv.FormatBool(pv.(bool))
|
||||
if b != vv {
|
||||
t.Errorf("Failed to match imported bool value %v with expected %v", b, vv)
|
||||
return
|
||||
if b := strconv.FormatBool(pv.(bool)); b != vv {
|
||||
t.Errorf("failed to match imported bool value %v with expected %v", b, vv)
|
||||
}
|
||||
default:
|
||||
if pv.(string) != vv {
|
||||
t.Errorf("Failed to match imported string value %q with expected %q", pv, vv)
|
||||
return
|
||||
t.Errorf("failed to match imported string value %q with expected %q", pv, vv)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetAliasDependency(t *testing.T) {
|
||||
c, err := loader.Load("testdata/frobnitz")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load testdata: %s", err)
|
||||
}
|
||||
|
||||
c := loadChart(t, "testdata/frobnitz")
|
||||
req := c.Metadata.Dependencies
|
||||
|
||||
if len(req) == 0 {
|
||||
t.Fatalf("There are no dependencies to test")
|
||||
t.Fatalf("there are no dependencies to test")
|
||||
}
|
||||
|
||||
// Success case
|
||||
aliasChart := getAliasDependency(c.Dependencies(), req[0])
|
||||
if aliasChart == nil {
|
||||
t.Fatalf("Failed to get dependency chart for alias %s", req[0].Name)
|
||||
t.Fatalf("failed to get dependency chart for alias %s", req[0].Name)
|
||||
}
|
||||
if req[0].Alias != "" {
|
||||
if aliasChart.Name() != req[0].Alias {
|
||||
t.Fatalf("Dependency chart name should be %s but got %s", req[0].Alias, aliasChart.Name())
|
||||
t.Fatalf("dependency chart name should be %s but got %s", req[0].Alias, aliasChart.Name())
|
||||
}
|
||||
} else if aliasChart.Name() != req[0].Name {
|
||||
t.Fatalf("Dependency chart name should be %s but got %s", req[0].Name, aliasChart.Name())
|
||||
t.Fatalf("dependency chart name should be %s but got %s", req[0].Name, aliasChart.Name())
|
||||
}
|
||||
|
||||
if req[0].Version != "" {
|
||||
if !version.IsCompatibleRange(req[0].Version, aliasChart.Metadata.Version) {
|
||||
t.Fatalf("Dependency chart version is not in the compatible range")
|
||||
t.Fatalf("dependency chart version is not in the compatible range")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,161 +268,99 @@ func TestGetAliasDependency(t *testing.T) {
|
||||
|
||||
req[0].Version = "something else which is not in the compatible range"
|
||||
if version.IsCompatibleRange(req[0].Version, aliasChart.Metadata.Version) {
|
||||
t.Fatalf("Dependency chart version which is not in the compatible range should cause a failure other than a success ")
|
||||
t.Fatalf("dependency chart version which is not in the compatible range should cause a failure other than a success ")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDependentChartAliases(t *testing.T) {
|
||||
c, err := loader.Load("testdata/dependent-chart-alias")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load testdata: %s", err)
|
||||
c := loadChart(t, "testdata/dependent-chart-alias")
|
||||
|
||||
if len(c.Dependencies()) != 2 {
|
||||
t.Fatalf("expected 2 dependencies for this chart, but got %d", len(c.Dependencies()))
|
||||
}
|
||||
|
||||
if len(c.Dependencies()) == 0 {
|
||||
t.Fatal("There are no dependencies to run this test")
|
||||
if err := processDependencyEnabled(c, c.Values); err != nil {
|
||||
t.Fatalf("expected no errors but got %q", err)
|
||||
}
|
||||
|
||||
origLength := len(c.Dependencies())
|
||||
if err := ProcessDependencyEnabled(c, c.Values); err != nil {
|
||||
t.Fatalf("Expected no errors but got %q", err)
|
||||
}
|
||||
|
||||
if len(c.Dependencies()) == origLength {
|
||||
t.Fatal("Expected alias dependencies to be added, but did not got that")
|
||||
if len(c.Dependencies()) != 3 {
|
||||
t.Fatal("expected alias dependencies to be added")
|
||||
}
|
||||
|
||||
if len(c.Dependencies()) != len(c.Metadata.Dependencies) {
|
||||
t.Fatalf("Expected number of chart dependencies %d, but got %d", len(c.Metadata.Dependencies), len(c.Dependencies()))
|
||||
t.Fatalf("expected number of chart dependencies %d, but got %d", len(c.Metadata.Dependencies), len(c.Dependencies()))
|
||||
}
|
||||
// FIXME test for correct aliases
|
||||
}
|
||||
|
||||
func TestDependentChartWithSubChartsAbsentInDependency(t *testing.T) {
|
||||
c, err := loader.Load("testdata/dependent-chart-no-requirements-yaml")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load testdata: %s", err)
|
||||
c := loadChart(t, "testdata/dependent-chart-no-requirements-yaml")
|
||||
|
||||
if len(c.Dependencies()) != 2 {
|
||||
t.Fatalf("expected 2 dependencies for this chart, but got %d", len(c.Dependencies()))
|
||||
}
|
||||
|
||||
if err := processDependencyEnabled(c, c.Values); err != nil {
|
||||
t.Fatalf("expected no errors but got %q", err)
|
||||
}
|
||||
|
||||
if len(c.Dependencies()) != 2 {
|
||||
t.Fatalf("Expected 2 dependencies for this chart, but got %d", len(c.Dependencies()))
|
||||
}
|
||||
|
||||
origLength := len(c.Dependencies())
|
||||
if err := ProcessDependencyEnabled(c, c.Values); err != nil {
|
||||
t.Fatalf("Expected no errors but got %q", err)
|
||||
}
|
||||
|
||||
if len(c.Dependencies()) != origLength {
|
||||
t.Fatal("Expected no changes in dependencies to be, but did something got changed")
|
||||
t.Fatal("expected no changes in dependencies")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDependentChartWithSubChartsHelmignore(t *testing.T) {
|
||||
if _, err := loader.Load("testdata/dependent-chart-helmignore"); err != nil {
|
||||
t.Fatalf("Failed to load testdata: %s", err)
|
||||
}
|
||||
// FIXME what does this test?
|
||||
loadChart(t, "testdata/dependent-chart-helmignore")
|
||||
}
|
||||
|
||||
func TestDependentChartsWithSubChartsSymlink(t *testing.T) {
|
||||
c, err := loader.Load("testdata/joonix")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load testdata: %s", err)
|
||||
}
|
||||
c := loadChart(t, "testdata/joonix")
|
||||
|
||||
if c.Name() != "joonix" {
|
||||
t.Fatalf("Unexpected chart name: %s", c.Name())
|
||||
t.Fatalf("unexpected chart name: %s", c.Name())
|
||||
}
|
||||
if n := len(c.Dependencies()); n != 1 {
|
||||
t.Fatalf("Expected 1 dependency for this chart, but got %d", n)
|
||||
t.Fatalf("expected 1 dependency for this chart, but got %d", n)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDependentChartsWithSubchartsAllSpecifiedInDependency(t *testing.T) {
|
||||
c, err := loader.Load("testdata/dependent-chart-with-all-in-requirements-yaml")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load testdata: %s", err)
|
||||
c := loadChart(t, "testdata/dependent-chart-with-all-in-requirements-yaml")
|
||||
|
||||
if len(c.Dependencies()) != 2 {
|
||||
t.Fatalf("expected 2 dependencies for this chart, but got %d", len(c.Dependencies()))
|
||||
}
|
||||
|
||||
if len(c.Dependencies()) == 0 {
|
||||
t.Fatal("There are no dependencies to run this test")
|
||||
if err := processDependencyEnabled(c, c.Values); err != nil {
|
||||
t.Fatalf("expected no errors but got %q", err)
|
||||
}
|
||||
|
||||
origLength := len(c.Dependencies())
|
||||
if err := ProcessDependencyEnabled(c, c.Values); err != nil {
|
||||
t.Fatalf("Expected no errors but got %q", err)
|
||||
}
|
||||
|
||||
if len(c.Dependencies()) != origLength {
|
||||
t.Fatal("Expected no changes in dependencies to be, but did something got changed")
|
||||
if len(c.Dependencies()) != 2 {
|
||||
t.Fatal("expected no changes in dependencies")
|
||||
}
|
||||
|
||||
if len(c.Dependencies()) != len(c.Metadata.Dependencies) {
|
||||
t.Fatalf("Expected number of chart dependencies %d, but got %d", len(c.Metadata.Dependencies), len(c.Dependencies()))
|
||||
t.Fatalf("expected number of chart dependencies %d, but got %d", len(c.Metadata.Dependencies), len(c.Dependencies()))
|
||||
}
|
||||
}
|
||||
|
||||
func TestDependentChartsWithSomeSubchartsSpecifiedInDependency(t *testing.T) {
|
||||
c, err := loader.Load("testdata/dependent-chart-with-mixed-requirements-yaml")
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to load testdata: %s", err)
|
||||
c := loadChart(t, "testdata/dependent-chart-with-mixed-requirements-yaml")
|
||||
|
||||
if len(c.Dependencies()) != 2 {
|
||||
t.Fatalf("expected 2 dependencies for this chart, but got %d", len(c.Dependencies()))
|
||||
}
|
||||
|
||||
if len(c.Dependencies()) == 0 {
|
||||
t.Fatal("There are no dependencies to run this test")
|
||||
if err := processDependencyEnabled(c, c.Values); err != nil {
|
||||
t.Fatalf("expected no errors but got %q", err)
|
||||
}
|
||||
|
||||
origLength := len(c.Dependencies())
|
||||
if err := ProcessDependencyEnabled(c, c.Values); err != nil {
|
||||
t.Fatalf("Expected no errors but got %q", err)
|
||||
if len(c.Dependencies()) != 2 {
|
||||
t.Fatal("expected no changes in dependencies")
|
||||
}
|
||||
|
||||
if len(c.Dependencies()) != origLength {
|
||||
t.Fatal("Expected no changes in dependencies to be, but did something got changed")
|
||||
}
|
||||
|
||||
if len(c.Dependencies()) <= len(c.Metadata.Dependencies) {
|
||||
t.Fatalf("Expected more dependencies than specified in Chart.yaml(%d), but got %d", len(c.Metadata.Dependencies), len(c.Dependencies()))
|
||||
}
|
||||
}
|
||||
|
||||
func verifyDependency(t *testing.T, c *chart.Chart) {
|
||||
if len(c.Metadata.Dependencies) != 2 {
|
||||
t.Errorf("Expected 2 dependencies, got %d", len(c.Metadata.Dependencies))
|
||||
}
|
||||
tests := []*chart.Dependency{
|
||||
{Name: "alpine", Version: "0.1.0", Repository: "https://example.com/charts"},
|
||||
{Name: "mariner", Version: "4.3.2", Repository: "https://example.com/charts"},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
d := c.Metadata.Dependencies[i]
|
||||
if d.Name != tt.Name {
|
||||
t.Errorf("Expected dependency named %q, got %q", tt.Name, d.Name)
|
||||
}
|
||||
if d.Version != tt.Version {
|
||||
t.Errorf("Expected dependency named %q to have version %q, got %q", tt.Name, tt.Version, d.Version)
|
||||
}
|
||||
if d.Repository != tt.Repository {
|
||||
t.Errorf("Expected dependency named %q to have repository %q, got %q", tt.Name, tt.Repository, d.Repository)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func verifyChartLock(t *testing.T, c *chart.Chart) {
|
||||
if len(c.Metadata.Dependencies) != 2 {
|
||||
t.Errorf("Expected 2 dependencies, got %d", len(c.Metadata.Dependencies))
|
||||
}
|
||||
tests := []*chart.Dependency{
|
||||
{Name: "alpine", Version: "0.1.0", Repository: "https://example.com/charts"},
|
||||
{Name: "mariner", Version: "4.3.2", Repository: "https://example.com/charts"},
|
||||
}
|
||||
for i, tt := range tests {
|
||||
d := c.Metadata.Dependencies[i]
|
||||
if d.Name != tt.Name {
|
||||
t.Errorf("Expected dependency named %q, got %q", tt.Name, d.Name)
|
||||
}
|
||||
if d.Version != tt.Version {
|
||||
t.Errorf("Expected dependency named %q to have version %q, got %q", tt.Name, tt.Version, d.Version)
|
||||
}
|
||||
if d.Repository != tt.Repository {
|
||||
t.Errorf("Expected dependency named %q to have repository %q, got %q", tt.Name, tt.Repository, d.Repository)
|
||||
}
|
||||
if len(c.Metadata.Dependencies) != 1 {
|
||||
t.Fatalf("expected 1 dependency specified in Chart.yaml, got %d", len(c.Metadata.Dependencies))
|
||||
}
|
||||
}
|
||||
|
||||
58
pkg/chartutil/testdata/subpop/Chart.yaml
vendored
58
pkg/chartutil/testdata/subpop/Chart.yaml
vendored
@@ -3,33 +3,33 @@ description: A Helm chart for Kubernetes
|
||||
name: parentchart
|
||||
version: 0.1.0
|
||||
dependencies:
|
||||
- name: subchart1
|
||||
repository: http://localhost:10191
|
||||
version: 0.1.0
|
||||
condition: subchart1.enabled
|
||||
tags:
|
||||
- front-end
|
||||
- subchart1
|
||||
import-values:
|
||||
- child: SC1data
|
||||
parent: imported-chart1
|
||||
- child: SC1data
|
||||
parent: overridden-chart1
|
||||
- child: imported-chartA
|
||||
parent: imported-chartA
|
||||
- child: imported-chartA-B
|
||||
parent: imported-chartA-B
|
||||
- child: overridden-chartA-B
|
||||
parent: overridden-chartA-B
|
||||
- child: SCBexported1A
|
||||
parent: .
|
||||
- SCBexported2
|
||||
- SC1exported1
|
||||
- name: subchart1
|
||||
repository: http://localhost:10191
|
||||
version: 0.1.0
|
||||
condition: subchart1.enabled
|
||||
tags:
|
||||
- front-end
|
||||
- subchart1
|
||||
import-values:
|
||||
- child: SC1data
|
||||
parent: imported-chart1
|
||||
- child: SC1data
|
||||
parent: overridden-chart1
|
||||
- child: imported-chartA
|
||||
parent: imported-chartA
|
||||
- child: imported-chartA-B
|
||||
parent: imported-chartA-B
|
||||
- child: overridden-chartA-B
|
||||
parent: overridden-chartA-B
|
||||
- child: SCBexported1A
|
||||
parent: .
|
||||
- SCBexported2
|
||||
- SC1exported1
|
||||
|
||||
- name: subchart2
|
||||
repository: http://localhost:10191
|
||||
version: 0.1.0
|
||||
condition: subchart2.enabled
|
||||
tags:
|
||||
- back-end
|
||||
- subchart2
|
||||
- name: subchart2
|
||||
repository: http://localhost:10191
|
||||
version: 0.1.0
|
||||
condition: subchart2.enabled
|
||||
tags:
|
||||
- back-end
|
||||
- subchart2
|
||||
|
||||
@@ -3,34 +3,34 @@ description: A Helm chart for Kubernetes
|
||||
name: subchart1
|
||||
version: 0.1.0
|
||||
dependencies:
|
||||
- name: subcharta
|
||||
repository: http://localhost:10191
|
||||
version: 0.1.0
|
||||
condition: subcharta.enabled,subchart1.subcharta.enabled
|
||||
tags:
|
||||
- front-end
|
||||
- subcharta
|
||||
import-values:
|
||||
- child: SCAdata
|
||||
parent: imported-chartA
|
||||
- child: SCAdata
|
||||
parent: overridden-chartA
|
||||
- child: SCAdata
|
||||
parent: imported-chartA-B
|
||||
- name: subcharta
|
||||
repository: http://localhost:10191
|
||||
version: 0.1.0
|
||||
condition: subcharta.enabled,subchart1.subcharta.enabled
|
||||
tags:
|
||||
- front-end
|
||||
- subcharta
|
||||
import-values:
|
||||
- child: SCAdata
|
||||
parent: imported-chartA
|
||||
- child: SCAdata
|
||||
parent: overridden-chartA
|
||||
- child: SCAdata
|
||||
parent: imported-chartA-B
|
||||
|
||||
- name: subchartb
|
||||
repository: http://localhost:10191
|
||||
version: 0.1.0
|
||||
condition: subchartb.enabled
|
||||
import-values:
|
||||
- child: SCBdata
|
||||
parent: imported-chartB
|
||||
- child: SCBdata
|
||||
parent: imported-chartA-B
|
||||
- child: exports.SCBexported2
|
||||
parent: exports.SCBexported2
|
||||
- SCBexported1
|
||||
- name: subchartb
|
||||
repository: http://localhost:10191
|
||||
version: 0.1.0
|
||||
condition: subchartb.enabled
|
||||
import-values:
|
||||
- child: SCBdata
|
||||
parent: imported-chartB
|
||||
- child: SCBdata
|
||||
parent: imported-chartA-B
|
||||
- child: exports.SCBexported2
|
||||
parent: exports.SCBexported2
|
||||
- SCBexported1
|
||||
|
||||
tags:
|
||||
- front-end
|
||||
- subchartb
|
||||
tags:
|
||||
- front-end
|
||||
- subchartb
|
||||
|
||||
@@ -3,17 +3,17 @@ description: A Helm chart for Kubernetes
|
||||
name: subchart2
|
||||
version: 0.1.0
|
||||
dependencies:
|
||||
- name: subchartb
|
||||
repository: http://localhost:10191
|
||||
version: 0.1.0
|
||||
condition: subchartb.enabled,subchart2.subchartb.enabled
|
||||
tags:
|
||||
- back-end
|
||||
- subchartb
|
||||
- name: subchartc
|
||||
repository: http://localhost:10191
|
||||
version: 0.1.0
|
||||
condition: subchartc.enabled
|
||||
tags:
|
||||
- back-end
|
||||
- subchartc
|
||||
- name: subchartb
|
||||
repository: http://localhost:10191
|
||||
version: 0.1.0
|
||||
condition: subchartb.enabled,subchart2.subchartb.enabled
|
||||
tags:
|
||||
- back-end
|
||||
- subchartb
|
||||
- name: subchartc
|
||||
repository: http://localhost:10191
|
||||
version: 0.1.0
|
||||
condition: subchartc.enabled
|
||||
tags:
|
||||
- back-end
|
||||
- subchartc
|
||||
|
||||
1
pkg/chartutil/testdata/subpop/values.yaml
vendored
1
pkg/chartutil/testdata/subpop/values.yaml
vendored
@@ -38,4 +38,3 @@ overridden-chartA-B:
|
||||
tags:
|
||||
front-end: true
|
||||
back-end: false
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ limitations under the License.
|
||||
package chartutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
@@ -29,10 +30,14 @@ import (
|
||||
)
|
||||
|
||||
// ErrNoTable indicates that a chart does not have a matching table.
|
||||
type ErrNoTable error
|
||||
type ErrNoTable string
|
||||
|
||||
func (e ErrNoTable) Error() string { return fmt.Sprintf("%q is not a table", e) }
|
||||
|
||||
// ErrNoValue indicates that Values does not contain a key with a value
|
||||
type ErrNoValue error
|
||||
type ErrNoValue string
|
||||
|
||||
func (e ErrNoValue) Error() string { return fmt.Sprintf("%q is not a value", e) }
|
||||
|
||||
// GlobalKey is the name of the Values key that is used for storing global vars.
|
||||
const GlobalKey = "global"
|
||||
@@ -63,9 +68,8 @@ func (v Values) Table(name string) (Values, error) {
|
||||
var err error
|
||||
|
||||
for _, n := range parsePath(name) {
|
||||
table, err = tableLookup(table, n)
|
||||
if err != nil {
|
||||
return table, err
|
||||
if table, err = tableLookup(table, n); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return table, err
|
||||
@@ -95,7 +99,7 @@ func (v Values) Encode(w io.Writer) error {
|
||||
func tableLookup(v Values, simple string) (Values, error) {
|
||||
v2, ok := v[simple]
|
||||
if !ok {
|
||||
return v, ErrNoTable(errors.Errorf("no table named %q (%v)", simple, v))
|
||||
return v, ErrNoTable(simple)
|
||||
}
|
||||
if vv, ok := v2.(map[string]interface{}); ok {
|
||||
return vv, nil
|
||||
@@ -108,8 +112,7 @@ func tableLookup(v Values, simple string) (Values, error) {
|
||||
return vv, nil
|
||||
}
|
||||
|
||||
var e ErrNoTable = errors.Errorf("no table named %q", simple)
|
||||
return Values{}, e
|
||||
return Values{}, ErrNoTable(simple)
|
||||
}
|
||||
|
||||
// ReadValues will parse YAML byte data into a Values.
|
||||
@@ -150,19 +153,18 @@ func CoalesceValues(chrt *chart.Chart, vals []byte) (Values, error) {
|
||||
return cvals, err
|
||||
}
|
||||
}
|
||||
|
||||
coalesce(chrt, cvals)
|
||||
|
||||
if _, err := coalesce(chrt, cvals); err != nil {
|
||||
return cvals, err
|
||||
}
|
||||
return coalesceDeps(chrt, cvals)
|
||||
}
|
||||
|
||||
// coalesce coalesces the dest values and the chart values, giving priority to the dest values.
|
||||
//
|
||||
// This is a helper function for CoalesceValues.
|
||||
func coalesce(ch *chart.Chart, dest map[string]interface{}) map[string]interface{} {
|
||||
func coalesce(ch *chart.Chart, dest map[string]interface{}) (map[string]interface{}, error) {
|
||||
coalesceValues(ch, dest)
|
||||
coalesceDeps(ch, dest)
|
||||
return dest
|
||||
return coalesceDeps(ch, dest)
|
||||
}
|
||||
|
||||
// coalesceDeps coalesces the dependencies of the given chart.
|
||||
@@ -181,7 +183,11 @@ func coalesceDeps(chrt *chart.Chart, dest map[string]interface{}) (map[string]in
|
||||
coalesceGlobals(dvmap, dest)
|
||||
|
||||
// Now coalesce the rest of the values.
|
||||
dest[subchart.Name()] = coalesce(subchart, dvmap)
|
||||
var err error
|
||||
dest[subchart.Name()], err = coalesce(subchart, dvmap)
|
||||
if err != nil {
|
||||
return dest, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return dest, nil
|
||||
@@ -363,20 +369,20 @@ func (v Values) pathValue(path []string) (interface{}, error) {
|
||||
if _, ok := v[path[0]]; ok && !istable(v[path[0]]) {
|
||||
return v[path[0]], nil
|
||||
}
|
||||
return nil, ErrNoValue(errors.Errorf("%v is not a value", path[0]))
|
||||
return nil, ErrNoValue(path[0])
|
||||
}
|
||||
|
||||
key, path := path[len(path)-1], path[:len(path)-1]
|
||||
// get our table for table path
|
||||
t, err := v.Table(joinPath(path...))
|
||||
if err != nil {
|
||||
return nil, ErrNoValue(errors.Errorf("%v is not a value", key))
|
||||
return nil, ErrNoValue(key)
|
||||
}
|
||||
// check table for key and ensure value is not a table
|
||||
if k, ok := t[key]; ok && !istable(k) {
|
||||
return k, nil
|
||||
}
|
||||
return nil, ErrNoValue(errors.Errorf("key not found: %s", key))
|
||||
return nil, ErrNoValue(key)
|
||||
}
|
||||
|
||||
func parsePath(key string) []string { return strings.Split(key, ".") }
|
||||
|
||||
@@ -26,7 +26,6 @@ import (
|
||||
kversion "k8s.io/apimachinery/pkg/version"
|
||||
|
||||
"k8s.io/helm/pkg/chart"
|
||||
"k8s.io/helm/pkg/chart/loader"
|
||||
"k8s.io/helm/pkg/version"
|
||||
)
|
||||
|
||||
@@ -290,11 +289,7 @@ pequod:
|
||||
`
|
||||
|
||||
func TestCoalesceValues(t *testing.T) {
|
||||
tchart := "testdata/moby"
|
||||
c, err := loader.LoadDir(tchart)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c := loadChart(t, "testdata/moby")
|
||||
|
||||
v, err := CoalesceValues(c, []byte(testCoalesceValuesYaml))
|
||||
if err != nil {
|
||||
|
||||
@@ -97,15 +97,10 @@ func (c *Client) InstallReleaseFromChart(chart *chart.Chart, ns string, opts ...
|
||||
}
|
||||
var m map[string]interface{}
|
||||
yaml.Unmarshal(req.Values, &m)
|
||||
err := chartutil.ProcessDependencyEnabled(req.Chart, m)
|
||||
err := chartutil.ProcessDependencies(req.Chart, m)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
err = chartutil.ProcessDependencyImportValues(req.Chart)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.tiller.InstallRelease(req)
|
||||
}
|
||||
|
||||
@@ -171,13 +166,9 @@ func (c *Client) UpdateReleaseFromChart(rlsName string, chart *chart.Chart, opts
|
||||
if err := yaml.Unmarshal(req.Values, &m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := chartutil.ProcessDependencyEnabled(req.Chart, m); err != nil {
|
||||
if err := chartutil.ProcessDependencies(req.Chart, m); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := chartutil.ProcessDependencyImportValues(req.Chart); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return c.tiller.UpdateRelease(req)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user