parent
							
								
									6c89fac8e5
								
							
						
					
					
						commit
						d609dab848
					
				
							
								
								
									
										5
									
								
								main.go
								
								
								
								
							
							
						
						
									
										5
									
								
								main.go
								
								
								
								
							|  | @ -476,7 +476,9 @@ func loadDesiredStateFromFile(c *cli.Context, file string) (*state.HelmState, he | ||||||
| 	namespace := c.GlobalString("namespace") | 	namespace := c.GlobalString("namespace") | ||||||
| 	labels := c.GlobalStringSlice("selector") | 	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 { | 	if err != nil { | ||||||
| 		return nil, nil, false, fmt.Errorf("failed to read %s: %v", file, err) | 		return nil, nil, false, fmt.Errorf("failed to read %s: %v", file, err) | ||||||
| 	} | 	} | ||||||
|  | @ -514,7 +516,6 @@ func loadDesiredStateFromFile(c *cli.Context, file string) (*state.HelmState, he | ||||||
| 		clean(st, errs) | 		clean(st, errs) | ||||||
| 	}() | 	}() | ||||||
| 
 | 
 | ||||||
| 	logger := c.App.Metadata["logger"].(*zap.SugaredLogger) |  | ||||||
| 	return st, helmexec.New(logger, kubeContext), false, nil | 	return st, helmexec.New(logger, kubeContext), false, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -19,6 +19,7 @@ import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"regexp" | 	"regexp" | ||||||
| 
 | 
 | ||||||
