helm-template get value of the map by key - kubernetes-helm

In the helm-template I'm trying to retrieve a value of the map by key.
I've tried to use the index from the go-templates, as suggested here:
Access a map value using a variable key in a Go template
However it doesn't work for me (see later test). Any idea for the alternative solution?
Chart.yaml:
apiVersion: v1
appVersion: "1.0"
description: A Helm chart for Kubernetes
name: foochart
version: 0.1.0
values.yaml:
label:
- name: foo
value: foo1
- name: bar
value: bar2
templates/test.txt
label: {{ .Values.label }}
Works OK for helm template .:
---
# Source: foochart/templates/test.txt
label: [map[value:foo1 name:foo] map[name:bar value:bar2]]
However once trying to use the index:
templates/test.txt
label: {{ .Values.label }}
foolabel: {{ index .Values.label "foo" }}
It won't work - helm template .:
Error: render error in "foochart/templates/test.txt": template: foochart/templates/test.txt:2:13: executing "foochart/templates/test.txt" at <index .Values.label ...>: error calling index: cannot index slice/array with type string

label is an array, so the index function will only work with integers, this is a working example:
foolabel: {{ index .Values.label 0 }}
The 0 selects the first element of the array.
A better option is to avoid using an array and replace it with a map:
label:
foo:
name: foo
value: foo1
bar:
name: bar
value: bar2
And you dont even need the index function:
foolabel: {{ .Values.label.foo }}

values.yaml
coins:
ether:
host: 10.11.0.50
port: 123
btc:
host: 10.11.0.10
port: 321
template.yaml
{{- range $key, $val := .Values.coins }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ $key }}
- env:
- name: SSH_HOSTNAME
value: {{ $val.host | quote }}
- name: SSH_TUNNEL_HOST
value: {{ $val.port | quote }}
---
{{- end }}
run $ helm template ./helm
---
# Source: test/templates/ether.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: btc
- env:
- name: SSH_HOSTNAME
value: "10.11.0.10"
- name: SSH_TUNNEL_HOST
value: "321"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: ether
- env:
- name: SSH_HOSTNAME
value: "10.11.0.50"
- name: SSH_TUNNEL_HOST
value: "123"
---

Related

Read an array in helm template from value file

I am trying to set and read array value like described below , parsing of yaml template file to json is failing , please suggest resolution.
template file :
spec:
arguments: {{ toYaml .Values.sparkapplication.spec.arguments | indent 6 }}
values file :
sparkapplication :
spec:
arguments:
- val: "/spark_app_prop/config.properties"
- val: "/spark_app_prop/log4j.properties"
expected parsed result in template file should be :
spec:
arguments: [ "/tmp/spark-streaming-poc-app-1.0.0.1/infa_conf/config.properties", "/tmp/spark-streaming-poc-app-1.0.0.1/infa_conf/log4j.properties" ]
values.yaml
sparkapplication :
spec:
arguments:
- val: "/spark_app_prop/config.properties"
- val: "/spark_app_prop/log4j.properties"
template/cm.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
{{- $list := list }}
{{- range .Values.sparkapplication.spec.arguments }}
{{- $list = append $list .val }}
{{- end }}
arguments: {{ toJson $list }}
output
apiVersion: v1
kind: ConfigMap
metadata:
name: test
data:
arguments: ["/spark_app_prop/config.properties","/spark_app_prop/log4j.properties"]

Helm Go Templating using Dictionary. I am need help in getting the values

I can not find a way to iterate over a range in helm templating. I have the next definition in my values.yaml
Variable dictionary to be consumed
projects:
- tenants: imc
namespaces:
- name: test-1
company: inter
environments:
- build
- dev
- stage
- test
- name: test-2
environments:
- build
- dev
- stage
- test
- name: test-3
environments:
- build
- dev
- stage
- test
Code snippet
{{- range $key, $value := .Values.tenants }}
{{- range $nkey, $nvalue := .namespaces }}
---
apiVersion: v1
kind: Namespace
metadata:
annotations:
parent_project_name: {{ $value.name }}
company: {{ $value.company }}
openshift.io/description: ""
openshift.io/display-name: ""
labels:
tenant: {{ $value.tenants }}
name: {{ $value.name }}-{{ $nvalue }}
spec: {}
status: {}
{{- end }}
{{- end }}
I need help in consuming the variable into the template
May you give the expected output? This is what I guess.
values.yaml
projects:
- tenants: imc
namespaces:
- name: test-1
company: inter
environments:
- build
- dev
- stage
- test
- name: test-2
environments:
- build
- dev
- stage
- test
- name: test-3
environments:
- build
- dev
- stage
- test
templates/ns.yaml
{{- range $key, $value := .Values.projects }}
{{- range $nkey, $nvalue := .namespaces }}
---
apiVersion: v1
kind: Namespace
metadata:
annotations:
parent_project_name: {{ $nvalue.name }}
company: {{ $nvalue.company }}
openshift.io/description: ""
openshift.io/display-name: ""
labels:
tenant: {{ $value.tenants }}
name: {{ $nvalue.name }}
spec: {}
status: {}
{{- end }}
{{- end }}
cmd
helm template --debug test .
output
---
apiVersion: v1
kind: Namespace
metadata:
annotations:
parent_project_name: test-1
company: inter
openshift.io/description: ""
openshift.io/display-name: ""
labels:
tenant: imc
name: test-1
spec: {}
status: {}
---
apiVersion: v1
kind: Namespace
metadata:
annotations:
parent_project_name: test-2
company:
openshift.io/description: ""
openshift.io/display-name: ""
labels:
tenant: imc
name: test-2
spec: {}
status: {}
---
apiVersion: v1
kind: Namespace
metadata:
annotations:
parent_project_name: test-3
company:
openshift.io/description: ""
openshift.io/display-name: ""
labels:
tenant: imc
name: test-3
spec: {}
status: {}

How to create a k8s configmap by looping over nested helm values

The helm values look like in the following example. Here appdata can scale to any number but will contain the same set of keys.
data:
appdata:
config0:
url: 'https://example1.com'
port: '80'
config1:
url: 'https://example2.com'
port: '8673'
someotherconfig:
url: 'https://example3.com'
port: '9887'
...
...
This is what I have so far. This keeps updating the last config's data from someotherconfig key and also I want to have the config map name to contain the config name for each iteration, like {{ template "app" $ }}-config0, {{ template "app" $ }}-config1 and so on based on iteration.
{{- range $Mydata := $.Values.data.appdata }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "app" $ }}
labels:
data:
url: {{ $Mydata.url }}
port: {{ $Mydata.port }}
{{- end }}
You're almost there. You need to use the key/value notation to get the key name. Try the following.
{{- range $configuration, $Mydata := $.Values.data.appdata }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ template "app" $ }}-{{ $configuration }}
data:
url: {{ $Mydata.url }}
port: {{ $Mydata.port }}
{{- end }}

Helm not merging array of secrets

I am trying to do merge of multiple values files which has array of secrets.But the merging is not working instead the last values file overrides.
This is my secret template
---
{{- range .Values.secrets }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ required "a valid name is required" .name }}
namespace: ""
type: Opaque
data:
{{- range $key, $val := .data }}
# fix printing the key name in the required string
{{ $key }}: {{ required "a valid key is required" $val }}
{{- end }}
{{- end }}
value1.yaml:
secrets:
- name: "sample"
data:
test: "YXBpa2V5MQo="
value2.yaml:
- name: "sample2"
data:
test: "YXBpa2V5MQo="
helm template secrets-template -f value1.yaml -f value2.yaml
The output is
---
apiVersion: v1
kind: Secret
metadata:
name: sample2
namespace: ""
type: Opaque
data:
# fix printing the key name in the required string
test: YXBpa2V5MQo=
But the expected output is
---
apiVersion: v1
kind: Secret
metadata:
name: sample
namespace: ""
type: Opaque
data:
# fix printing the key name in the required string
test: YXBpa2V5MQo=
---
apiVersion: v1
kind: Secret
metadata:
name: sample2
namespace: ""
type: Opaque
data:
# fix printing the key name in the required string
test: YXBpa2V5MQo=
Any help on this ?
As far as I can tell, helm always overwrites arrays. A work around, is to use dictionaries. For example, use the name of the secret as the key.
template:
---
{{- range $secretName, $secretValue := .Values.secrets }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ required "a valid name is required" $secretName }}
namespace: ""
type: Opaque
data:
{{- range $key, $val := $secretValue }}
# fix printing the key name in the required string
{{ $key }}: {{ required "a valid key is required" $val }}
{{- end }}
{{- end }}
value1.yaml
secrets:
sample:
test: "YXBpa2V5MQo="
value2.yaml
secrets:
sample2:
test: "YXBpa2V5MQo="
Thankyou..it works..I did a small modification.
{{- range $secretName,$secretValue := .Values.secrets }}
---
apiVersion: v1
kind: Secret
metadata:
name: {{ required "a valid name is required" $secretName }}
type: {{ $secretValue.type | default "Opaque" }}
data:
{{- range $key, $val := $secretValue.data }}
# fix printing the key name in the required string
{{ $key }}: {{ required "a valid key is required" $val }}
{{- end }}
{{- end }}
values file:
secrets:
sample2:
data:
test2: "YXBpa2V5MQo="
But I am getting below warning eventhough it works fine..Is this a problem?How to fix this warning?
coalesce.go:160: warning: skipped value for secrets: Not a table.

Kubernetes - How to define ConfigMap built using a file in a yaml?

At present I am creating a configmap from the file config.json by executing:
kubectl create configmap jksconfig --from-file=config.json
I would want the ConfigMap to be created as part of the deployment and tried to do this:
apiVersion: v1
kind: ConfigMap
metadata:
name: jksconfig
data:
config.json: |-
{{ .Files.Get "config.json" | indent 4 }}
But doesn't seem to work. What should be going into configmap.yaml so that the same configmap is created?
---UPDATE---
when I do a helm install dry run:
# Source: mychartv2/templates/jks-configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: jksconfig
data:
config.json: |
Note: I am using minikube as my kubernetes cluster
Your config.json file should be inside your mychart/ directory, not inside mychart/templates
Chart Template Guide
configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
config.json: |-
{{ .Files.Get "config.json" | indent 4}}
config.json
{
"val": "key"
}
helm install --dry-run --debug mychart
[debug] Created tunnel using local port: '52091'
[debug] SERVER: "127.0.0.1:52091"
...
NAME: dining-saola
REVISION: 1
RELEASED: Fri Nov 23 15:06:17 2018
CHART: mychart-0.1.0
USER-SUPPLIED VALUES:
{}
...
---
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: dining-saola-configmap
data:
config.json: |-
{
"val": "key"
}
EDIT:
But I want it the values in the config.json file to be taken from values.yaml. Is that possible?
configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
config.json: |-
{
{{- range $key, $val := .Values.json }}
{{ $key | quote | indent 6}}: {{ $val | quote }}
{{- end}}
}
values.yaml
json:
key1: val1
key2: val2
key3: val3
helm install --dry-run --debug mychart
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mangy-hare-configmap
data:
config.json: |-
{
"key1": "val1"
"key2": "val2"
"key3": "val3"
}
Here is an example of a ConfigMap that is attached to a Deployment:
ConfigMap:
---
apiVersion: v1
kind: ConfigMap
metadata:
name: jksconfig
data:
config.json: |-
{{ .Files.Get "config.json" | indent 4 }}
Deployment:
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: jksapp
labels:
app: jksapp
spec:
selector:
matchLabels:
app: jksapp
template:
metadata:
labels:
app: jksapp
containers:
- name: jksapp
image: jksapp:1.0.0
ports:
- containerPort: 8080
volumeMounts:
- name: config #The name(key) value must match pod volumes name(key) value
mountPath: /path/to/config.json
volumes:
- name: config
configMap:
name: jksconfig
Soln 01:
insert your config.json file content into a template
then use this template into your data against config.json
then run $ helm install command
finally,
{{define "config"}}
{
"a": "A",
"b": {
"b1": 1
}
}
{{end}}
apiVersion: v1
kind: ConfigMap
metadata:
name: jksconfig
labels:
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
app: "my-app"
heritage: "{{ .Release.Service }}"
release: "{{ .Release.Name }}"
data:
config.json: {{ (include "config" .) | trim | quote }}