Use --namespace value within Helmfile template (#343)

* Use --namespace value within Helmfile template (#326).

* Tabs and spaces.

* Tab/spaces fix.

* Pacifying "go fmt".

* Hard-coding namespace in test convenience function.

* MR feedback: Add comment to exported identifier.

* MR feedback: Put comment in correct location.

* fix(ci): fix never-ending build issue by auto-approving `helmfile delete`
This commit is contained in:
Dan Helfman 2018-09-17 05:28:45 -07:00 committed by KUOKA Yusuke
parent 6453768f2e
commit 1ade353c1a
6 changed files with 62 additions and 27 deletions

View File

@ -83,6 +83,9 @@ releases:
values:
- 1
- 2
# set a templated value
- name: namespace
value: {{ .Namespace }}
# will attempt to decrypt it using helm-secrets plugin
secrets:
- vault_secret.yaml
@ -200,7 +203,7 @@ GLOBAL OPTIONS:
--quiet, -q Silence output. Equivalent to log-level warn
--kube-context value Set kubectl context. Uses current context by default
--log-level value Set log level, default info
--namespace value, -n value Set namespace. Uses the namespace set in the context by default
--namespace value, -n value Set namespace. Uses the namespace set in the context by default, and is available in templates as {{ .Namespace }}
--selector value, -l value Only run using the releases that match labels. Labels can take the form of foo=bar or foo!=bar.
A release must match all labels in a group in order to be used. Multiple groups can be specified at once.
--selector tier=frontend,tier!=proxy --selector tier=backend. Will match all frontend, non-proxy releases AND all backend releases.

View File

@ -91,7 +91,7 @@ func main() {
},
cli.StringFlag{
Name: "namespace, n",
Usage: "Set namespace. Uses the namespace set in the context by default",
Usage: "Set namespace. Uses the namespace set in the context by default, and is available in templates as {{ .Namespace }}",
},
cli.StringSliceFlag{
Name: "selector, l",
@ -638,6 +638,7 @@ func prependLineNumbers(text string) string {
type twoPassRenderer struct {
reader func(string) ([]byte, error)
env string
namespace string
filename string
logger *zap.SugaredLogger
abs func(string) (string, error)
@ -673,7 +674,7 @@ func (r *twoPassRenderer) renderTemplate(content []byte) (*bytes.Buffer, error)
// try a first pass render. This will always succeed, but can produce a limited env
firstPassEnv := r.renderEnvironment(content)
secondPassRenderer := tmpl.NewFileRenderer(r.reader, filepath.Dir(r.filename), firstPassEnv)
secondPassRenderer := tmpl.NewFileRenderer(r.reader, filepath.Dir(r.filename), firstPassEnv, r.namespace)
yamlBuf, err := secondPassRenderer.RenderTemplateContentToBuffer(content)
if err != nil {
if r.logger != nil {
@ -704,6 +705,7 @@ func (a *app) FindAndIterateOverDesiredStates(fileOrDir string, converge func(*s
r := &twoPassRenderer{
reader: a.readFile,
env: env,
namespace: namespace,
filename: f,
logger: a.logger,
abs: a.abs,

View File

@ -45,6 +45,7 @@ func makeRenderer(readFile func(string) ([]byte, error), env string) *twoPassRen
return &twoPassRenderer{
reader: readFile,
env: env,
namespace: "namespace",
filename: "",
logger: logger,
abs: filepath.Abs,
@ -99,7 +100,7 @@ releases:
func TestReadFromYaml_RenderTemplate(t *testing.T) {
defaultValuesYalm := []byte(`
defaultValuesYaml := []byte(`
releaseName: "hello"
conditionalReleaseTag: "yes"
`)
@ -127,7 +128,7 @@ releases:
if !strings.HasSuffix(filename, expectedFilename) {
return nil, fmt.Errorf("unexpected filename: expected=%s, actual=%s", expectedFilename, filename)
}
return defaultValuesYalm, nil
return defaultValuesYaml, nil
}
r := makeRenderer(fileReader, "staging")
@ -158,7 +159,7 @@ releases:
}
func TestReadFromYaml_RenderTemplateWithValuesReferenceError(t *testing.T) {
defaultValuesYalm := []byte("")
defaultValuesYaml := []byte("")
yamlContent := []byte(`
environments:
@ -176,7 +177,7 @@ releases:
// make a reader that returns a simulated context
fileReader := func(filename string) ([]byte, error) {
return defaultValuesYalm, nil
return defaultValuesYaml, nil
}
r := makeRenderer(fileReader, "staging")
@ -193,7 +194,7 @@ releases:
// This does not apply to .gotmpl files, which is a nice side-effect.
func TestReadFromYaml_RenderTemplateWithGotmpl(t *testing.T) {
defaultValuesYalmGotmpl := []byte(`
defaultValuesYamlGotmpl := []byte(`
releaseName: {{ readFile "nonIgnoredFile" }}
`)
@ -215,7 +216,7 @@ releases:
if strings.HasSuffix(filename, "nonIgnoredFile") {
return []byte("release-a"), nil
}
return defaultValuesYalmGotmpl, nil
return defaultValuesYamlGotmpl, nil
}
r := makeRenderer(fileReader, "staging")
@ -232,3 +233,29 @@ releases:
t.Fatal("release should have been declared")
}
}
func TestReadFromYaml_RenderTemplateWithNamespace(t *testing.T) {
defaultValuesYaml := []byte(``)
yamlContent := []byte(`releases:
- name: {{ .Namespace }}-myrelease
chart: mychart
`)
// make a reader that returns a simulated context
fileReader := func(filename string) ([]byte, error) {
return defaultValuesYaml, nil
}
r := makeRenderer(fileReader, "staging")
yamlBuf, err := r.renderTemplate(yamlContent)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
var state state.HelmState
err = yaml.Unmarshal(yamlBuf.Bytes(), &state)
if state.Releases[0].Name != "namespace-myrelease" {
t.Errorf("release name should be namespace-myrelease")
}
}

View File

@ -61,7 +61,7 @@ wait_deploy_ready httpbin-httpbin
retry 5 "curl --fail $(minikube service --url --namespace=${test_ns} httpbin-httpbin)/status/200"
[ ${retry_result} -eq 0 ] || fail "httpbin failed to return 200 OK"
info "Deleting release"
${helmfile} -f ${dir}/happypath.yaml delete
${helmfile} -f ${dir}/happypath.yaml delete --auto-approve
${helm} status --namespace=${test_ns} httpbin &> /dev/null && fail "release should not exist anymore after a delete"
test_pass "happypath"

View File

@ -16,13 +16,15 @@ type templateFileRenderer struct {
type TemplateData struct {
// Environment is accessible as `.Environment` from any template executed by the renderer
Environment environment.Environment
// Namespace is accessible as `.Namespace` from any non-values template executed by the renderer
Namespace string
}
type FileRenderer interface {
RenderTemplateFileToBuffer(file string) (*bytes.Buffer, error)
}
func NewFileRenderer(readFile func(filename string) ([]byte, error), basePath string, env environment.Environment) *templateFileRenderer {
func NewFileRenderer(readFile func(filename string) ([]byte, error), basePath string, env environment.Environment, namespace string) *templateFileRenderer {
return &templateFileRenderer{
ReadFile: readFile,
Context: &Context{
@ -31,6 +33,7 @@ func NewFileRenderer(readFile func(filename string) ([]byte, error), basePath st
},
Data: TemplateData{
Environment: env,
Namespace: namespace,
},
}
}

View File

@ -15,7 +15,7 @@ type renderer struct {
func NewRenderer(readFile func(filename string) ([]byte, error), basePath string, env environment.Environment) *renderer {
return &renderer{
readFile: readFile,
tmplFileRenderer: tmpl.NewFileRenderer(readFile, basePath, env),
tmplFileRenderer: tmpl.NewFileRenderer(readFile, basePath, env, ""),
}
}