{{ If }} clause inside of range scope doesn't see values - kubernetes

The task is to range over workers collection and if the current worker has autoscaling.enabled=true create an hpa for it.
I've tried to compare .autoscaling.enabled to "true" but it returned "error calling eq: incompatible types for comparison". Here people say that it actually means that .autoscaling.enabled is nil. So {{ if .autoscaling.enabled }} somehow doesn't see the variable and assumes it doesn't exist.
Values:
...
workers:
- name: worker1
command: somecommand1
memoryRequest: 500Mi
memoryLimit: 1400Mi
cpuRequest: 50m
cpuLimit: 150m
autoscaling:
enabled: false
- name: worker2
command: somecommand2
memoryRequest: 512Mi
memoryLimit: 1300Mi
cpuRequest: 50m
cpuLimit: 150m
autoscaling:
enabled: false
- name: workerWithAutoscaling
command: somecommand3
memoryRequest: 600Mi
memoryLimit: 2048Mi
cpuRequest: 150m
cpuLimit: 400m
autoscaling:
enabled: true
minReplicas: 1
maxReplicas: 5
targetCPUUtilization: 50
targetMemoryUtilization: 50
...
template:
...
{{- range .Values.workers }}
{{- if .autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
labels:
...
name: "hpa-{{ .name }}-{{ $.Realeas.Name }}"
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ .name }}
minReplicas: {{ .minReplicas }}
maxReplicas: {{ .maxReplicas }}
metrics:
{{- with .targetCPUUtilization}}
- type: Resource
resource:
name: cpu
targetAverageUtilization: {{ . }}
{{- end }}
{{- with .targetMemoryUtilization}}
- type: Resource
resource:
name: memory
targetAverageUtilization: {{ . }}
{{- end }}
---
{{- end }}
{{- end }}
I expect the manifest for one hpa that targets workerWithAutoscaling, but the actual output is totally empty.

Your use of {{- range .Values.workers }} and {{- if .autoscaling.enabled }} is fine. You are not getting any values because .minReplicas, .maxReplicas, etc, are inside .autoscaling scope.
See Modifying scope using with
Adding {{- with .autoscaling}} will solve the issue.
{{- range .Values.workers }}
{{- if .autoscaling.enabled }}
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
labels:
name: "hpa-{{ .name }}-{{ $.Release.Name }}"
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: {{ .name }}
{{- with .autoscaling}}
minReplicas: {{ .minReplicas }}
maxReplicas: {{ .maxReplicas }}
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: {{ .targetCPUUtilization}}
- type: Resource
resource:
name: memory
targetAverageUtilization: {{ .targetMemoryUtilization}}
{{- end }}
{{- end }}
{{- end }}
helm template .
---
# Source: templates/hpa.yaml
apiVersion: autoscaling/v2beta1
kind: HorizontalPodAutoscaler
metadata:
labels:
name: "hpa-workerWithAutoscaling-release-name"
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: workerWithAutoscaling
minReplicas: 1
maxReplicas: 5
metrics:
- type: Resource
resource:
name: cpu
targetAverageUtilization: 50
- type: Resource
resource:
name: memory
targetAverageUtilization: 50

Related

Kubernetes CronJob Helm template can not set value to true

i have a helm template vor an cronjob in a chart:
apiVersion: batch/v1
kind: CronJob
metadata:
name: {{ include "gdp-chart.fullname" . }}-importjob
labels:
{{- include "gdp-chart.labels" . | nindent 4 }}
spec:
suspend: {{ .Values.import.suspend }}
schedule: {{ .Values.import.schedule }}
jobTemplate:
metadata:
name: import-job
spec:
template:
spec:
containers:
- image: curlimages/curl
name: import-job
args:
- "$(GDP_INT_IMPORT_URL)"
{{- with .Values.import.env}}
env:
{{- toYaml . | nindent 12}}
{{- end}}
restartPolicy: Never
I want to change spec.suspend by command. If i set it to from true to false it works, suspend is set to false:
helm upgrade --reuse-values --set import.suspend=false gdp gdp-api
but if i try to set it to from false true, the value of suspend does not change to true:
helm upgrade --reuse-values --set import.suspend='true' gdp gdp-api
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
gdp-api-importjob 0 0 31 2 * False 0 7h32m 3d7h
Why is this the case?

helm to create single configmap with different labels

can anyone help me creating configmaps in helm with different labels.
I have 6 configmaps each have their own labels which will be used by pods. I would like to have the same labels in helm as well. Is it possible in Helm?
These are my values for configmap. I want to render these values and create separate configmap.
values.yaml/
configmaptestingforhelm:
configmapref1:
confname: serviceaccount-config
key: serviceaccount.test.path
value: /root/test_key.json
configmapref2:
confname: host-credentials-config
key: secret.credentials.host.path
value: /root/host_key.json
I am trying to create separate configmap for each configmappref* as below
configmap1
apiVersion: v1
kind: ConfigMap
{{- range $value := .Values.configmap.configmapref1 }}
metadata:
name: {{ $value.confname }}
data:
{{ $value.key }} : {{ $value.value }}
{{- end}}
configmap2
apiVersion: v1
kind: ConfigMap
{{- range $value := .Values.configmap.configmapref2 }}
metadata:
name: {{ $value.confname }}
data:
{{ $value.key }} : {{ $value.value }}
{{- end}}
My expected output is as below ,but I am not getting the desired output
apiVersion: v1
data:
secret.credentials.host.path: /root/host_key.json
kind: ConfigMap
metadata:
name: host-credentials-config
apiVersion: v1
data:
serviceaccount.test.path: /root/test_key.json
kind: ConfigMap
metadata:
name: serviceaccount-config
values.yaml
testLables:
cm0:
a: b
c: d
cm1:
e: f
g: k
templates/configmap.yaml
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "test.fullname" . }}-0
labels:
{{- include "test.labels" . | nindent 4 }}
{{- range $k, $v := .Values.testLables.cm0 }}
{{ $k }}: {{ $v }}
{{- end }}
data:
data: |-
k: v
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ include "test.fullname" . }}-1
labels:
{{- include "test.labels" . | nindent 4 }}
{{- range $k, $v := .Values.testLables.cm1 }}
{{ $k }}: {{ $v }}
{{- end }}
data:
data: |-
k: v
cmd:
helm template --debug test .
output
---
# Source: test/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: test-0
labels:
helm.sh/chart: test-0.1.0
app.kubernetes.io/name: test
app.kubernetes.io/instance: test
app.kubernetes.io/version: "1.18.0"
app.kubernetes.io/managed-by: Helm
a: b
c: d
data:
data: |-
k: v
---
# Source: test/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: test-1
labels:
helm.sh/chart: test-0.1.0
app.kubernetes.io/name: test
app.kubernetes.io/instance: test
app.kubernetes.io/version: "1.18.0"
app.kubernetes.io/managed-by: Helm
e: f
g: k
data:
data: |-
k: v
update:
values.yaml
configmaptestingforhelm:
configmapref1:
confname: serviceaccount-config
key: serviceaccount.test.path
value: /root/test_key.json
configmapref2:
confname: host-credentials-config
key: secret.credentials.host.path
value: /root/host_key.json
templates/configmap.yaml
{{- range $k, $cm := .Values.configmaptestingforhelm }}
---
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ $cm.confname }}
data:
{{ $cm.key }}: {{ $cm.value }}
{{- end }}
cmd
helm template --debug test .
output:
---
apiVersion: v1
kind: ConfigMap
metadata:
name: serviceaccount-config
data:
serviceaccount.test.path: /root/test_key.json
---
apiVersion: v1
kind: ConfigMap
metadata:
name: host-credentials-config
data:
secret.credentials.host.path: /root/host_key.json

Helm - Check if value not exists OR part of list

Assuming I have this values.yaml under my helm chart -
tasks:
- name: test-production-dev
env:
- production
- dev
- name: test-dev
env:
- dev
- name: test-all
environment_variables:
STAGE: dev
I would like to run my cronjob based on these values -
if .env doesn't exist - run any time.
if .env exists - run only if environment_variables.STAGE is in the .env list.
This is what I've done so far ( with no luck ) -
{{- range $.Values.tasks}}
# check if $value.env not exists OR contains stage
{{if or .env (hasKey .env "$.Values.environment_variables.STAGE") }}
apiVersion: batch/v1
kind: CronJob
...
{{- end}}
---
{{- end}}
values.yaml
tasks:
- name: test-production-dev
env:
- production
- dev
- name: test-dev
env:
- dev
- name: test-all
- name: test-production
env:
- production
environment_variables:
STAGE: dev
template/xxx.yaml
plan a
...
{{- range $.Values.tasks }}
{{- $flag := false }}
{{- if .env }}
{{- range .env }}
{{- if eq . $.Values.environment_variables.STAGE }}
{{- $flag = true }}
{{- end }}
{{- end }}
{{- else }}
{{- $flag = true }}
{{- end }}
{{- if $flag }}
apiVersion: batch/v1
kind: CronJob
meta:
name: {{ .name }}
{{- end }}
{{- end }}
...
plan b
...
{{- range $.Values.tasks }}
{{- if or (not .env) (has $.Values.environment_variables.STAGE .env) }}
apiVersion: batch/v1
kind: CronJob
meta:
name: {{ .name }}
{{- end }}
{{- end }}
...
output
...
apiVersion: batch/v1
kind: CronJob
meta:
name: test-production-dev
apiVersion: batch/v1
kind: CronJob
meta:
name: test-dev
apiVersion: batch/v1
kind: CronJob
meta:
name: test-all
...

helm helpers file can't evaluate field type interface array/string

