fix: "cannot unmarshal !!str `<no value>` into bool" errors in state templates (#645)
Seems like we are affected by https://github.com/golang/go/issues/24963. That is, even though we internally use the template option `missingkey=zero`, in some cases it still prints `<no value>` instead of zero values, which has been confusing the state yaml parsing. This fixes the issue by naively replacing all the remaining occurrences of `<no value>` in the rendered text, while printing debug logs to ease debugging in the future when there is unexpected side-effects introduced by this native method. Fixes #553
This commit is contained in:
		
							parent
							
								
									1d3f5f8a33
								
							
						
					
					
						commit
						65ee6a2124
					
				
							
								
								
									
										2
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										2
									
								
								go.mod
								
								
								
								
							|  | @ -6,7 +6,7 @@ require ( | ||||||
| 	github.com/Masterminds/semver v1.4.1 | 	github.com/Masterminds/semver v1.4.1 | ||||||
| 	github.com/Masterminds/sprig v2.16.0+incompatible | 	github.com/Masterminds/sprig v2.16.0+incompatible | ||||||
| 	github.com/aokoli/goutils v1.0.1 // indirect | 	github.com/aokoli/goutils v1.0.1 // indirect | ||||||
| 	github.com/google/go-cmp v0.3.0 // indirect | 	github.com/google/go-cmp v0.3.0 | ||||||
| 	github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c // indirect | 	github.com/google/uuid v0.0.0-20161128191214-064e2069ce9c // indirect | ||||||
| 	github.com/huandu/xstrings v1.0.0 // indirect | 	github.com/huandu/xstrings v1.0.0 // indirect | ||||||
| 	github.com/imdario/mergo v0.3.6 | 	github.com/imdario/mergo v0.3.6 | ||||||
|  |  | ||||||
|  | @ -838,7 +838,7 @@ releases: | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| func TestVisitDesiredStatesWithReleasesFiltered_StateValueOverrides(t *testing.T) { | func TestVisitDesiredStatesWithReleasesFiltered_EnvironmentValueOverrides(t *testing.T) { | ||||||
| 	files := map[string]string{ | 	files := map[string]string{ | ||||||
| 		"/path/to/helmfile.yaml": ` | 		"/path/to/helmfile.yaml": ` | ||||||
| environments: | environments: | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ package app | ||||||
| import ( | import ( | ||||||
| 	"bytes" | 	"bytes" | ||||||
| 	"fmt" | 	"fmt" | ||||||
|  | 	"github.com/google/go-cmp/cmp" | ||||||
| 	"github.com/roboll/helmfile/pkg/environment" | 	"github.com/roboll/helmfile/pkg/environment" | ||||||
| 	"github.com/roboll/helmfile/pkg/state" | 	"github.com/roboll/helmfile/pkg/state" | ||||||
| 	"github.com/roboll/helmfile/pkg/tmpl" | 	"github.com/roboll/helmfile/pkg/tmpl" | ||||||
|  | @ -31,10 +32,20 @@ func (r *desiredStateLoader) renderEnvironment(firstPassEnv *environment.Environ | ||||||
| 			return firstPassEnv | 			return firstPassEnv | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  | 	yamlData := yamlBuf.String() | ||||||
|  | 
 | ||||||
|  | 	// Work-around for https://github.com/golang/go/issues/24963
 | ||||||
|  | 	sanitized := strings.ReplaceAll(yamlData, "<no value>", "") | ||||||
|  | 
 | ||||||
|  | 	if len(yamlData) != len(sanitized) { | ||||||
|  | 		msg := "replaced <no value>s to workaround https://github.com/golang/go/issues/24963 to address https://github.com/roboll/helmfile/issues/553:\n%s" | ||||||
|  | 		r.logger.Debugf(msg, cmp.Diff(yamlData, sanitized)) | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	c := r.underlying() | 	c := r.underlying() | ||||||
| 	c.Strict = false | 	c.Strict = false | ||||||
| 	// create preliminary state, as we may have an environment. Tolerate errors.
 | 	// create preliminary state, as we may have an environment. Tolerate errors.
 | ||||||
| 	prestate, err := c.ParseAndLoad(yamlBuf.Bytes(), baseDir, filename, r.env, false, firstPassEnv) | 	prestate, err := c.ParseAndLoad([]byte(sanitized), baseDir, filename, r.env, false, firstPassEnv) | ||||||
| 	if err != nil && r.logger != nil { | 	if err != nil && r.logger != nil { | ||||||
| 		switch err.(type) { | 		switch err.(type) { | ||||||
| 		case *state.StateLoadError: | 		case *state.StateLoadError: | ||||||
|  |  | ||||||
|  | @ -13,9 +13,9 @@ func (c *Context) stringTemplate() *template.Template { | ||||||
| 	} | 	} | ||||||
| 	tmpl := template.New("stringTemplate").Funcs(funcMap) | 	tmpl := template.New("stringTemplate").Funcs(funcMap) | ||||||
| 	if c.preRender { | 	if c.preRender { | ||||||
| 		tmpl.Option("missingkey=zero") | 		tmpl = tmpl.Option("missingkey=zero") | ||||||
| 	} else { | 	} else { | ||||||
| 		tmpl.Option("missingkey=error") | 		tmpl = tmpl.Option("missingkey=error") | ||||||
| 	} | 	} | ||||||
| 	return tmpl | 	return tmpl | ||||||
| } | } | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue