Helm templating doesn't let me use dash in names - kubernetes-helm

I am creating a helm chart for my app. In the templates directory, I have a config-map.yaml with this in it
{{- with Values.xyz }}
xyz.abc-def: {{ .abc-def }}
{{- end }}
When I try to run helm install I get a
Error: parse error in "config-map.yaml": template:config-map.yaml:2: unexpected bad character U+002D '-' in command.
Is there a way to use dashes in the name and variable for helm?

Might be worth trying using index method:
xyz.abc-def: {{ index .Values.xyz "abc-def" }}
looks like it's still restricted by helm to allow hyphens in variable names (as well in subchart names) and index is a workaround

I faced the same issue because the resource defined had a '-' in its name:
resources:
{{- with .Values.my-value }}
After I removed the '-', the error disappeared:
resources:
{{- with .Values.myvalue }}

Related

helm --set to select environment

Struggling with some helm templating...
I'm trying to pass a separate yaml file with springboot parameters to helm, and have them split by environment... then I want to pass the environment to helm using --set env=staging
Feels like I've tried everything but clearly I'm lacking a fundamental understanding...
My _helpers.tpl contains these:
{{- define "env" }}
{{- printf "%s" .Values.env }}
{{- end }}
{{ define "configmap.metadata" }}
name: {{ .Values.name }}-config
{{ end }}
{{ define "configmap.properties" }}
{{ index .Values.environment (include "env" .) "properties" | indent 4 }}
{{ end }}
The template for the config map:
apiVersion: v1
kind: ConfigMap
metadata:
{{ include "configmap.metadata" . }}
data:
app.properties: |-
{{ include "configmap.properties" .}}
And the yaml file containing the properties looks like this:
environment:
staging:
properties:
spring:
datasource:
url: something
username: something
password: something
app1:
key: something
secret: something
baseUri: something
app2:
bootstrap_server: something
bootstrap_port: something
registry_schema: something
production:
properties:
spring:
etc, etc
And then I want to select the environment using set. I'm testing with:
helm template test . -f values.yaml -f properties.yaml --set env=staging
I think I've just tried so many things that I just can't see the wood for the trees! The error I'm seeing is:
Error: template: microservice/templates/configmap.yaml:7:7: executing "microservice/templates/configmap.yaml" at <include "configmap.properties" .>: error calling include: template: microservice/templates/_helpers.tpl:56:76: executing "configmap.properties" at <4>: wrong type for value; expected string; got map[string]interface {}
EDIT:
After tweaking, I'm still getting an error, but I'm seeing something in the configmap.. but I wonder if the error is due to the 8 spaces on the first line..
data:
app.properties: |-
app2:
bootstrap_port: something
bootstrap_server: something
registry_schema: something
app1:
baseUri: something
key: something
secret: something
spring:
datasource:
password: something
url: something
username: something
I think your actual error message is around the way you're using the .Values.environment.production.properties value. It's a YAML map, but the indent function expects it to be a string. You should be able to see some odd indentation and maybe an odd [map spring [map datasource ...]] string if you use the helm template --debug option.
When you go to render the ConfigMap, you need to make sure to do two things. Since the data you have is structured properties, you need to use the lightly-documented toYaml function to convert it back to YAML. This will begin at the first column, so you need to apply the indent function to it, and then you need to make sure the markup that invokes it is also at the first column (indent should be the only thing that supplies indentation).
data:
app.properties: |-
{{ include "configmap.properties" . | indent 4}}
{{/*- starts at column 1, but includes the `indent` function */}}
{{ define "configmap.properties" }}
{{- index .Values.environment (.Values.env) "properties" | toYaml }}
{{/*- starts at first column, includes `toYaml`, does not include `indent` */}}
{{- end }}

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.

Unknown object type "nil" in Secret.data.redis-password

I have a tool which is now available to be deployed on Kubernetes. A known person made a document on getithub where he asked to run two power shell files. source
When I run first file 0-install-tools.ps1, it installs tools like virtualbox, minikube, helm and kubernetes-cli.
When I run second file 1-Deploy-Minikube.ps1, it is getting failed on last step where it is executing:
helm install -n qliksense qlik/qliksense -f values.yaml
The person who has created the getithub doc on the same has run it successful but am not sure why it is failing at my windows10 machine.
Following error I am getting:
error validating data: unknown object type "nil" in Secret.data.redis-password
Can you please help me to know why it is failing at my side or there is some problem with the version these powershell files are installing ?
Hardware: 3 core and 8 GB RAM.
I am hoping a positive response from your team.
Thanks,
Rohit
I rerun powershell files several times.
Expected result is mentioned in the article I discussed in content
set the empty properties as:'''''' instead of nil, null or ""
I had same problem. In my case solution is create new function in _helpers.tpl
{{/*
Nullable secret value
*/}}
{{- define "secretValue" -}}
{{- $value := . }}
{{- if $value }}
{{- printf "%s" $value | b64enc }}
{{- else }}
{{- printf "%q" "" }}
{{- end }}
{{- end }}
then in secret.yaml past follow
apiVersion: v1
kind: Secret
metadata:
name: common-secret
type: Opaque
data:
REDIS_PASSWORD: {{ include "secretValue" .Values.redisPassword }}
result is
apiVersion: v1
kind: Secret
metadata:
name: common-secret
type: Opaque
data:
REDIS_PASSWORD: ""
You need to downgrade to Helm 12.3.1 as recently described in the project Troubleshooting.
This error appears during Qlik package installation, when using Helm 2.14. Issue can be reoslve by downgrading to Helm 12.3.1.
choco install kubernetes-helm --version 2.13.1 --yes --force
Make sure to quote the secret value before encrypting it
{{- range $key, $val := .Values.secretEnv }}
{{ $key }}: {{ $val | quote | b64enc }}
{{- end }}

How to reference a value defined in a template in a sub-chart in helm for kubernetes?

I'm starting to write helm charts for our services.
There are two things I'm not sure how they are supposed to work or what to do with them.
First: the release name. When installing a chart, you specify a name which helm uses to create a release. This release name is often referenced within a chart to properly isolate chart installs from each other? For example the postgres chart contains:
{{- define "postgresql.fullname" -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
Which is then used for the service:
metadata:
name: {{ template "postgresql.fullname" . }}
It does look like "myrelease-postgresql" in the end in kubernetes.
I wonder what a good release name is? What is typically used for this? A version? Or some code-name like the ubuntu releases?
Second: referencing values.
My chart uses postgresql as a sub-chart. I'd like to not duplicate the way the value for the name of the postgresql service is created (see snipped above).
Is there a way I can reference the service name of a sub-chart or that template define {{ template "postgresql.fullname" . }} in the parent chart? I need it to pass it into my service as database host (which works if I hardcode everything but that cannot be the meaning of this).
I tried:
env:
- name: DB_HOST
value: {{ template "mychart.postgresql.fullname" . }}
But that lead into an error message:
template "mychart.postgresql.fullname" not defined
I've seen examples of Charts doing similar things, like the odoo chart. But in here that logic how the postgresql host name is created is copied and an own define in the template is created.
So is there a way to access sub-chart names? Or values or template defines?
Thanks!
Update after some digging:
According to Subcharts and Globals the templates are shared between charts.
So what I can do is this:
In my chart in _helpers.tpl I add (overwrite) the postgres block:
{{- define "postgresql.fullname" -}}
{{- $name := .Values.global.name -}}
{{- printf "%s-%s" $name "postgresql" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
So this value is used when the sub-chart is deployed. I cannot reference all values or the chart name in here as it will be different in the sub-chart - so I used a global value.
Like this I know the value of the service that is created in the sub-chart.
Not sure if this is the best way to do this :-/
Are you pulling in postgresql as a subchart of your chart (via your chart's requirements.yaml)? If so, both the postgresql (sub) chart and your chart will have the same .Release.Name - thus, you could specify your container's environment as
env:
- name: DB_HOST
value: {{ printf "%s-postgresql" .Release.Name }}
if you override postgresql's name by adding the following to your chart's values.yaml:
postgresql:
nameOverride: your-postgresql
then your container's env would be:
env:
- name: DB_HOST
value: {{ printf "%s-%s" .Release.Name .Values.postgresql.nameOverride }}
You can overwrite the values of the subchart with the values of the parent chart as described here:
https://helm.sh/docs/chart_template_guide/subcharts_and_globals/
I don't think it's possible (and it also doesn't make sense) to override the template name of the subchart.
What I would do is define the database service name in the .Values files both in the parent and sub charts and let helm override the one in the subchart - that way you will always have the database name in the parent chart. This would however mean that the service name of the database should not be {{ template "name" . }}, but something like {{ .Values.database.service.name }}
mychart/.Values
mysubchart:
service:
name: my-database
mychart/templates/deployment.yaml
env:
- name: DB_HOST
value: {{ .Values.mysubchart.service.name }}
mychart/charts/mysubchart/.Values
service:
name: my-database
mychart/charts/mysubchart/templates/service.yaml:
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.service.name }}
Another way is to use global chart values, also described in https://helm.sh/docs/chart_template_guide/subcharts_and_globals/
For values in the helper.tpl instead of values.yaml
To access a value from a chart you do the following:
{{ template "keycloak.fullname" . }}
To access a value from a sub chart
{{ template "keycloak.fullname" .Subcharts.keycloak }}
You could import values from a sub chart as described here: https://helm.sh/docs/topics/charts/#importing-child-values-via-dependencies.
However there is a caveat. This works not for values defined at the root level in the values.yaml.
See this issue for more information: https://github.com/helm/helm/issues/9817