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:
parent
01ae59fedd
commit
4bc99337b2
|
|
@ -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 }}`
|
||||||
# ...
|
# ...
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,33 @@ func (r ReleaseSpec) ExecuteTemplateExpressions(renderer *tmpl.FileRenderer) (*R
|
||||||
result.Labels[key] = s.String()
|
result.Labels[key] = s.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if result.ValuesTemplate != nil && len(result.ValuesTemplate) > 0 {
|
||||||
|
for i, t := range result.ValuesTemplate {
|
||||||
|
switch ts := t.(type) {
|
||||||
|
case map[interface{}]interface{}:
|
||||||
|
serialized, err := yaml.Marshal(ts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, ts, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := renderer.RenderTemplateContentToBuffer([]byte(serialized))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, serialized, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var deserialized map[interface{}]interface{}
|
||||||
|
|
||||||
|
if err := yaml.Unmarshal(s.Bytes(), &deserialized); err != nil {
|
||||||
|
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, ts, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
result.ValuesTemplate[i] = deserialized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
result.Values = result.ValuesTemplate
|
||||||
|
}
|
||||||
|
|
||||||
for i, t := range result.Values {
|
for i, t := range result.Values {
|
||||||
switch ts := t.(type) {
|
switch ts := t.(type) {
|
||||||
case string:
|
case string:
|
||||||
|
|
@ -101,24 +128,6 @@ func (r ReleaseSpec) ExecuteTemplateExpressions(renderer *tmpl.FileRenderer) (*R
|
||||||
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%s\": %v", r.Name, i, ts, err)
|
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()
|
result.Values[i] = s.String()
|
||||||
case map[interface{}]interface{}:
|
|
||||||
serialized, err := yaml.Marshal(ts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, ts, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
s, err := renderer.RenderTemplateContentToBuffer([]byte(serialized))
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, serialized, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var deserialized map[interface{}]interface{}
|
|
||||||
|
|
||||||
if err := yaml.Unmarshal(s.Bytes(), &deserialized); err != nil {
|
|
||||||
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".values[%d] = \"%v\": %v", r.Name, i, ts, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
result.Values[i] = deserialized
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -130,42 +139,46 @@ 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
|
{
|
||||||
ts := val.Name
|
// name
|
||||||
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
|
ts := val.Name
|
||||||
if err != nil {
|
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
|
||||||
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].name = \"%s\": %v", r.Name, i, ts, err)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].name = \"%s\": %v", r.Name, i, ts, err)
|
||||||
|
}
|
||||||
|
result.SetValuesTemplate[i].Name = s.String()
|
||||||
}
|
}
|
||||||
result.SetValues[i].Name = s.String()
|
{
|
||||||
}
|
// value
|
||||||
{
|
ts := val.Value
|
||||||
// value
|
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
|
||||||
ts := val.Value
|
if err != nil {
|
||||||
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
|
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].value = \"%s\": %v", r.Name, i, ts, err)
|
||||||
if err != nil {
|
}
|
||||||
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].value = \"%s\": %v", r.Name, i, ts, err)
|
result.SetValuesTemplate[i].Value = s.String()
|
||||||
}
|
}
|
||||||
result.SetValues[i].Value = s.String()
|
{
|
||||||
}
|
// file
|
||||||
{
|
ts := val.File
|
||||||
// file
|
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
|
||||||
ts := val.File
|
if err != nil {
|
||||||
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
|
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].file = \"%s\": %v", r.Name, i, ts, err)
|
||||||
if err != nil {
|
}
|
||||||
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].file = \"%s\": %v", r.Name, i, ts, err)
|
result.SetValuesTemplate[i].File = s.String()
|
||||||
}
|
}
|
||||||
result.SetValues[i].File = s.String()
|
for j, ts := range val.Values {
|
||||||
}
|
// values
|
||||||
for j, ts := range val.Values {
|
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
|
||||||
// values
|
if err != nil {
|
||||||
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
|
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].values[%d] = \"%s\": %v", r.Name, i, j, ts, err)
|
||||||
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)
|
result.SetValuesTemplate[i].Values[j] = s.String()
|
||||||
}
|
}
|
||||||
result.SetValues[i].Values[j] = s.String()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result.SetValues = result.SetValuesTemplate
|
||||||
}
|
}
|
||||||
|
|
||||||
return result, nil
|
return result, nil
|
||||||
|
|
|
||||||
|
|
@ -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"`
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,13 @@ func TestHelmState_executeTemplates(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "Has template expressions in chart, values, secrets, version, labels",
|
name: "Has template expressions in chart, values, secrets, version, labels",
|
||||||
input: ReleaseSpec{
|
input: ReleaseSpec{
|
||||||
Chart: "test-charts/{{ .Release.Name }}",
|
Chart: "test-charts/{{ .Release.Name }}",
|
||||||
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 }}"},
|
||||||
},
|
},
|
||||||
want: ReleaseSpec{
|
want: ReleaseSpec{
|
||||||
Chart: "test-charts/test-app",
|
Chart: "test-charts/test-app",
|
||||||
|
|
@ -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"}},
|
||||||
|
|
@ -114,11 +114,11 @@ func TestHelmState_executeTemplates(t *testing.T) {
|
||||||
{
|
{
|
||||||
name: "Has template in values (map)",
|
name: "Has template in values (map)",
|
||||||
input: ReleaseSpec{
|
input: ReleaseSpec{
|
||||||
Chart: "test-charts/chart",
|
Chart: "test-charts/chart",
|
||||||
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",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue