Make advanced templating backward-compatible (#833)

This is a follow-up for #823
Ref https://github.com/roboll/helmfile/pull/823#discussion_r319712283
This commit is contained in:
KUOKA Yusuke 2019-08-31 22:37:46 +09:00 committed by GitHub
parent 01ae59fedd
commit 4bc99337b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 81 additions and 65 deletions

View File

@ -102,7 +102,7 @@ Release Templating supports the following parts of release definition:
- `set` block values: - `set` block values:
```yaml ```yaml
# ... # ...
set: setTemplate:
- name: '{{`{{ .Release.Name }}`}}' - name: '{{`{{ .Release.Name }}`}}'
values: '{{`{{ .Release.Namespace }}`}}' values: '{{`{{ .Release.Namespace }}`}}'
# ... # ...
@ -110,7 +110,7 @@ Release Templating supports the following parts of release definition:
- `values` and `secrets` file paths: - `values` and `secrets` file paths:
```yaml ```yaml
# ... # ...
values: valuesTemplate:
- config/{{`{{ .Release.Name }}`}}/values.yaml - config/{{`{{ .Release.Name }}`}}/values.yaml
secrets: secrets:
- config/{{`{{ .Release.Name }}`}}/secrets.yaml - config/{{`{{ .Release.Name }}`}}/secrets.yaml
@ -119,7 +119,7 @@ Release Templating supports the following parts of release definition:
- inline `values` map: - inline `values` map:
```yaml ```yaml
# ... # ...
values: valuesTemplate:
- image: - image:
tag: `{{ .Release.Labels.tag }}` tag: `{{ .Release.Labels.tag }}`
# ... # ...

View File

@ -93,14 +93,9 @@ func (r ReleaseSpec) ExecuteTemplateExpressions(renderer *tmpl.FileRenderer) (*R
result.Labels[key] = s.String() result.Labels[key] = s.String()
} }
for i, t := range result.Values { if result.ValuesTemplate != nil && len(result.ValuesTemplate) > 0 {
for i, t := range result.ValuesTemplate {
switch ts := t.(type) { switch ts := t.(type) {
case string:
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
if err != nil {
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%s\": %v", r.Name, i, ts, err)
}
result.Values[i] = s.String()
case map[interface{}]interface{}: case map[interface{}]interface{}:
serialized, err := yaml.Marshal(ts) serialized, err := yaml.Marshal(ts)
if err != nil { if err != nil {
@ -118,7 +113,21 @@ func (r ReleaseSpec) ExecuteTemplateExpressions(renderer *tmpl.FileRenderer) (*R
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, ts, err) return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, ts, err)
} }
result.Values[i] = deserialized result.ValuesTemplate[i] = deserialized
}
}
result.Values = result.ValuesTemplate
}
for i, t := range result.Values {
switch ts := t.(type) {
case string:
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
if err != nil {
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%s\": %v", r.Name, i, ts, err)
}
result.Values[i] = s.String()
} }
} }
@ -130,7 +139,8 @@ func (r ReleaseSpec) ExecuteTemplateExpressions(renderer *tmpl.FileRenderer) (*R
result.Secrets[i] = s.String() result.Secrets[i] = s.String()
} }
for i, val := range result.SetValues { if result.SetValuesTemplate != nil && len(result.SetValuesTemplate) > 0 {
for i, val := range result.SetValuesTemplate {
{ {
// name // name
ts := val.Name ts := val.Name
@ -138,7 +148,7 @@ func (r ReleaseSpec) ExecuteTemplateExpressions(renderer *tmpl.FileRenderer) (*R
if err != nil { if err != nil {
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].name = \"%s\": %v", r.Name, i, ts, err) return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].name = \"%s\": %v", r.Name, i, ts, err)
} }
result.SetValues[i].Name = s.String() result.SetValuesTemplate[i].Name = s.String()
} }
{ {
// value // value
@ -147,7 +157,7 @@ func (r ReleaseSpec) ExecuteTemplateExpressions(renderer *tmpl.FileRenderer) (*R
if err != nil { if err != nil {
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].value = \"%s\": %v", r.Name, i, ts, err) return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].value = \"%s\": %v", r.Name, i, ts, err)
} }
result.SetValues[i].Value = s.String() result.SetValuesTemplate[i].Value = s.String()
} }
{ {
// file // file
@ -156,7 +166,7 @@ func (r ReleaseSpec) ExecuteTemplateExpressions(renderer *tmpl.FileRenderer) (*R
if err != nil { if err != nil {
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].file = \"%s\": %v", r.Name, i, ts, err) return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].file = \"%s\": %v", r.Name, i, ts, err)
} }
result.SetValues[i].File = s.String() result.SetValuesTemplate[i].File = s.String()
} }
for j, ts := range val.Values { for j, ts := range val.Values {
// values // values
@ -164,10 +174,13 @@ func (r ReleaseSpec) ExecuteTemplateExpressions(renderer *tmpl.FileRenderer) (*R
if err != nil { if err != nil {
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].values[%d] = \"%s\": %v", r.Name, i, j, ts, err) return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].values[%d] = \"%s\": %v", r.Name, i, j, ts, err)
} }
result.SetValues[i].Values[j] = s.String() result.SetValuesTemplate[i].Values[j] = s.String()
} }
} }
result.SetValues = result.SetValuesTemplate
}
return result, nil return result, nil
} }