I am rather new to helm, and I am trying to create a chart, but running into values not transforming from the values.yaml file into my generated chart.
here are my values.yaml
apiVersion: security.istio.io/v1alpha2
kind: RequestAuthentication
metadata:
name: name01
namespace: ns-01
spec:
selector:
matchLabels:
app: app-label
jwtRules:
- issuer: foo
jwksUri: bar
forwardOriginalToken: true
audiences:
- user1
- user2
then with my helm template:
apiVersion: networking.istio.io/v1alpha2
kind: RequestAuthentication
metadata:
name: name01
spec:
selector:
matchLabels:
app: {{ .Values.spec.selector.matchLabels.app }}
jwtRules:
- issuer: foo
jwksUri: bar
forwardOriginalToken: true
audiences: |-
{{- range .Values.spec.jwtRules.audiences }}
- {{ . | title | quote }}
{{ end }}
---
I also have a helpers file.
_helpers.tpl
{{/* vim: set filetype=mustache: */}}
{{- define "jwtRules.audiences" -}}
{{- range $.Values.spec.jwtRules.audiences }}
audiences:
- {{ . | quote }}
{{- end }}
{{- end }}
the error its producing: at <.Values.spec.jwtRules.audiences>: can't evaluate field audiences in type interface {}
This one is simple - you don't have a spec.jwtRules.audiences in your values file! jwtRules contains an array, so you'll have to use some index or iterate over it. Also, i don't think that neither your indentation, nor using of |- for audiences is correct, per docs it should be an array of strings.
So i came up with this example (your values are unchanged):
apiVersion: networking.istio.io/v1alpha2
kind: RequestAuthentication
metadata:
name: name01
spec:
selector:
matchLabels:
app: {{ .Values.spec.selector.matchLabels.app }}
jwtRules:
- issuer: foo
jwksUri: bar
forwardOriginalToken: true
audiences:
{{- with (first .Values.spec.jwtRules) }}
{{- range .audiences }}
- {{ . | title | quote -}}
{{- end }}
{{- end }}
renders into:
apiVersion: networking.istio.io/v1alpha2
kind: RequestAuthentication
metadata:
name: name01
spec:
selector:
matchLabels:
app: app-label
jwtRules:
- issuer: foo
jwksUri: bar
forwardOriginalToken: true
audiences:
- "User1"
- "User2"
In this case it uses a first element of array
Thank you #andrew. I also came to a simple solution but would like feedback on it.
I removed the helpers file then modified my helm chart with the following.
values.yaml (is kept the same as above)
helmchart:
apiVersion: networking.istio.io/v1alpha2
kind: RequestAuthentication
metadata:
name: name01
spec:
selector:
matchLabels:
app: {{ .Values.spec.selector.matchLabels.app }}
jwtRules:
- issuer: foo
jwksUri: bar
forwardOriginalToken: true
{{- with index .Values.spec.jwtRules 0 }}
audiences:
{{- range $a := .audiences }}
- {{ $a -}}
{{ end }}
{{ end }}
---
This produces the following:
apiVersion: networking.istio.io/v1alpha2
kind: RequestAuthentication
metadata:
name: name01
spec:
selector:
matchLabels:
app: app-label
jwtRules:
- issuer: foo
jwksUri: bar
forwardOriginalToken: true
audiences:
- user1
- user2
Should I continue to use a helpers file?
Thanks again for all the help.

How to compare a value to a string with go templating

I want to loop through a values file to create a namespace and a networkpolicy in/for that namespace, except for default. I only want to create the policy and not the namespace for default since it is there by default.
values file:
namespaces:
- name: default
- name: test1
- name: test2
template file:
# Loop through the namespace names and create the namespaces
{{- range $namespaces := .Values.namespaces }}
{{- if ne "default" }}
apiVersion: v1
kind: Namespace
metadata:
name: {{ $namespaces.name }}
---
{{- end }}
{{- end }}
# Loop through the namespace names and create a network policy for those namespace
{{- range $namespaces := .Values.namespaces }}
---
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: {{ $namespaces.name }}-networkpolicy
namespace: {{ $namespaces.name }}
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
name: {{ $namespaces.name }}
---
{{- end }}
The error I get is:
Error: UPGRADE FAILED: template: namespaces/templates/namespaces.yaml:3:7: executing "namespaces/templates/namespaces.yaml" at <ne>: wrong number of args for ne: want 2 got 1
It's probably something simple, but not seeing it. Hope someone can help.
This worked for me:
# Loop through the namespace names and create the namespaces
{{- range $namespaces := .Values.namespaces }}
{{- if ne $namespaces.name "default" }}
apiVersion: v1
kind: Namespace
metadata:
name: {{ $namespaces.name }}
---
{{- end }}
{{- end }}
# Loop through the namespace names and create a network policy for those namespace
{{- range $namespaces := .Values.namespaces }}
---
kind: NetworkPolicy
apiVersion: networking.k8s.io/v1
metadata:
name: {{ $namespaces.name }}-networkpolicy
namespace: {{ $namespaces.name }}
spec:
podSelector: {}
ingress:
- from:
- namespaceSelector:
matchLabels:
name: {{ $namespaces.name }}
---
{{- end }}