Introduce import-values strategy + revert default strategy for backwards compat

Signed-off-by: Seppe Volkaerts <seppevolkaerts@hotmail.com>
pull/11162/head
Seppe Volkaerts 3 years ago
parent 001850aa4f
commit 3929178912
No known key found for this signature in database
GPG Key ID: EAC2C4F089D6BC64

@ -226,49 +226,72 @@ func processImportValues(c *chart.Chart) error {
if err != nil { if err != nil {
return err return err
} }
b := make(map[string]interface{}) c.Values = copyMap(cvals)
overrides := make(map[string]interface{})
// import values from each dependency if specified in import-values // import values from each dependency if specified in import-values
for _, r := range c.Metadata.Dependencies { for _, r := range c.Metadata.Dependencies {
var outiv []interface{} var outiv []interface{}
for _, riv := range r.ImportValues { for _, riv := range r.ImportValues {
var strategy string
var values map[string]interface{}
var child string
parent := "."
switch iv := riv.(type) { switch iv := riv.(type) {
case map[string]interface{}: case map[string]interface{}:
child := iv["child"].(string) var strategyOk bool
parent := iv["parent"].(string) strategy, strategyOk = iv["strategy"].(string)
if !strategyOk {
outiv = append(outiv, map[string]string{ strategy = "ifNotPresent"
"child": child, }
"parent": parent, if key, ok := iv["key"].(string); ok {
}) child = "exports." + key
vm, err := cvals.Table(r.Name + "." + child)
// get child table if err != nil {
log.Printf("Warning: ImportValues missing table: %v", err)
continue
}
values = vm.AsMap()
} else {
child = iv["child"].(string)
parent = iv["parent"].(string)
vv, err := cvals.Table(r.Name + "." + child) vv, err := cvals.Table(r.Name + "." + child)
if err != nil { if err != nil {
log.Printf("Warning: ImportValues missing table from chart %s: %v", r.Name, err) log.Printf("Warning: ImportValues missing table from chart %s: %v", r.Name, err)
continue continue
} }
// create value map from child to be merged into parent values = pathToMap(parent, vv.AsMap())
b = CoalesceTables(cvals, pathToMap(parent, vv.AsMap())) }
case string: case string:
// backwards compat to use the override strategy when using a string
strategy = "override"
child := "exports." + iv child := "exports." + iv
outiv = append(outiv, map[string]string{
"child": child,
"parent": ".",
})
vm, err := cvals.Table(r.Name + "." + child) vm, err := cvals.Table(r.Name + "." + child)
if err != nil { if err != nil {
log.Printf("Warning: ImportValues missing table: %v", err) log.Printf("Warning: ImportValues missing table: %v", err)
continue continue
} }
b = CoalesceTables(b, vm.AsMap()) values = vm.AsMap()
}
// merge the values from the child into the parent values according to the import strategy
if strategy == "override" {
overrides = CoalesceTables(overrides, values)
} else if strategy == "ifNotPresent" {
c.Values = CoalesceTables(c.Values, values)
} else {
log.Printf("Warning: ImportValues with an invalid import strategy %v", strategy)
continue
} }
outiv = append(outiv, map[string]string{
"child": child,
"parent": parent,
"strategy": strategy,
})
} }
// set our formatted import values // set our formatted import values
r.ImportValues = outiv r.ImportValues = outiv
} }
// merge the overrides into the parent values
// set the new values c.Values = CoalesceTables(overrides, c.Values)
c.Values = CoalesceTables(cvals, b)
return nil return nil
} }