View File

@ -153,6 +153,9 @@ type ReleaseSpec struct {
Secrets []string `yaml:"secrets,omitempty"` Secrets []string `yaml:"secrets,omitempty"`
SetValues []SetValue `yaml:"set,omitempty"` SetValues []SetValue `yaml:"set,omitempty"`
ValuesTemplate []interface{} `yaml:"valuesTemplate,omitempty"`
SetValuesTemplate []SetValue `yaml:"setTemplate,omitempty"`
// The 'env' section is not really necessary any longer, as 'set' would now provide the same functionality // The 'env' section is not really necessary any longer, as 'set' would now provide the same functionality
EnvValues []SetValue `yaml:"env,omitempty"` EnvValues []SetValue `yaml:"env,omitempty"`

View File

@ -35,7 +35,7 @@ func TestHelmState_executeTemplates(t *testing.T) {
Version: "{{ .Release.Name }}-0.1", Version: "{{ .Release.Name }}-0.1",
Name: "test-app", Name: "test-app",
Namespace: "test-namespace-{{ .Release.Name }}", Namespace: "test-namespace-{{ .Release.Name }}",
Values: []interface{}{"config/{{ .Environment.Name }}/{{ .Release.Name }}/values.yaml"}, ValuesTemplate: []interface{}{"config/{{ .Environment.Name }}/{{ .Release.Name }}/values.yaml"},
Secrets: []string{"config/{{ .Environment.Name }}/{{ .Release.Name }}/secrets.yaml"}, Secrets: []string{"config/{{ .Environment.Name }}/{{ .Release.Name }}/secrets.yaml"},
Labels: map[string]string{"id": "{{ .Release.Name }}"}, Labels: map[string]string{"id": "{{ .Release.Name }}"},
}, },
@ -94,7 +94,7 @@ func TestHelmState_executeTemplates(t *testing.T) {
Chart: "test-charts/chart", Chart: "test-charts/chart",
Name: "test-app", Name: "test-app",
Namespace: "dev", Namespace: "dev",
SetValues: []SetValue{ SetValuesTemplate: []SetValue{
SetValue{Name: "val1", Value: "{{ .Release.Name }}-val1"}, SetValue{Name: "val1", Value: "{{ .Release.Name }}-val1"},
SetValue{Name: "val2", File: "{{ .Release.Name }}.yml"}, SetValue{Name: "val2", File: "{{ .Release.Name }}.yml"},
SetValue{Name: "val3", Values: []string{"{{ .Release.Name }}-val2", "{{ .Release.Name }}-val3"}}, SetValue{Name: "val3", Values: []string{"{{ .Release.Name }}-val2", "{{ .Release.Name }}-val3"}},
@ -118,7 +118,7 @@ func TestHelmState_executeTemplates(t *testing.T) {
Verify: nil, Verify: nil,
Name: "app", Name: "app",
Namespace: "dev", Namespace: "dev",
Values: []interface{}{map[string]string{"key": "{{ .Release.Name }}-val0"}}, ValuesTemplate: []interface{}{map[string]string{"key": "{{ .Release.Name }}-val0"}},
}, },
want: ReleaseSpec{ want: ReleaseSpec{
Chart: "test-charts/chart", Chart: "test-charts/chart",