|  | 	"go.uber.org/zap" | ||||||
| 	yaml "gopkg.in/yaml.v2" | 	yaml "gopkg.in/yaml.v2" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | @ -32,6 +33,8 @@ type HelmState struct { | ||||||
| 	Namespace          string           `yaml:"namespace"` | 	Namespace          string           `yaml:"namespace"` | ||||||
| 	Repositories       []RepositorySpec `yaml:"repositories"` | 	Repositories       []RepositorySpec `yaml:"repositories"` | ||||||
| 	Releases           []ReleaseSpec    `yaml:"releases"` | 	Releases           []ReleaseSpec    `yaml:"releases"` | ||||||
|  | 
 | ||||||
|  | 	logger *zap.SugaredLogger | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // HelmSpec to defines helmDefault values
 | // HelmSpec to defines helmDefault values
 | ||||||
|  | @ -79,28 +82,17 @@ type SetValue struct { | ||||||
| 	Value string `yaml:"value"` | 	Value string `yaml:"value"` | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| // ReadFromFile loads the helmfile from disk and processes the template
 | // CreateFromFile loads the helmfile from disk and processes the template
 | ||||||
| func ReadFromFile(file string) (*HelmState, error) { | func CreateFromFile(file string, logger *zap.SugaredLogger) (*HelmState, error) { | ||||||
| 	content, err := ioutil.ReadFile(file) | 	yamlBuf, err := renderTemplateFileToBuffer(file) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	tpl, err := stringTemplate().Parse(string(content)) | 	return readFromYaml(yamlBuf.Bytes(), file, logger) | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 	var tplString bytes.Buffer | func readFromYaml(content []byte, file string, logger *zap.SugaredLogger) (*HelmState, error) { | ||||||
| 	err = tpl.Execute(&tplString, nil) |  | ||||||
| 	if err != nil { |  | ||||||
| 		return nil, err |  | ||||||
| 	} |  | ||||||
| 
 |  | ||||||
| 	return readFromYaml(tplString.Bytes(), file) |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| func readFromYaml(content []byte, file string) (*HelmState, error) { |  | ||||||
| 	var state HelmState | 	var state HelmState | ||||||
| 
 | 
 | ||||||
| 	state.BaseChartPath, _ = filepath.Abs(filepath.Dir(file)) | 	state.BaseChartPath, _ = filepath.Abs(filepath.Dir(file)) | ||||||
|  | @ -117,6 +109,8 @@ func readFromYaml(content []byte, file string) (*HelmState, error) { | ||||||
| 		state.DeprecatedReleases = []ReleaseSpec{} | 		state.DeprecatedReleases = []ReleaseSpec{} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | 	state.logger = logger | ||||||
|  | 
 | ||||||
| 	return &state, nil | 	return &state, nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -138,19 +132,36 @@ func getRequiredEnv(name string) (string, error) { | ||||||
| 	return "", fmt.Errorf("required env var `%s` is not set", name) | 	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) | 	var t, parseErr = stringTemplate().Parse(s) | ||||||
| 	if parseErr != nil { | 	if parseErr != nil { | ||||||
| 		return "", parseErr | 		return nil, parseErr | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	var tplString bytes.Buffer | 	var tplString bytes.Buffer | ||||||
| 	var execErr = t.Execute(&tplString, nil) | 	var execErr = t.Execute(&tplString, nil) | ||||||
| 
 | 
 | ||||||
| 	if execErr != 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 | 	return tplString.String(), nil | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -194,7 +205,7 @@ func (state *HelmState) SyncReleases(helm helmexec.Interface, additionalValues [ | ||||||
| 		go func() { | 		go func() { | ||||||
| 			for release := range jobQueue { | 			for release := range jobQueue { | ||||||
| 				state.applyDefaultsTo(release) | 				state.applyDefaultsTo(release) | ||||||
| 				flags, flagsErr := flagsForRelease(helm, state.BaseChartPath, release) | 				flags, flagsErr := state.flagsForRelease(helm, state.BaseChartPath, release) | ||||||
| 				if flagsErr != nil { | 				if flagsErr != nil { | ||||||
| 					errQueue <- flagsErr | 					errQueue <- flagsErr | ||||||
| 					doneQueue <- true | 					doneQueue <- true | ||||||
|  | @ -274,7 +285,7 @@ func (state *HelmState) DiffReleases(helm helmexec.Interface, additionalValues [ | ||||||
| 
 | 
 | ||||||
| 				state.applyDefaultsTo(release) | 				state.applyDefaultsTo(release) | ||||||
| 
 | 
 | ||||||
| 				flags, err := flagsForRelease(helm, state.BaseChartPath, release) | 				flags, err := state.flagsForRelease(helm, state.BaseChartPath, release) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					errs = append(errs, err) | 					errs = append(errs, err) | ||||||
| 				} | 				} | ||||||
|  | @ -358,7 +369,7 @@ func (state *HelmState) LintReleases(helm helmexec.Interface, additionalValues [ | ||||||
| 		go func() { | 		go func() { | ||||||
| 			for release := range jobQueue { | 			for release := range jobQueue { | ||||||
| 				errs := []error{} | 				errs := []error{} | ||||||
| 				flags, err := flagsForRelease(helm, state.BaseChartPath, release) | 				flags, err := state.flagsForRelease(helm, state.BaseChartPath, release) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
| 					errs = append(errs, err) | 					errs = append(errs, err) | ||||||
| 				} | 				} | ||||||
|  | @ -641,7 +652,7 @@ func chartNameWithoutRepository(chart string) string { | ||||||
| 	return chartSplit[len(chartSplit)-1] | 	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{} | 	flags := []string{} | ||||||
| 	if release.Version != "" { | 	if release.Version != "" { | ||||||
| 		flags = append(flags, "--version", release.Version) | 		flags = append(flags, "--version", release.Version) | ||||||
|  | @ -664,7 +675,21 @@ func flagsForRelease(helm helmexec.Interface, basePath string, release *ReleaseS | ||||||
| 			if _, err := os.Stat(path); os.IsNotExist(err) { | 			if _, err := os.Stat(path); os.IsNotExist(err) { | ||||||
| 				return nil, 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{}: | 		case map[interface{}]interface{}: | ||||||
| 			valfile, err := ioutil.TempFile("", "values") | 			valfile, err := ioutil.TempFile("", "values") | ||||||
|  |  | ||||||
|  | @ -6,9 +6,12 @@ import ( | ||||||
| 	"testing" | 	"testing" | ||||||
| 
 | 
 | ||||||
| 	"errors" | 	"errors" | ||||||
|  | 	"github.com/roboll/helmfile/helmexec" | ||||||
| 	"strings" | 	"strings" | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
|  | var logger = helmexec.NewLogger(os.Stdout, "warn") | ||||||
|  | 
 | ||||||
| func TestReadFromYaml(t *testing.T) { | func TestReadFromYaml(t *testing.T) { | ||||||
| 	yamlFile := "example/path/to/yaml/file" | 	yamlFile := "example/path/to/yaml/file" | ||||||
| 	yamlContent := []byte(`releases: | 	yamlContent := []byte(`releases: | ||||||
|  | @ -16,7 +19,7 @@ func TestReadFromYaml(t *testing.T) { | ||||||
|   namespace: mynamespace |   namespace: mynamespace | ||||||
|   chart: mychart |   chart: mychart | ||||||
| `) | `) | ||||||
| 	state, err := readFromYaml(yamlContent, yamlFile) | 	state, err := readFromYaml(yamlContent, yamlFile, logger) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Errorf("unxpected error: %v", err) | 		t.Errorf("unxpected error: %v", err) | ||||||
| 	} | 	} | ||||||
|  | @ -39,7 +42,7 @@ func TestReadFromYaml_StrictUnmarshalling(t *testing.T) { | ||||||
|   namespace: mynamespace |   namespace: mynamespace | ||||||
|   releases: mychart |   releases: mychart | ||||||
| `) | `) | ||||||
| 	_, err := readFromYaml(yamlContent, yamlFile) | 	_, err := readFromYaml(yamlContent, yamlFile, logger) | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| 		t.Error("expected an error for wrong key 'releases' which is not in struct") | 		t.Error("expected an error for wrong key 'releases' which is not in struct") | ||||||
| 	} | 	} | ||||||
|  | @ -51,7 +54,7 @@ func TestReadFromYaml_DeprecatedReleaseReferences(t *testing.T) { | ||||||
| - name: myrelease | - name: myrelease | ||||||
|   chart: mychart |   chart: mychart | ||||||
| `) | `) | ||||||
| 	state, err := readFromYaml(yamlContent, yamlFile) | 	state, err := readFromYaml(yamlContent, yamlFile, logger) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Errorf("unxpected error: %v", err) | 		t.Errorf("unxpected error: %v", err) | ||||||
| 	} | 	} | ||||||
|  | @ -73,7 +76,7 @@ releases: | ||||||
| - name: myrelease2 | - name: myrelease2 | ||||||
|   chart: mychart2 |   chart: mychart2 | ||||||
| `) | `) | ||||||
| 	_, err := readFromYaml(yamlContent, yamlFile) | 	_, err := readFromYaml(yamlContent, yamlFile, logger) | ||||||
| 	if err == nil { | 	if err == nil { | ||||||
| 		t.Error("expected error") | 		t.Error("expected error") | ||||||
| 	} | 	} | ||||||
|  | @ -109,7 +112,7 @@ func TestReadFromYaml_FilterReleasesOnLabels(t *testing.T) { | ||||||
| 		{LabelFilter{positiveLabels: [][]string{[]string{"tier", "frontend"}}, negativeLabels: [][]string{[]string{"foo", "bar"}}}, | 		{LabelFilter{positiveLabels: [][]string{[]string{"tier", "frontend"}}, negativeLabels: [][]string{[]string{"foo", "bar"}}}, | ||||||
| 			[]bool{false, true, false}}, | 			[]bool{false, true, false}}, | ||||||
| 	} | 	} | ||||||
| 	state, err := readFromYaml(yamlContent, yamlFile) | 	state, err := readFromYaml(yamlContent, yamlFile, logger) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Errorf("unexpected error: %v", err) | 		t.Errorf("unexpected error: %v", err) | ||||||
| 	} | 	} | ||||||
|  | @ -148,7 +151,7 @@ func TestReadFromYaml_FilterNegatives(t *testing.T) { | ||||||
| 		{LabelFilter{negativeLabels: [][]string{[]string{"stage", "pre"}, []string{"stage", "post"}}}, | 		{LabelFilter{negativeLabels: [][]string{[]string{"stage", "pre"}, []string{"stage", "post"}}}, | ||||||
| 			[]bool{false, false, true}}, | 			[]bool{false, false, true}}, | ||||||
| 	} | 	} | ||||||
| 	state, err := readFromYaml(yamlContent, yamlFile) | 	state, err := readFromYaml(yamlContent, yamlFile, logger) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		t.Errorf("unexpected error: %v", err) | 		t.Errorf("unexpected error: %v", err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue