diff --git a/docs/charts.md b/docs/charts.md index b7d97cc0b..677e9e66d 100644 --- a/docs/charts.md +++ b/docs/charts.md @@ -302,6 +302,98 @@ helm install --set tags.front-end=true --set subchart2.enabled=false * The `tags:` key in values must be a top level key. Globals and nested `tags:` tables are not currently supported. +#### Importing Child Values via requirements.yaml + +In some cases it is desirable to allow a child chart's values to propagate to the parent chart and be shared +as common defaults. The values to be imported can be specified in the parent chart's requirements.yaml +using a YAML list format that contains the source of the values to be imported (child) and the +destination path in the parent chart's values (parent). + +The optional `import-values` in the example below instructs Helm to take any values found at `child:` +path and copy them to the path at `parent:` + +```` +# parent's requirements.yaml +dependencies: + - name: subchart1 + repository: http://localhost:10191 + version: 0.1.0 + ... + import-values: + - child: default.data + parent: myimports +```` +In the above example, values found at `default.data` in the subchart1's values will be imported +to the `myimports` key in the parent chart's values as detailed below: + +```` +# parent's values + +myimports: + myint: 0 + mybool: false + mystring: "helm rocks" + + +```` +```` +# subchart1's values.yaml + +default: + data: + myint: 999 + mybool: true + +```` +The parent chart's resulting values would be: + +```` +# parent's final values + +myimports: + myint: 999 + mybool: true + mystring: "helm rocks" + +```` + +The parent's final values now contains the `myint` and `mybool` fields imported from subchart1. + +##### Using the exports convention + +If a values.yaml contains an `exports` field at the root, it's contents may be imported +directly into the parent's values by using a simple string format as in the example below: + +```` +# parent's requirements.yaml + ... + import-values: + - data +```` +```` +# child values + +... +exports: + data: + myint:99 +```` + +Since we are using the simple string `data` in our import list, Helm looks in the the `exports` +field of the child chart for `data` key and imports its contents. + +The final parent values would contain our exported field. + +```` +# parent's values +... +myint: 99 + +```` + +Please note the parent key `data` is not contained in the parent's final values. If +you need to specify the parent key, use the 'child/parent' format. + ## Templates and Values Helm Chart templates are written in the diff --git a/pkg/chartutil/requirements.go b/pkg/chartutil/requirements.go index 189e2c647..31e4d255a 100644 --- a/pkg/chartutil/requirements.go +++ b/pkg/chartutil/requirements.go @@ -271,6 +271,9 @@ func ProcessRequirementsEnabled(c *chart.Chart, v *chart.Config) error { // pathToMap creates a nested map given a YAML path in dot notation. func pathToMap(path string, data map[string]interface{}) map[string]interface{} { + if path == "." { + return data + } ap := strings.Split(path, ".") if len(ap) == 0 { return nil @@ -318,15 +321,18 @@ func processImportValues(c *chart.Chart, v *chart.Config) error { if err != nil { return err } + // combine chart values and its dependencies' values cvals, err := CoalesceValues(c, v) if err != nil { return err } nv := v.GetValues() b := make(map[string]interface{}) - for kk, v3 := range nv { - b[kk] = v3 + // convert values to map + for kk, vvv := range nv { + b[kk] = vvv } + // import values from each dependency if specified in import-values for _, r := range reqs.Dependencies { if len(r.ImportValues) > 0 { var outiv []interface{} @@ -339,47 +345,40 @@ func processImportValues(c *chart.Chart, v *chart.Config) error { } outiv = append(outiv, nm) s := r.Name + "." + nm["child"] + // get child table vv, err := cvals.Table(s) if err != nil { log.Printf("Warning: ImportValues missing table %v", err) continue } - if nm["parent"] == "." { - coalesceTables(b, vv.AsMap()) - } else { - - vm := pathToMap(nm["parent"], vv.AsMap()) - coalesceTables(b, vm) - } + // create value map from child to be merged into parent + vm := pathToMap(nm["parent"], vv.AsMap()) + b = coalesceTables(cvals, vm) case string: nm := make(map[string]string) nm["child"] = "exports." + iv nm["parent"] = "." outiv = append(outiv, nm) s := r.Name + "." + nm["child"] - vv, err := cvals.Table(s) + vm, err := cvals.Table(s) if err != nil { log.Printf("Warning: ImportValues missing table %v", err) continue } - coalesceTables(b, vv.AsMap()) + b = coalesceTables(b, vm.AsMap()) } } // set our formatted import values r.ImportValues = outiv } } - cv, err := coalesceValues(c, b) - if err != nil { - return err - } - y, err := yaml.Marshal(cv) + b = coalesceTables(b, cvals) + y, err := yaml.Marshal(b) if err != nil { return err } - bb := &chart.Config{Raw: string(y)} - v = bb - c.Values = bb + // set the new values + c.Values.Raw = string(y) return nil } diff --git a/pkg/chartutil/requirements_test.go b/pkg/chartutil/requirements_test.go index 59c4ecc11..c92c9f052 100644 --- a/pkg/chartutil/requirements_test.go +++ b/pkg/chartutil/requirements_test.go @@ -217,21 +217,65 @@ func TestProcessRequirementsImportValues(t *testing.T) { v := &chart.Config{Raw: ""} e := make(map[string]string) - e["imported-from-chart1.type"] = "ClusterIP" - e["imported-from-chart1.name"] = "nginx" - e["imported-from-chart1.externalPort"] = "80" - // this doesn't exist in imported table. it should merge and remain unchanged - e["imported-from-chart1.notimported1"] = "1" - e["imported-from-chartA-via-chart1.limits.cpu"] = "300m" - e["imported-from-chartA-via-chart1.limits.memory"] = "300Mi" - e["imported-from-chartA-via-chart1.limits.volume"] = "11" - e["imported-from-chartA-via-chart1.requests.truthiness"] = "0.01" - // single list items (looks for exports. parent key) - e["imported-from-chartB-via-chart1.databint"] = "1" - e["imported-from-chartB-via-chart1.databstr"] = "x.y.z" - e["parent1c3"] = "true" - // checks that a chartb value was merged in with charta values - e["imported-from-chartA-via-chart1.resources.limits.shares"] = "100" + + e["imported-chart1.SC1bool"] = "true" + e["imported-chart1.SC1float"] = "3.14" + e["imported-chart1.SC1int"] = "100" + e["imported-chart1.SC1string"] = "dollywood" + e["imported-chart1.SC1extra1"] = "11" + e["imported-chart1.SPextra1"] = "helm rocks" + e["imported-chart1.SC1extra1"] = "11" + + e["imported-chartA.SCAbool"] = "false" + e["imported-chartA.SCAfloat"] = "3.1" + e["imported-chartA.SCAint"] = "55" + e["imported-chartA.SCAstring"] = "jabba" + e["imported-chartA.SPextra3"] = "1.337" + e["imported-chartA.SC1extra2"] = "1.337" + e["imported-chartA.SCAnested1.SCAnested2"] = "true" + + e["imported-chartA-B.SCAbool"] = "false" + e["imported-chartA-B.SCAfloat"] = "3.1" + e["imported-chartA-B.SCAint"] = "55" + e["imported-chartA-B.SCAstring"] = "jabba" + + e["imported-chartA-B.SCBbool"] = "true" + e["imported-chartA-B.SCBfloat"] = "7.77" + e["imported-chartA-B.SCBint"] = "33" + e["imported-chartA-B.SCBstring"] = "boba" + e["imported-chartA-B.SPextra5"] = "k8s" + e["imported-chartA-B.SC1extra5"] = "tiller" + + e["overridden-chart1.SC1bool"] = "false" + e["overridden-chart1.SC1float"] = "3.141592" + e["overridden-chart1.SC1int"] = "99" + e["overridden-chart1.SC1string"] = "pollywog" + e["overridden-chart1.SPextra2"] = "42" + + e["overridden-chartA.SCAbool"] = "true" + e["overridden-chartA.SCAfloat"] = "41.3" + e["overridden-chartA.SCAint"] = "808" + e["overridden-chartA.SCAstring"] = "jaberwocky" + e["overridden-chartA.SPextra4"] = "true" + + e["overridden-chartA-B.SCAbool"] = "true" + e["overridden-chartA-B.SCAfloat"] = "41.3" + e["overridden-chartA-B.SCAint"] = "808" + e["overridden-chartA-B.SCAstring"] = "jaberwocky" + e["overridden-chartA-B.SCBbool"] = "false" + e["overridden-chartA-B.SCBfloat"] = "1.99" + e["overridden-chartA-B.SCBint"] = "77" + e["overridden-chartA-B.SCBstring"] = "jango" + e["overridden-chartA-B.SPextra6"] = "111" + e["overridden-chartA-B.SCAextra1"] = "23" + e["overridden-chartA-B.SCBextra1"] = "13" + e["overridden-chartA-B.SC1extra6"] = "77" + + // `exports` style + e["SCBexported1B"] = "1965" + e["SC1extra7"] = "true" + e["SCBexported2A"] = "blaster" + e["global.SC1exported2.all.SC1exported3"] = "SC1expstr" verifyRequirementsImportValues(t, c, v, e) } diff --git a/pkg/chartutil/testdata/subpop/charts/subchart1/charts/subchartA/values.yaml b/pkg/chartutil/testdata/subpop/charts/subchart1/charts/subchartA/values.yaml index 8c348e86c..712b3a2fa 100644 --- a/pkg/chartutil/testdata/subpop/charts/subchart1/charts/subchartA/values.yaml +++ b/pkg/chartutil/testdata/subpop/charts/subchart1/charts/subchartA/values.yaml @@ -2,24 +2,16 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. # subchartA -replicaCount: 1 -image: - repository: nginx - tag: stable - pullPolicy: IfNotPresent service: name: nginx type: ClusterIP externalPort: 80 internalPort: 80 -resources: - limits: - cpu: 300m - memory: 300Mi - plasticity: 1.7331 - volume: 11 - requests: - cpu: 350m - memory: 350Mi - truthiness: 0.01 +SCAdata: + SCAbool: false + SCAfloat: 3.1 + SCAint: 55 + SCAstring: "jabba" + SCAnested1: + SCAnested2: true diff --git a/pkg/chartutil/testdata/subpop/charts/subchart1/charts/subchartB/values.yaml b/pkg/chartutil/testdata/subpop/charts/subchart1/charts/subchartB/values.yaml index 5f473ef61..aba524d97 100644 --- a/pkg/chartutil/testdata/subpop/charts/subchart1/charts/subchartB/values.yaml +++ b/pkg/chartutil/testdata/subpop/charts/subchart1/charts/subchartB/values.yaml @@ -1,29 +1,37 @@ # Default values for subchart. # This is a YAML-formatted file. # Declare variables to be passed into your templates. -replicaCount: 1 -image: - repository: nginx - tag: stable - pullPolicy: IfNotPresent service: name: nginx type: ClusterIP externalPort: 80 internalPort: 80 -resources: - limits: - cpu: 100m - memory: 128Mi - requests: - cpu: 100m - memory: 128Mi + +SCBdata: + SCBbool: true + SCBfloat: 7.77 + SCBint: 33 + SCBstring: "boba" + exports: - convention1: - data: - databint: 1 - databstr: x.y.z - convention2: - resources: - limits: - shares: 100 + SCBexported1: + SCBexported1A: + SCBexported1B: 1965 + + SCBexported2: + SCBexported2A: "blaster" + +global: + kolla: + nova: + api: + all: + port: 8774 + metadata: + all: + port: 8775 +test: + dummy: 1 + + + diff --git a/pkg/chartutil/testdata/subpop/charts/subchart1/requirements.yaml b/pkg/chartutil/testdata/subpop/charts/subchart1/requirements.yaml index cb62b9f36..abfe85e76 100644 --- a/pkg/chartutil/testdata/subpop/charts/subchart1/requirements.yaml +++ b/pkg/chartutil/testdata/subpop/charts/subchart1/requirements.yaml @@ -7,18 +7,26 @@ dependencies: - front-end - subcharta import-values: - - child: resources.limits - parent: imported-from-chartA.limits - - child: resources.requests - parent: imported-from-chartA.requests + - 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: - - convention1 - - convention2 + - child: SCBdata + parent: imported-chartB + - child: SCBdata + parent: imported-chartA-B + - child: exports.SCBexported2 + parent: exports.SCBexported2 + - SCBexported1 + tags: - front-end - subchartb diff --git a/pkg/chartutil/testdata/subpop/charts/subchart1/values.yaml b/pkg/chartutil/testdata/subpop/charts/subchart1/values.yaml index 15ba88485..4b5bd6bd9 100644 --- a/pkg/chartutil/testdata/subpop/charts/subchart1/values.yaml +++ b/pkg/chartutil/testdata/subpop/charts/subchart1/values.yaml @@ -2,26 +2,54 @@ # This is a YAML-formatted file. # Declare variables to be passed into your templates. # subchart1 -replicaCount: 1 -image: - repository: nginx - tag: stable - pullPolicy: IfNotPresent service: name: nginx type: ClusterIP externalPort: 80 internalPort: 80 -resources: - limits: - cpu: 200m - memory: 200Mi - plasticity: 0 - requests: - cpu: 250m - memory: 250Mi - truthiness: 200 -exports: - convention3: - parent1c3: true + +SC1data: + SC1bool: true + SC1float: 3.14 + SC1int: 100 + SC1string: "dollywood" + SC1extra1: 11 + +imported-chartA: + SC1extra2: 1.337 + +overridden-chartA: + SCAbool: true + SCAfloat: 3.14 + SCAint: 100 + SCAstring: "jabathehut" + SC1extra3: true + +imported-chartA-B: + SC1extra5: "tiller" + +overridden-chartA-B: + SCAbool: true + SCAfloat: 3.33 + SCAint: 555 + SCAstring: "wormwood" + SCAextra1: 23 + + SCBbool: true + SCBfloat: 0.25 + SCBint: 98 + SCBstring: "murkwood" + SCBextra1: 13 + + SC1extra6: 77 + +SCBexported1A: + SC1extra7: true + +exports: + SC1exported1: + global: + SC1exported2: + all: + SC1exported3: "SC1expstr" \ No newline at end of file diff --git a/pkg/chartutil/testdata/subpop/requirements.yaml b/pkg/chartutil/testdata/subpop/requirements.yaml index e299d057b..a8eb0aace 100644 --- a/pkg/chartutil/testdata/subpop/requirements.yaml +++ b/pkg/chartutil/testdata/subpop/requirements.yaml @@ -7,16 +7,21 @@ dependencies: - front-end - subchart1 import-values: - - child: service - parent: imported-from-chart1 - - child: imported-from-chartA - parent: imported-from-chartA-via-chart1 - - convention3 - # this merges chartb "shares" into charta "limits" - - child: resources.limits - parent: imported-from-chartA-via-chart1.resources.limits - - child: data - parent: imported-from-chartB-via-chart1 + - 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 diff --git a/pkg/chartutil/testdata/subpop/values.yaml b/pkg/chartutil/testdata/subpop/values.yaml index f03c449cf..55e872d41 100644 --- a/pkg/chartutil/testdata/subpop/values.yaml +++ b/pkg/chartutil/testdata/subpop/values.yaml @@ -1,19 +1,39 @@ # parent/values.yaml -# switch-like -imported-from-chart1: - name: bathtubginx - type: None - externalPort: 25 - notimported1: 1 - -imported-from-chartA-via-chart1: - limits: - cpu: 100m - memory: 100Mi - notimported2: 100 - requests: - truthiness: 33.3 +imported-chart1: + SPextra1: "helm rocks" + +overridden-chart1: + SC1bool: false + SC1float: 3.141592 + SC1int: 99 + SC1string: "pollywog" + SPextra2: 42 + + +imported-chartA: + SPextra3: 1.337 + +overridden-chartA: + SCAbool: true + SCAfloat: 41.3 + SCAint: 808 + SCAstring: "jaberwocky" + SPextra4: true + +imported-chartA-B: + SPextra5: "k8s" + +overridden-chartA-B: + SCAbool: true + SCAfloat: 41.3 + SCAint: 808 + SCAstring: "jaberwocky" + SCBbool: false + SCBfloat: 1.99 + SCBint: 77 + SCBstring: "jango" + SPextra6: 111 tags: front-end: true