@ -206,6 +206,8 @@ func TestProcessDependencyImportValues(t *testing.T) {
e["overridden-chartA-B.SCBextra1"] = "13" e["overridden-chartA-B.SCBextra1"] = "13"
e["overridden-chartA-B.SC1extra6"] = "77" e["overridden-chartA-B.SC1extra6"] = "77"
e["subchart1.force-overridden-chartA.SCAFbool"] = "false"
// `exports` style // `exports` style
e["SCBexported1B"] = "1965" e["SCBexported1B"] = "1965"
e["SC1extra7"] = "true" e["SC1extra7"] = "true"
@ -225,15 +227,15 @@ func TestProcessDependencyImportValues(t *testing.T) {
switch pv := pv.(type) { switch pv := pv.(type) {
case float64: case float64:
if s := strconv.FormatFloat(pv, 'f', -1, 64); s != vv { if s := strconv.FormatFloat(pv, 'f', -1, 64); s != vv {
t.Errorf("failed to match imported float value %v with expected %v", s, vv) t.Errorf("%v: failed to match imported float value %v with expected %v", kk, s, vv)
} }
case bool: case bool:
if b := strconv.FormatBool(pv); b != vv { if b := strconv.FormatBool(pv); b != vv {
t.Errorf("failed to match imported bool value %v with expected %v", b, vv) t.Errorf("%v: failed to match imported bool value %v with expected %v", kk, b, vv)
} }
default: default:
if pv != vv { if pv != vv {
t.Errorf("failed to match imported string value %q with expected %q", pv, vv) t.Errorf("%v: failed to match imported string value %q with expected %q", kk, pv, vv)
} }
} }
} }
@ -244,8 +246,9 @@ func TestProcessDependencyImportValuesMultiLevelPrecedence(t *testing.T) {
e := make(map[string]string) e := make(map[string]string)
e["app1.service.port"] = "3456" e["app1.service.port"] = "1010" // app1 is the chart with the default import override behavior
e["app2.service.port"] = "8080" e["app2.service.port"] = "2222" // app2 is the chart with the ifNotPresent import behavior
e["app3.service.port"] = "1234" // app3 is the chart with the default import override behavior, but the port is overridden in the umbrella chart
if err := processDependencyImportValues(c); err != nil { if err := processDependencyImportValues(c); err != nil {
t.Fatalf("processing import values dependencies %v", err) t.Fatalf("processing import values dependencies %v", err)

@ -17,7 +17,9 @@ dependencies:
parent: overridden-chartA parent: overridden-chartA
- child: SCAdata - child: SCAdata
parent: imported-chartA-B parent: imported-chartA-B
- child: SCAdata-forced
parent: force-overridden-chartA
strategy: override
- name: subchartb - name: subchartb
repository: http://localhost:10191 repository: http://localhost:10191
version: 0.1.0 version: 0.1.0

@ -14,4 +14,6 @@ SCAdata:
SCAstring: "jabba" SCAstring: "jabba"
SCAnested1: SCAnested1:
SCAnested2: true SCAnested2: true
SCAdata-forced:
SCAFbool: false

@ -26,6 +26,9 @@ overridden-chartA:
SCAstring: "jabbathehut" SCAstring: "jabbathehut"
SC1extra3: true SC1extra3: true
force-overridden-chartA:
SCAFbool: true # Will be overridden by the import
imported-chartA-B: imported-chartA-B:
SC1extra5: "tiller" SC1extra5: "tiller"

@ -10,7 +10,6 @@ overridden-chart1:
SC1string: "pollywog" SC1string: "pollywog"
SPextra2: 42 SPextra2: 42
imported-chartA: imported-chartA:
SPextra3: 1.337 SPextra3: 1.337

@ -11,3 +11,6 @@ dependencies:
- name: app2 - name: app2
version: 0.1.0 version: 0.1.0
condition: app2.enabled condition: app2.enabled
- name: app3
version: 0.1.0
condition: app3.enabled

@ -2,4 +2,4 @@ exports:
defaults: defaults:
service: service:
type: ClusterIP type: ClusterIP
port: 9090 port: 1010

@ -1,3 +1,3 @@
service: service:
type: ClusterIP type: ClusterIP
port: 1234 port: 1111

@ -8,4 +8,5 @@ dependencies:
- name: library - name: library
version: 0.1.0 version: 0.1.0
import-values: import-values:
- defaults - key: defaults
strategy: ifNotPresent

@ -2,4 +2,4 @@ exports:
defaults: defaults:
service: service:
type: ClusterIP type: ClusterIP
port: 9090 port: 2020

@ -1,3 +1,3 @@
service: service:
type: ClusterIP type: ClusterIP
port: 8080 port: 2222

@ -0,0 +1,11 @@
apiVersion: v2
name: app3
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
dependencies:
- name: library
version: 0.1.0
import-values:
- defaults

@ -0,0 +1,5 @@
apiVersion: v2
name: library
description: A Helm chart for Kubernetes
type: library
version: 0.1.0

@ -0,0 +1,9 @@
apiVersion: v1
kind: Service
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http

@ -0,0 +1,5 @@
exports:
defaults:
service:
type: ClusterIP
port: 3030

@ -1,8 +1,11 @@
app1: app1:
enabled: true enabled: true
service:
type: ClusterIP
port: 3456
app2: app2:
enabled: true enabled: true
app3:
enabled: true
service:
type: ClusterIP
port: 1234

Loading…
Cancel
Save