Include a helm template in yaml file, removing quotes - kubernetes

This is a snippet from helpers.tpl of my helm chart:
{{/*
Pod-specific labels - added to pod template only
Adding a revision label to the pod will cause it to restart every time the chart is deployed.
*/}}
{{- define "app.podLabels" -}}
helm-revision: {{ .Release.Revision | quote }}
{{- end }}
Including it in pod labels like this:
labels:
{{- include "app.podLabels" . | nindent 8 }}
The result would be as shown below. The quotes around 1 is required because Kubernetes accepts string labels only.
labels:
helm-revision: "1"
I need to use the same template for an init container, replacing the : with = like this:
args:
- "pod"
- "-l {{ include "app.podLabels" . | replace ": " "=" }}"
But the output would be an incorrect yaml:
args:
- "pod"
- "-l helm-revision="1""
with error:
error converting YAML to JSON: yaml: line 34: did not find expected '-' indicator
What I actually want is something like this, that doesn't contain quotes around 1:
args:
- "pod"
- "-l helm-revision=1"
How can I achieve this?

This can be achieved by replacing " with nothing ( In effect, removes "). Escaping the quotes using \ character would be needed.
Also adding a replace function to remove newlines and add , as a separator between labels. This would be helpful if more than one pod-specific label is present. But make sure this will work in your case when rendering the template.
args:
- "pod"
- "-l {{ include "app.podLabels" . | replace ": " "=" | replace "\n" ", " | replace "\"" "" }}"

Related

Helm equals to one of multiple values

I want to have a condition that will be considered as "true" if .Values.envName is "dev" + the release namespace name is one of a closed list. otherwise, it should be "false".
Tried the following, but seems like it gets unexpected "false" when I ran it with .Values.envName = dev & .Values.envName = ns-1:
env:
- name: MY_ENV
{{- if and (eq .Values.envName "dev") (regexMatch "^(?!^ns-1$)(?!^ns-2$).*$" .Release.Namespace)}}
value: 'true'
{{- else }}
value: 'false'
{{- end }}
A general note - if there is a better way to use eq with multiple possible values please let me know.
You can use has to test if some item is in a list; and then you can use list to construct a list of known items.
So for your example, if the test is that envName is exactly dev, and the namespace is either ns-1 or ns-2, then you can say
env:
{{- $isDev := eq .Values.envName "dev" }}
{{- $isNs := list "ns-1" "ns-2" | has .Release.Namespace }}
- name: MY_ENV
value: {{ and $isDev $isNs | toString | quote }}
You could do this case with a regular expression too. The start-of-string test ^ and the end-of-string test $ generally need to be outside parentheses; I wouldn't worry about "non-greedy matches" if you're just trying to determine whether a string matches without extracting things. Here I might write either of
{{- $isNs := regexMatch "^ns-[12]$" .Release.Namespace }}
{{- $isNs := regexMatch "^ns-1|ns-2$" .Release.Namespace }}
If you've got an enumerated list of values that don't neatly fall into a regex, using has and list is probably clearer.

helm multiline file inside range

