Helm default value throws error converting YAML to JSON - kubernetes

I have a basic kubernetes helm template like below
apiVersion: v1
kind: ConfigMap
metadata:
name: test
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/instance: {{ .Release.Name }}
data:
config.tpl: |
{{- default ((tpl .Values.configTpl .) | indent 4) (tpl (.Files.Get "files/config.tpl") . | indent 4) -}}
and the values.yml file
configTpl: |
{{ x=8gwifi.org }}
When i apply the helm chart it throw me an error
❯ helm upgrade mychart . --namespace=test --create-namespace --debug
upgrade.go:142: [debug] preparing upgrade for mychart
Error: UPGRADE FAILED: YAML parse error on 8gwifi.org-test/templates/configmap-logfilegen.yaml: error converting YAML to JSON: yaml: line 11: did not find expected comment or line break
helm.go:84: [debug] error converting YAML to JSON: yaml: line 11: did not find expected comment or line break
I tried different configuration
config.tpl: |
{{- default (tpl .Values.configTpl . | indent 4) (tpl (.Files.Get "files/config.tpl") . | indent 4) -}}
still resulting in same error, Is there a way to specify a config value if none is passed then used the hardcoded one
I'm sure it's an YAML syntx issue couldn't figure it out checked all cases
Based on David suggestion
Template debug is showing this
data:
config.tpl: |-
x := 8gwifi.org
y := "functions"
I can cleary see y is not indent and throwing YAML syntax error, not sure how to fix this
This is the updated definition
data:
config.tpl: |-
{{ (tpl .Values.configTpl . | indent 4) | default (tpl (.Files.Get "files/config.tpl") . | indent 4) -}}
values.yml
configTpl: |
x := "8gwifi.org"
y := "function"

You're hitting problems with whitespace in the first line of the block scalar. You should check two things:
The template block containing indent must not itself be indented, it must start at the first column of its line; and
The template block containing indent must not have a - inside the opening curly braces.
{{- $configTpl := .Values.configTpl | default (.Files.Get "tiles/config.tpl") }}
config.tpl: |
{{ tpl $configTpl . | indent 4 }}
The templating language isn't really aware of YAML syntax as it runs. If you have spaces in front of the indent line, they will get emitted, and then indent adds its own leading space, resulting in the last output you get where the first line is indented extra. The - whitespace control marker will also consume the preceding newline, resulting in the first line of the output being on the same line as the YAML block scalar marker.

Related

how split if statement over multiple lines in helm chart

