Skip to content

Commit

Permalink
feat: Template values files
Browse files Browse the repository at this point in the history
Resolves #97
  • Loading branch information
mumoshu committed Aug 22, 2018
1 parent 3550e5f commit f441f38
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 32 deletions.
5 changes: 3 additions & 2 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,9 @@ func loadDesiredStateFromFile(c *cli.Context, file string) (*state.HelmState, he
namespace := c.GlobalString("namespace")
labels := c.GlobalStringSlice("selector")

st, err := state.ReadFromFile(file)
logger := c.App.Metadata["logger"].(*zap.SugaredLogger)

st, err := state.CreateFromFile(file, logger)
if err != nil {
return nil, nil, false, fmt.Errorf("failed to read %s: %v", file, err)
}
Expand Down Expand Up @@ -514,7 +516,6 @@ func loadDesiredStateFromFile(c *cli.Context, file string) (*state.HelmState, he
clean(st, errs)
}()

logger := c.App.Metadata["logger"].(*zap.SugaredLogger)
return st, helmexec.New(logger, kubeContext), false, nil
}

Expand Down
73 changes: 49 additions & 24 deletions state/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"bytes"
"regexp"

"go.uber.org/zap"
yaml "gopkg.in/yaml.v2"
)

Expand All @@ -32,6 +33,8 @@ type HelmState struct {
Namespace string `yaml:"namespace"`
Repositories []RepositorySpec `yaml:"repositories"`
Releases []ReleaseSpec `yaml:"releases"`

logger *zap.SugaredLogger
}

// HelmSpec to defines helmDefault values
Expand Down Expand Up @@ -79,28 +82,17 @@ type SetValue struct {
Value string `yaml:"value"`
}