Im trying to create one secret with multiple file in it.
My value.yaml ( the format of the multiline is not yaml or json)
secretFiles:
- name: helm-template-file
subPath: ".file1"
mode: "0644"
value: |
This is a multiline
value, aka heredoc.
Then my secret file template is secret.yaml:
apiVersion: v1
kind: Secret
metadata:
name: {{ include "helm-template.fullname" . }}-file
namespace: {{ .Release.Namespace }}
labels:
app: {{ include "helm-template.name" . }}
chart: {{ include "helm-template.chart" . }}
type: Opaque
stringData:
{{- range .Values.secretFiles }}
{{ .subPath}}: |
{{ .value | indent 4}}
{{- end }}
The helm install gives error "error converting YAML to JSON: yaml: line 12: did not find expected comment or line break". How can I fix it? Thank you.
values.yaml
secretFiles:
- name: helm-template-file
subPath: ".file1"
mode: "0644"
value: |
This is a multiline
value, aka heredoc.
- name: helm-template-file2
subPath: ".file2"
mode: "0644"
value: |
This is a multiline222
value, aka heredoc.
xxx_tpl.yaml
...
stringData:
{{- range .Values.secretFiles }}
{{ .subPath}}: |
{{- .value | nindent 4}}
{{- end }}
output
...
stringData:
.file1: |
This is a multiline
value, aka heredoc.
.file2: |
This is a multiline222
value, aka heredoc.
ref:
nindent
The nindent function is the same as the indent function, but
prepends a new line to the beginning of the string.
indent
The indent function indents every line in a given string to the specified indent width
When you indent a line, you need to make sure the markup in the line starts at the very first column.
stringData:
{{- range .Values.secretFiles }}
{{ .subPath}}: |
{{ .value | indent 4}}{{/* no space at start of this line */}}
{{- end }}
In the form you have in the original question, the four spaces at the start of the line are copied to the output, then the indent expression adds four more spaces to the start of every line. This results in the first line being indented by eight spaces, and the second line by 4, and that inconsistency results in the YAML parse error you see.
You'd also be able to see this visually if you run helm template --debug over your chart; you'll see the same error but also the template output that can't be parsed.
(#z.x's answer solves the same problem a different way: putting the - inside the curly braces removes both the leading whitespace and also the preceding newline, and then changing indent to nindent puts the newline back.)

helm escape ` in template yaml file

Does anyone know how to espace ` in helm template?
I try to add \ in front doesn't seem to work
original:
{{- if not .Values.istio_cni.chained }}
k8s.v1.cni.cncf.io/networks: '{{ appendMultusNetwork (index .ObjectMeta.Annotations `k8s.v1.cni.cncf.io/networks`) `istio-cni` }}',
{{- end }}
Tried:
{{- if not .Values.istio_cni.chained }}
k8s.v1.cni.cncf.io/networks: '{{`{{ appendMultusNetwork (index .ObjectMeta.Annotations \`k8s.v1.cni.cncf.io/networks\`) `istio-cni` }}`}}',
{{- end }}
Error:
Error: parse error at (test/templates/istio-sidecar-injector-istio-system-ConfigMap.yaml:29): unexpected "k8s" in operand
In the Go text/template language backticks delimit "raw string constants"; in standard Go, there is no escaping at all inside raw string literals and they cannot contain backticks.
In your example, it looks like you're trying to emit a Go template block into the output. You can make this work if you use double quotes around the variable names inside the template, and then backticks around the whole thing:
# double quotes around string literal
# v v
k8s.v1.cni.cncf.io/networks: '{{`{{ appendMultusNetwork ... "istio-cni" }}`}}'
# ^ ^
# backticks around whole expression

trying to remove first and last square brackets from json injecting data into configmap using helm

I have data in a JSON file and am adding each line as key value into a ConfigMap using Helm, but i need to remove first and last curly brackets.
Below is the JSON file content:
{
"type": "PurposeResourcesDefinition",
"version": "1.0",
"purposeId": "p#####",
"description": "Artifactory container registry",
"resources": [{
"type": "artifactory.containerregistry",
"name": "<repository name prefixed with the purpose>"
]
}
I am using the below Helm syntax:
data:
{{ range .Files.Lines "foo/app.json" }}
{{ . }}{{ end }}
How can I remove the surrounding curly brackets using Helm templating?
If you know that { and } will be on lines by themselves, you can just skip them. This isn't especially robust, but it will work for the example you show.
data:
{{- range .Files.Lines "foo/app.json" }}
{{- if and (ne . "{") (ne . "}") }}
{{ . }}
{{- end }}
At a higher level, it looks like you're trying to read in a JSON file and then write these values out as the contents of a ConfigMap. Stripping the leading and trailing braces will work because of the syntactic similarities between YAML and JSON, but it might be better to actively convert from one format to the other. Helm has several undocumented conversion functions including fromJson and toYaml. So you can also write this as:
data: {{- .Files.Get "foo/app.json" | fromJson | toYaml | nindent 2 }}

Add suffix to each list member in helm template

I'm trying to iterate over a list in a helm template, and add a suffix to each member.
I currently have this block of code that does exactly that:
{{- range $host := .Values.ingress.hosts }}
{{- $subdomain := initial (initial (splitList "." $host)) | join "." }}
{{- $topLevelDomain := last (splitList "." $host) }}
{{- $secondLevelDomain := last (initial (splitList "." $host)) }}
- host: {{- printf " %s-%s.%s.%s" $subdomain $environment $secondLevelDomain $topLevelDomain | trimSuffix "-" }}
{{- end }}
Since I need to do the exact same manipulation twice in the same file, I want to create a new list, called $host-with-env, that will contain the suffix I'm looking for. That way I can only perform this operation once.
Problem is - I've no idea how to create an empty list in helm - so I can't append items from the existing list into the new one.
Any idea how can I achieve this?
I'm also fine with altering the existing list but every manipulation I apply to the list seems to apply to the scope of the foreach I apply to it.
Any ideas how to go about this?
It might not be quite clear what result are you trying to achieve, it will be helpful to add your input, like your values.yaml and the desired output. However, I added an example that answers your question.
Inspired by this answer, you can use dictionary.
This code will add suffix to all .Values.ingress.hosts and put them into $hostsWithEnv dictionary into a list, which can be accessed by myhosts key
values.yaml
ingress:
hosts:
- one
- two
configmap.yaml
{{- $hostsWithEnv := dict "myhosts" (list) -}}
{{- range $host := .Values.ingress.hosts -}}
{{- $var := printf "%s.domain.com" $host | append $hostsWithEnv.myhosts | set $hostsWithEnv "myhosts" -}}
{{- end }}
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
{{- range $hostsWithEnv.myhosts}}
- host: {{- printf " %s" . | trimSuffix "-" }}
{{- end }}
output
$ helm install --debug --dry-run .
[debug] Created tunnel using local port: '62742'
...
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: my-configmap
data:
- host: one.domain.com
- host: two.domain.com