breaking: Fix the inherit feature to support multi-inheritance (#674)

* breaking: Fix the inherit feature introduced in Helmfile v0.150.0 for multi-inheritance

Follow-up for #435
Addresses https://github.com/helmfile/helmfile/discussions/656#discussioncomment-4877360 towards Helmfile v1

Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>

* Print a deprecation warning on releases[].inherit of map

Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>

---------

Signed-off-by: Yusuke Kuoka <ykuoka@gmail.com>
This commit is contained in:
Yusuke Kuoka 2023-02-07 09:18:19 +09:00 committed by GitHub
parent b359efef8b
commit fc027d1538
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 86 additions and 67 deletions

View File

@ -435,23 +435,23 @@ func TestTemplate_CyclicInheritance(t *testing.T) {
templates: templates:
a: a:
inherit: inherit:
template: b - template: b
values: values:
- a.yaml - a.yaml
b: b:
inherit: inherit:
template: c - template: c
values: values:
- b.yaml - b.yaml
c: c:
inherit: inherit:
template: a - template: a
values: values:
- c.yaml - c.yaml
releases: releases:
- name: app1 - name: app1
inherit: inherit:
template: a - template: a
chart: incubator/raw chart: incubator/raw
`, `,
} }

View File

@ -213,6 +213,8 @@ type Inherit struct {
Except []string `yaml:"except,omitempty"` Except []string `yaml:"except,omitempty"`
} }
type Inherits []Inherit
// ReleaseSpec defines the structure of a helm release // ReleaseSpec defines the structure of a helm release
type ReleaseSpec struct { type ReleaseSpec struct {
// Chart is the name of the chart being installed to create this release // Chart is the name of the chart being installed to create this release
@ -353,7 +355,22 @@ type ReleaseSpec struct {
PostRenderer *string `yaml:"postRenderer,omitempty"` PostRenderer *string `yaml:"postRenderer,omitempty"`
// Inherit is used to inherit a release template from a release or another release template // Inherit is used to inherit a release template from a release or another release template
Inherit Inherit `yaml:"inherit,omitempty"` Inherit Inherits `yaml:"inherit,omitempty"`
}
func (r *Inherits) UnmarshalYAML(unmarshal func(interface{}) error) error {
var v0151 []Inherit
if err := unmarshal(&v0151); err != nil {
var v0150 Inherit
if err := unmarshal(&v0150); err != nil {
return err
}
fmt.Fprintf(os.Stderr, "releases[].inherit of map(%+v) has been deprecated and will be removed in v0.152.0. Wrap it into an array: %v\n", v0150, err)
*r = []Inherit{v0150}
return nil
}
*r = v0151
return nil
} }
// ChartPathOrName returns ChartPath if it is non-empty, and returns Chart otherwise. // ChartPathOrName returns ChartPath if it is non-empty, and returns Chart otherwise.

View File

@ -154,7 +154,10 @@ func (e CyclicReleaseTemplateInheritanceError) Error() string {
// a cyclic relese template inheritance. // a cyclic relese template inheritance.
// This functions fails with a CyclicReleaseTemplateInheritanceError if it finds a cyclic inheritance. // This functions fails with a CyclicReleaseTemplateInheritanceError if it finds a cyclic inheritance.
func (st *HelmState) releaseWithInheritedTemplate(r *ReleaseSpec, inheritancePath []string) (*ReleaseSpec, error) { func (st *HelmState) releaseWithInheritedTemplate(r *ReleaseSpec, inheritancePath []string) (*ReleaseSpec, error) {
templateName := r.Inherit.Template var merged ReleaseSpec
for _, inherit := range r.Inherit {
templateName := inherit.Template
if templateName == "" { if templateName == "" {
return r, nil return r, nil
} }
@ -184,7 +187,7 @@ func (st *HelmState) releaseWithInheritedTemplate(r *ReleaseSpec, inheritancePat
return nil, fmt.Errorf("unable to load release template %q: %w", templateName, err) return nil, fmt.Errorf("unable to load release template %q: %w", templateName, err)
} }
for _, k := range r.Inherit.Except { for _, k := range inherit.Except {
switch k { switch k {
case "labels": case "labels":
src.Labels = map[string]string{} src.Labels = map[string]string{}
@ -203,17 +206,16 @@ func (st *HelmState) releaseWithInheritedTemplate(r *ReleaseSpec, inheritancePat
st.logger.Debugf("excluded field %q when inheriting template %q to release %q", k, templateName, r.Name) st.logger.Debugf("excluded field %q when inheriting template %q to release %q", k, templateName, r.Name)
} }
var merged ReleaseSpec
if err := mergo.Merge(&merged, src, mergo.WithAppendSlice, mergo.WithSliceDeepCopy); err != nil { if err := mergo.Merge(&merged, src, mergo.WithAppendSlice, mergo.WithSliceDeepCopy); err != nil {
return nil, fmt.Errorf("unable to inherit release template %q: %w", templateName, err) return nil, fmt.Errorf("unable to inherit release template %q: %w", templateName, err)
} }
}
if err := mergo.Merge(&merged, r, mergo.WithAppendSlice, mergo.WithSliceDeepCopy); err != nil { if err := mergo.Merge(&merged, r, mergo.WithAppendSlice, mergo.WithSliceDeepCopy); err != nil {
return nil, fmt.Errorf("unable to load release %q: %w", r.Name, err) return nil, fmt.Errorf("unable to load release %q: %w", r.Name, err)
} }
merged.Inherit = Inherit{} merged.Inherit = nil
return &merged, nil return &merged, nil
} }

View File

@ -38,39 +38,39 @@ func TestGenerateID(t *testing.T) {
run(testcase{ run(testcase{
subject: "baseline", subject: "baseline",
release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"},
want: "foo-values-5d85cdbb5d", want: "foo-values-7cd4757dfd",
}) })
run(testcase{ run(testcase{
subject: "different bytes content", subject: "different bytes content",
release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"},
data: []byte(`{"k":"v"}`), data: []byte(`{"k":"v"}`),
want: "foo-values-9548bdcd9", want: "foo-values-7bb85f848f",
}) })
run(testcase{ run(testcase{
subject: "different map content", subject: "different map content",
release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"}, release: ReleaseSpec{Name: "foo", Chart: "incubator/raw"},
data: map[string]interface{}{"k": "v"}, data: map[string]interface{}{"k": "v"},
want: "foo-values-5db884fb87", want: "foo-values-c57649655",
}) })
run(testcase{ run(testcase{
subject: "different chart", subject: "different chart",
release: ReleaseSpec{Name: "foo", Chart: "stable/envoy"}, release: ReleaseSpec{Name: "foo", Chart: "stable/envoy"},
want: "foo-values-6596c997cc", want: "foo-values-bf798c8f",
}) })
run(testcase{ run(testcase{
subject: "different name", subject: "different name",
release: ReleaseSpec{Name: "bar", Chart: "incubator/raw"}, release: ReleaseSpec{Name: "bar", Chart: "incubator/raw"},
want: "bar-values-5ccfd9f8b5", want: "bar-values-5465f47b4f",
}) })
run(testcase{ run(testcase{
subject: "specific ns", subject: "specific ns",
release: ReleaseSpec{Name: "foo", Chart: "incubator/raw", Namespace: "myns"}, release: ReleaseSpec{Name: "foo", Chart: "incubator/raw", Namespace: "myns"},
want: "myns-foo-values-bc7cd5b87", want: "myns-foo-values-55f77767f5",
}) })
for id, n := range ids { for id, n := range ids {

View File

@ -17,7 +17,7 @@ templates:
labels: labels:
template1: template1 template1: template1
inherit: inherit:
template: base - template: base
except: except:
- labels - labels
template2: template2:
@ -29,14 +29,14 @@ templates:
labels: labels:
template2: template2 template2: template2
inherit: inherit:
template: base - template: base
except: except:
- valuesTemplate - valuesTemplate
releases: releases:
- name: foo1 - name: foo1
inherit: inherit:
template: template1 - template: template1
values: values:
- templates: - templates:
- | - |
@ -49,7 +49,7 @@ releases:
{{` {{ (unset .Values "templates") | toYaml | nindent 2 }} `}} {{` {{ (unset .Values "templates") | toYaml | nindent 2 }} `}}
- name: foo2 - name: foo2
inherit: inherit:
template: template2 - template: template2
values: values:
- templates: - templates:
- | - |