// ReadFromFile loads the helmfile from disk and processes the template
func ReadFromFile(file string) (*HelmState, error) {
content, err := ioutil.ReadFile(file)
if err != nil {
return nil, err
}

tpl, err := stringTemplate().Parse(string(content))
if err != nil {
return nil, err
}

var tplString bytes.Buffer
err = tpl.Execute(&tplString, nil)
// CreateFromFile loads the helmfile from disk and processes the template
func CreateFromFile(file string, logger *zap.SugaredLogger) (*HelmState, error) {
yamlBuf, err := renderTemplateFileToBuffer(file)
if err != nil {
return nil, err
}

return readFromYaml(tplString.Bytes(), file)
return readFromYaml(yamlBuf.Bytes(), file, logger)
}

func readFromYaml(content []byte, file string) (*HelmState, error) {
func readFromYaml(content []byte, file string, logger *zap.SugaredLogger) (*HelmState, error) {
var state HelmState

state.BaseChartPath, _ = filepath.Abs(filepath.Dir(file))
Expand All @@ -117,6 +109,8 @@ func readFromYaml(content []byte, file string) (*HelmState, error) {
state.DeprecatedReleases = []ReleaseSpec{}
}

state.logger = logger

return &state, nil
}

Expand All @@ -138,19 +132,36 @@ func getRequiredEnv(name string) (string, error) {
return "", fmt.Errorf("required env var `%s` is not set", name)
}

func renderTemplateString(s string) (string, error) {
func renderTemplateFileToBuffer(file string) (*bytes.Buffer, error) {
content, err := ioutil.ReadFile(file)
if err != nil {
return nil, err
}

return renderTemplateToBuffer(string(content))
}

func renderTemplateToBuffer(s string) (*bytes.Buffer, error) {
var t, parseErr = stringTemplate().Parse(s)
if parseErr != nil {
return "", parseErr
return nil, parseErr
}

var tplString bytes.Buffer
var execErr = t.Execute(&tplString, nil)

if execErr != nil {
return "", execErr
return nil, execErr
}

return &tplString, nil
}

func renderTemplateString(s string) (string, error) {
tplString, err := renderTemplateToBuffer(s)
if err != nil {
return "", err
}
return tplString.String(), nil
}

Expand Down Expand Up @@ -194,7 +205,7 @@ func (state *HelmState) SyncReleases(helm helmexec.Interface, additionalValues [
go func() {
for release := range jobQueue {
state.applyDefaultsTo(release)
flags, flagsErr := flagsForRelease(helm, state.BaseChartPath, release)
flags, flagsErr := state.flagsForRelease(helm, state.BaseChartPath, release)
if flagsErr != nil {
errQueue <- flagsErr
doneQueue <- true
Expand Down Expand Up @@ -273,7 +284,7 @@ func (state *HelmState) DiffReleases(helm helmexec.Interface, additionalValues [
errs := []error{}
// Plugin command doesn't support explicit namespace
release.Namespace = ""
flags, err := flagsForRelease(helm, state.BaseChartPath, release)
flags, err := state.flagsForRelease(helm, state.BaseChartPath, release)
if err != nil {
errs = append(errs, err)
}
Expand Down Expand Up @@ -356,7 +367,7 @@ func (state *HelmState) LintReleases(helm helmexec.Interface, additionalValues [
go func() {
for release := range jobQueue {
errs := []error{}
flags, err := flagsForRelease(helm, state.BaseChartPath, release)
flags, err := state.flagsForRelease(helm, state.BaseChartPath, release)
if err != nil {
errs = append(errs, err)
}
Expand Down Expand Up @@ -639,7 +650,7 @@ func chartNameWithoutRepository(chart string) string {
return chartSplit[len(chartSplit)-1]
}

func flagsForRelease(helm helmexec.Interface, basePath string, release *ReleaseSpec) ([]string, error) {
func (state *HelmState) flagsForRelease(helm helmexec.Interface, basePath string, release *ReleaseSpec) ([]string, error) {
flags := []string{}
if release.Version != "" {
flags = append(flags, "--version", release.Version)
Expand All @@ -662,7 +673,21 @@ func flagsForRelease(helm helmexec.Interface, basePath string, release *ReleaseS
if _, err := os.Stat(path); os.IsNotExist(err) {
return nil, err
}
flags = append(flags, "--values", path)
yamlBuf, err := renderTemplateFileToBuffer(path)
if err != nil {
return nil, err
}
valfile, err := ioutil.TempFile("", "values")
if err != nil {
return nil, err
}
defer valfile.Close()
yamlBytes := yamlBuf.Bytes()
if _, err := valfile.Write(yamlBytes); err != nil {
return nil, fmt.Errorf("failed to write %s: %v", valfile.Name(), err)
}
state.logger.Debugf("successfully generated the value file at %s. produced:\n%s", path, string(yamlBytes))
flags = append(flags, "--values", valfile.Name())

case map[interface{}]interface{}:
valfile, err := ioutil.TempFile("", "values")
Expand Down
15 changes: 9 additions & 6 deletions state/state_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,20 @@ import (
"testing"

"errors"
"github.com/roboll/helmfile/helmexec"
"strings"
)

var logger = helmexec.NewLogger(os.Stdout, "warn")

func TestReadFromYaml(t *testing.T) {
yamlFile := "example/path/to/yaml/file"
yamlContent := []byte(`releases:
- name: myrelease
namespace: mynamespace
chart: mychart
`)
state, err := readFromYaml(yamlContent, yamlFile)
state, err := readFromYaml(yamlContent, yamlFile, logger)
if err != nil {
t.Errorf("unxpected error: %v", err)
}
Expand All @@ -39,7 +42,7 @@ func TestReadFromYaml_StrictUnmarshalling(t *testing.T) {
namespace: mynamespace
releases: mychart
`)
_, err := readFromYaml(yamlContent, yamlFile)
_, err := readFromYaml(yamlContent, yamlFile, logger)
if err == nil {
t.Error("expected an error for wrong key 'releases' which is not in struct")
}
Expand All @@ -51,7 +54,7 @@ func TestReadFromYaml_DeprecatedReleaseReferences(t *testing.T) {
- name: myrelease
chart: mychart
`)
state, err := readFromYaml(yamlContent, yamlFile)
state, err := readFromYaml(yamlContent, yamlFile, logger)
if err != nil {
t.Errorf("unxpected error: %v", err)
}
Expand All @@ -73,7 +76,7 @@ releases:
- name: myrelease2
chart: mychart2
`)
_, err := readFromYaml(yamlContent, yamlFile)
_, err := readFromYaml(yamlContent, yamlFile, logger)
if err == nil {
t.Error("expected error")
}
Expand Down Expand Up @@ -109,7 +112,7 @@ func TestReadFromYaml_FilterReleasesOnLabels(t *testing.T) {
{LabelFilter{positiveLabels: [][]string{[]string{"tier", "frontend"}}, negativeLabels: [][]string{[]string{"foo", "bar"}}},
[]bool{false, true, false}},
}
state, err := readFromYaml(yamlContent, yamlFile)
state, err := readFromYaml(yamlContent, yamlFile, logger)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
Expand Down Expand Up @@ -148,7 +151,7 @@ func TestReadFromYaml_FilterNegatives(t *testing.T) {
{LabelFilter{negativeLabels: [][]string{[]string{"stage", "pre"}, []string{"stage", "post"}}},
[]bool{false, false, true}},
}
state, err := readFromYaml(yamlContent, yamlFile)
state, err := readFromYaml(yamlContent, yamlFile, logger)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
Expand Down

0 comments on commit f441f38

Please sign in to comment.