Im trying to format my yml to be more readable.
I have an if statement that is really long with a bunch of and/ors and I would like to be able to spread it across multiple lines
So something along the lines of
{{-if or
(eq 'abc' .values.foo)
(eq 'def' . values.bar)
}}
Def:'works'
{{- end}}
But this throws up errors for incomplete if statement.
Is there some special character or syntax I can use to achieve the above?
helm supports direct line breaks without special characters.
Missing a space between {{ and if.
There is an extra space between . and values.
String constants require double quotes.
demo:
values.yaml
foo: xxx
bar: yyy
templates/cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: test
labels:
{{- include "test.labels" . | nindent 4 }}
data:
cfg: |-
{{- if or
(eq "abc" .Values.foo)
(eq "def" .Values.bar)
}}
if
{{- else }}
else
{{- end }}
cmd
helm template --debug test .
output
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
cfg: |-
else

Creating a configMap from file is critical to file type and lines count in the file

I have a template that creates a configMap from the jmeter-test-data-file-configmap.yaml file in helm chart:
{{- if .Values.env.datafile }}
apiVersion: v1
kind: ConfigMap
metadata:
name: jmeter-testdata
data:
{{ .Values.env.datafile }}: |-
{{ .Files.Get .Values.env.datafile | indent 4}}
{{- end }}
the corresponding yaml.configuration is:
env:
testfile: sample
datafile: example.csv
When I do the helm upgrade, everything is ok, if the example.csv is a single line text file like that:
1,1
but is it would have at least two or even more lines
1,1
2,2
the deployment fails with unrelated error message:
upgrade.go:123: [debug] preparing upgrade for jmeter
Error: UPGRADE FAILED: YAML parse error on jmeter/templates/jmeter-test-data-file-configmap.yaml: error converting YAML to JSON: yaml: line 7: did not find expected key
helm.go:81: [debug] error converting YAML to JSON: yaml: line 7: did not find expected key
YAML parse error on jmeter/templates/jmeter-test-data-file-configmap.yaml
and the debug details are:
helm.sh/helm/v3/pkg/releaseutil.(*manifestFile).sort
/home/circleci/helm.sh/helm/pkg/releaseutil/manifest_sorter.go:146
helm.sh/helm/v3/pkg/releaseutil.SortManifests
/home/circleci/helm.sh/helm/pkg/releaseutil/manifest_sorter.go:106
helm.sh/helm/v3/pkg/action.(*Configuration).renderResources
/home/circleci/helm.sh/helm/pkg/action/action.go:165
helm.sh/helm/v3/pkg/action.(*Upgrade).prepareUpgrade
/home/circleci/helm.sh/helm/pkg/action/upgrade.go:215
helm.sh/helm/v3/pkg/action.(*Upgrade).Run
/home/circleci/helm.sh/helm/pkg/action/upgrade.go:124
main.newUpgradeCmd.func2
/home/circleci/helm.sh/helm/cmd/helm/upgrade.go:155
github.com/spf13/cobra.(*Command).execute
/go/pkg/mod/github.com/spf13/cobra#v1.1.1/command.go:850
github.com/spf13/cobra.(*Command).ExecuteC
/go/pkg/mod/github.com/spf13/cobra#v1.1.1/command.go:958
github.com/spf13/cobra.(*Command).Execute
/go/pkg/mod/github.com/spf13/cobra#v1.1.1/command.go:895
main.main
/home/circleci/helm.sh/helm/cmd/helm/helm.go:80
runtime.main
/usr/local/go/src/runtime/proc.go:204
runtime.goexit
/usr/local/go/src/runtime/asm_amd64.s:1374
UPGRADE FAILED
main.newUpgradeCmd.func2
/home/circleci/helm.sh/helm/cmd/helm/upgrade.go:157
github.com/spf13/cobra.(*Command).execute
/go/pkg/mod/github.com/spf13/cobra#v1.1.1/command.go:850
github.com/spf13/cobra.(*Command).ExecuteC
/go/pkg/mod/github.com/spf13/cobra#v1.1.1/command.go:958
github.com/spf13/cobra.(*Command).Execute
/go/pkg/mod/github.com/spf13/cobra#v1.1.1/command.go:895
main.main
/home/circleci/helm.sh/helm/cmd/helm/helm.go:80
runtime.main
/usr/local/go/src/runtime/proc.go:204
runtime.goexit
So, the error points to this line:
{{ .Values.env.datafile }}: |-
What could be wrong here and how can the file itself hurt the template processing because of its new lines? We tired /r/n, /n, /r with no success, all the same
We also tried to hadcode the line:7 like that:
{{- if .Values.env.datafile }}
apiVersion: v1
kind: ConfigMap
metadata:
name: jmeter-testdata
data:
example.csv: |-
{{ .Files.Get .Values.env.datafile | indent 4}}
{{- end }}
and still the same error. And even to replace the template value with the hardcode:
{{- if .Values.env.datafile }}
apiVersion: v1
kind: ConfigMap
metadata:
name: jmeter-testdata
data:
{{ (printf "example.csv" ) }}: |-
{{ .Files.Get (printf "example.csv" ) | indent 4}}
{{- end }}
But still the same error.
And that doesn't happens with almost the same config, that bring the multiline xml file to the configMap exactly the same way:
apiVersion: v1
kind: ConfigMap
metadata:
name: jmeter-test
data:
test.jmx: |-
{{ .Files.Get (printf "%s.jmx" .Values.env.testfile ) | indent 4}}
I suppose, that for some reason, probaby the intend is't applied to all lines for csv file, when it is applied to the jmx file. But how to figure that out ad how to work it around?
UPD:
1, 1
2, 2
3, 3
"intending" files manually like above made the trick, it was deployed, however this file isn't ok to use for the needs then. How to avoid that?
If you have a line containing indent it probably needs to begin at the start of the line, even if it's in otherwise indented context.
{{- if .Values.env.datafile }}
...
data:
{{ .Values.env.datafile }}: |-
{{ .Files.Get .Values.env.datafile | indent 4}}
{{/*- previous line is not indented */}}
{{- end }}
In your original example, let's focus on these two lines:
{{ .Values.env.datafile }}: |-
{{ .Files.Get .Values.env.datafile | indent 4}}
## (these two spaces are important)
Now, if the input line is your second example
1,1
2,2
Now: the line containing indent 4 is itself indented by 2 spaces. So in that line you have the two spaces at the start of the line, plus the four spaces from indent 4, so 6 spaces; then a newline and four spaces from indent 4, but no start-of-line spaces (you're still in the output from indent), so only 4 spaces.
test.jmx: |-
1,1
2,2
If you run helm template --debug on your original chart, you will still get the YAML parsing error, but it should also print out this output.
In some contexts you may find it slightly more aesthetic to use nindent, which includes a newline before the first line's indentation, in combination with a - just inside the curly braces to consume the preceding whitespace (including both spaces and newlines). This should also work:
data:
{{ .Values.env.datafile }}: |-
{{- .Files.Get .Values.env.datafile | nindent 4}}
{{/*- indented, starts with -, uses nindent */}}
But also for example:
metadata:
labels: {{- include "common.labels" . | nindent 4 }}
annotations: {{- include "common.annotations" . | nindent 4 }}
{{ .Files.Get (printf "%s" .Values.env.datafile ) | nindent 4}}
instead of
{{ .Files.Get (printf "%s" .Values.env.datafile ) | indent 4}}
has fixed the problem.
But for me it is still unclear why the problem has been arisen for the csv file, while wasn't there for the XML files. Is it all due to the spaces?

Helm's v3 Example Doesn't Show Multi-line Properties. Get YAML to JSON parse error

In Helm's v3 documentation: Accessing Files Inside Templates, the author gives an example of 3 properties (toml) files; where each file has only one key/value pair.
The configmap.yaml looks like this. I'm only adding one config.toml for simplicity.
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-config
data:
{{- $files := .Files }}
{{- range tuple "config.toml" }}
{{ . }}: |-
{{ $files.Get . }}
{{- end }}
This works fine, until I add a second line to the config.toml file.
config.toml
replicaCount=1
foo=bar
Then I get an Error: INSTALLATION FAILED: YAML parse error on deploy/templates/configmap.yaml: error converting YAML to JSON: yaml: line 9: could not find expected ':'
Any thoughts will be appreciated.
Thanks
Helm will read in that file, but it is (for good or bad) a text templating engine. It does not understand that you are trying to compose a YAML file and thus it will not help you. That's actually why you will see so many, many templates in the wild with {{ .thing | indent 8 }} or {{ .otherThing | toYaml }} -- because you need to help Helm know in what context it is emitting the text
Thus, in your specific case, you'll want the indent filter with a value of 4 because your current template has two spaces for the key indent level, and two more spaces for the value block scalar
data:
{{- $files := .Files }}
{{- range tuple "config.toml" }}
{{ . }}: |-
{{ $files.Get . | indent 4 }}
{{/* notice this ^^^ template expression is flush left,
because the 'indent' is handling whitespace, not the golang template itself */}}
{{- end }}
Also, while this is the specific answer to your question, don't overlook the .AsConfig section on that page which seems much more likely to be what you really want to happen, and requires less indent math

How to use if/else loop in Helm

I am trying to use if/else-if/else loop in helm chart. Basically, I want to add ENV configs in configfile based on the if/else condition. Below is the logic:
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Values.applicationName }}-configmap
labels:
projectName: {{ .Values.applicationName }}
environment: {{ .Values.environment }}
type: configmap
data:
{{- if eq .Values.environment "production" }}
{{ .Files.Get "config-prod.yaml" | nindent 2}}
{{- else if eq .Values.environment "development" }}
{{ .Files.Get "config-dev.yaml" | nindent 2}}
{{- else }}
{{ .Files.Get "config-stage.yaml" | nindent 2}}
{{- end }}
But I am not getting the desired output and facing some issue. Can anybody help me out with this?
Edit1: I have added my modified configmap.yaml as per the suggestions, helm install/template command gives Error: YAML parse error on demo2/templates/configmap.yaml: error converting YAML to JSON: yaml: line 14: did not find expected key error.
also my config-prod and config-stage is being rendered (as per the condition if I give environment: production then config-prod.yaml is being added and if I give environment: stage/null then config-stage.yaml is being added.
Your question would benefit from more specifics.
Please consider adding the following to your question:
How are you trying this? What commands exactly did you run?
How are you "not getting the desired output"? What output did you get?
Please also include:
the relevant entries from your values.yaml
the config-dev.yaml and config-stage.yaml files
Have you run helm template to generate the templates that Helm would apply to your cluster? This would be a good way to diagnose the issue.
I wonder whether you're chomping too much whitespace.
And you should just chomp left, i.e. {{- .... }} rather than left+right {{- ... -}}.
Sorry guys, it was my mistake, my dev-config.yaml has envs and it was defined like key=value, instead of key: value.

What is the difference between fullnameOverride and nameOverride in Helm?

I could find both fullnameOverride and nameOverride in Helm chart.Please help clarifying what is the difference between these two with an example.
nameOverride replaces the name of the chart in the Chart.yaml file, when this is used to construct Kubernetes object names. fullnameOverride completely replaces the generated name.
These come from the template provided by Helm for new charts. A typical object in the templates is named
name: {{ include "<CHARTNAME>.fullname" . }}
If you install a chart with a deployment with this name, and where the Chart.yaml file specifies name: chart-name...
helm install release-name ., the Deployment will be named release-name-chart-name
helm install release-name . --set nameOverride=name-override, the Deployment will be named release-name-name-override
helm install release-name . --set fullnameOverride=fullname-override, the Deployment will be named fullname-override
The generated ...fullname template is (one code branch omitted, still from the above link)
{{- define "<CHARTNAME>.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
So if fullnameOverride is provided, that completely replaces the rest of the logic in the template. Otherwise the name is constructed from the release name and the chart name, where nameOverride overrides the chart name.