Skip to content

Commit

Permalink
Make advanced templating backward-compatible
Browse files Browse the repository at this point in the history
This is a follow-up for #823
Ref #823 (comment)
  • Loading branch information
mumoshu committed Aug 31, 2019
1 parent 01ae59f commit 7e57fbc
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 66 deletions.
8 changes: 4 additions & 4 deletions docs/writing-helmfile.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,24 +102,24 @@ Release Templating supports the following parts of release definition:
- `set` block values:
```yaml
# ...
set:
setTemplate:
- name: '{{`{{ .Release.Name }}`}}'
values: '{{`{{ .Release.Namespace }}`}}'
# ...
```
- `values` and `secrets` file paths:
```yaml
# ...
values:
valuesTemplate:
- config/{{`{{ .Release.Name }}`}}/values.yaml
secrets:
secretsTemplate:
- config/{{`{{ .Release.Name }}`}}/secrets.yaml
# ...
```
- inline `values` map:
```yaml
# ...
values:
valuesTemplate:
- image:
tag: `{{ .Release.Labels.tag }}`
# ...
Expand Down
111 changes: 62 additions & 49 deletions pkg/state/release.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,33 @@ func (r ReleaseSpec) ExecuteTemplateExpressions(renderer *tmpl.FileRenderer) (*R
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 {
switch ts := t.(type) {
case string:
Expand All @@ -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)
}
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
}
}

Expand All @@ -130,42 +139,46 @@ func (r ReleaseSpec) ExecuteTemplateExpressions(renderer *tmpl.FileRenderer) (*R
result.Secrets[i] = s.String()
}

for i, val := range result.SetValues {
{
// name
ts := val.Name
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
if err != nil {
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].name = \"%s\": %v", r.Name, i, ts, err)
if result.SetValuesTemplate != nil && len(result.SetValuesTemplate) > 0 {
for i, val := range result.SetValuesTemplate {
{
// name
ts := val.Name
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
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
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
if err != nil {
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].value = \"%s\": %v", r.Name, i, ts, err)
{
// value
ts := val.Value
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
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
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
if err != nil {
return nil, fmt.Errorf("failed executing template expressions in release \"%s\".set[%d].file = \"%s\": %v", r.Name, i, ts, err)
{
// file
ts := val.File
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
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
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
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)
for j, ts := range val.Values {
// values
s, err := renderer.RenderTemplateContentToBuffer([]byte(ts))
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
Expand Down
3 changes: 3 additions & 0 deletions pkg/state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,9 @@ type ReleaseSpec struct {
Secrets []string `yaml:"secrets,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
EnvValues []SetValue `yaml:"env,omitempty"`

Expand Down
26 changes: 13 additions & 13 deletions pkg/state/state_exec_tmpl_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ func TestHelmState_executeTemplates(t *testing.T) {
{
name: "Has template expressions in chart, values, secrets, version, labels",
input: ReleaseSpec{
Chart: "test-charts/{{ .Release.Name }}",
Version: "{{ .Release.Name }}-0.1",
Name: "test-app",
Namespace: "test-namespace-{{ .Release.Name }}",
Values: []interface{}{"config/{{ .Environment.Name }}/{{ .Release.Name }}/values.yaml"},
Secrets: []string{"config/{{ .Environment.Name }}/{{ .Release.Name }}/secrets.yaml"},
Labels: map[string]string{"id": "{{ .Release.Name }}"},
Chart: "test-charts/{{ .Release.Name }}",
Version: "{{ .Release.Name }}-0.1",
Name: "test-app",
Namespace: "test-namespace-{{ .Release.Name }}",
ValuesTemplate: []interface{}{"config/{{ .Environment.Name }}/{{ .Release.Name }}/values.yaml"},
Secrets: []string{"config/{{ .Environment.Name }}/{{ .Release.Name }}/secrets.yaml"},
Labels: map[string]string{"id": "{{ .Release.Name }}"},
},
want: ReleaseSpec{
Chart: "test-charts/test-app",
Expand Down Expand Up @@ -94,7 +94,7 @@ func TestHelmState_executeTemplates(t *testing.T) {
Chart: "test-charts/chart",
Name: "test-app",
Namespace: "dev",
SetValues: []SetValue{
SetValuesTemplate: []SetValue{
SetValue{Name: "val1", Value: "{{ .Release.Name }}-val1"},
SetValue{Name: "val2", File: "{{ .Release.Name }}.yml"},
SetValue{Name: "val3", Values: []string{"{{ .Release.Name }}-val2", "{{ .Release.Name }}-val3"}},
Expand All @@ -114,11 +114,11 @@ func TestHelmState_executeTemplates(t *testing.T) {
{
name: "Has template in values (map)",
input: ReleaseSpec{
Chart: "test-charts/chart",
Verify: nil,
Name: "app",
Namespace: "dev",
Values: []interface{}{map[string]string{"key": "{{ .Release.Name }}-val0"}},
Chart: "test-charts/chart",
Verify: nil,
Name: "app",
Namespace: "dev",
ValuesTemplate: []interface{}{map[string]string{"key": "{{ .Release.Name }}-val0"}},
},
want: ReleaseSpec{
Chart: "test-charts/chart",
Expand Down

0 comments on commit 7e57fbc

Please sign in to comment.