How to use Lookup function in Helm Chart - kubernetes

While deploying a Kubernetes application, I want to check if a particular PodSecurityPolicy exists, and if it does then skip installing it again.
I came across the helm lookup function, which allows us to check the existing K8 resources.
While I understand how to use this function to get all the resources of same kind, how do I use this function to check if a PodSecurityPolicy named "myPodSecurityPolicy" exists.
I tried something like this:
{{- if ne (lookup "v1" "PodSecurityPolicy" "" "") "myPodSecurityPolicy"}}
<do my stuff>
{{- end }}
But it doesn't look like I can compare it this way, seeing an error -
error calling ne: invalid type for comparison
Any inputs? Thanks in advance.

Please check your API version and PSP name. Lookup is returning a map or nil not a string and that's why you are getting that error. The following is working for me. For negative expression, just add not after if.
{{- if (lookup "policy/v1beta1" "PodSecurityPolicy" "" "example") }}
<found: do your stuff>
{{- end }}
HTH

Related

how to access certain dotted value in helm ConfigMap

i want to access dotted named value with helm to use in ConfigMap
the value is something like that
valuenum:
joji.json: zok
i want to use it in ConfigMap with helm as this
{{ toYaml .Values.valuenum.joji.json }}
it returns syntax error.
could not find a fix for it.
I found the answer myself, when using index we can search for nested variables with quotes.
{{ index .Values.valuenum "joji.json" }}
link for helm doc about index and more

Use regex in helm template

I'm trying to provide a condition inside my helm template to check for a valid (or a rather invalid) hostname using regexMatch function.
Here's my line of code that I'm using:
{{- if regexMatch "(?:[0-9]{1,3}\.){3}[0-9]{1,3}$" .Values.hostname }}
The related part in the values file is a simple one:
hostname: 10.10.10.10
However, I'm hitting a syntax error with no real explanation:
Error: parse error at (api-gateway/templates/ingress.yml:1): invalid syntax
When I've tried to use the example from the docs: https://helm.sh/docs/chart_template_guide/function_list/#regexmatch-mustregexmatch
it obviously worked, so I wonder why my code isn't working.
Turns out that I needed to use a double backslash to make it work:
{{- if regexMatch "(?:[0-9]{1,3}\\.){3}[0-9]{1,3}$" .Values.hostname }}

Is it possible to configure a helm chart to dynamically use a value based on another value?

Is there any way to use helm logic to analyze the Kubernetes version, i.e. Capabilities.KubeVersion, then dynamically choose a value from a map of Kubernetes versions to values, something like
kubernetesVersionCompatibility:
1.15:
insertValue: foo
1.18:
insertValue: bar
You can stitch together a couple of different parts to do that.
You've already found the .Capabilities built-in object. You can use that to guard against, for instance, the Deployment version change in Kubernetes 1.16:
{{- if .Capabilities.APIVersions.Has "apps/v1" }}
apiVersion: apps/v1
{{- else }}
apiVersion: apps/v1beta1
{{- end }}
kind: Deployment
I'd prefer this method to checking on the .Capabilities.KubeVersion.Version if you can.
You can easily check for an exact match using the structure you show. The core text/template language includes an index function that can look up an arbitrary key in a dictionary:
{{- $v := index .Values.kubernetesVersionCompatibility .Capabilities.KubeVersion.Version }}
Insert the value {{ $v.insertValue }}
(You may need to force the keys to be strings "1.15":.)
There's not a convenient way to look up the highest version less than or equal to the current version. If, say, a developer's kind cluster runs Kubernetes 1.20, the 1.18 values will most likely work, but that would have to be explicitly listed in the values. A last resort could be hard-coding the values:
{{- if ge (int .Capabilities.KubeVersion.Minor) 18 }}
Insert the value bar
{{- else if ge (int .Capabilities.KubeVersion.Minor) 15 }}
Insert the value foo
{{- else }}
Insert the value ???
{{- end }}

Helm Charts - How do I use `default` on undefined object property values?

Using Helm, I was under the impression default would be the fallback if a variable is not defined. However, it doesn't appear Helm can get to values in sub-object hashes:
type: {{ default "NodePort" .Values.fpm.service.type }}
If .Values.fpm.service or service.type is not defined, it should use 9000.
However, attempting to template this throws a nil pointer error:
<.Values.fpm.service.type>: nil pointer evaluating interface {}.type
Is there a way to simply perform this level of variable testing? Or am I subjected to an if/else test?
The intent of this is to optionally define .fpm.service (and [..].type) within your values.yaml file.
(I'm building a Helm Library chart to handle optional definitions by main charts)
According to the official Helm doc (Using Default Function), the syntax is different and you should use it this way:
type: {{ .Values.fpm.service.type | default "NodePort" | quote }}
Doesn't look like there's really a good way to stop Helm from trying to dive into non-existing objects. I moved into a single line if condition, and it worked:
type: {{ if .Values.fpm.service -}} {{ .default "NodePort" .Values.fpm.service.type | quote }} {{- else -}} "NodePort" {{- end }}
This way, I check if fpm.service exists first, before trying .type check. It works, whether .service and .service.type is or is not defined.

How to fail a helm release based on inputs in values.yaml

I'm installing up a helm chart using helm install command. I have values.yaml which takes a few inputs from the user. One of the keys in values.yaml is action, which can only take three predefined values (let's say action1, action2 and action3) as an input. Any other value other than this is invalid.
When a user provides the value to action field in values.yaml and trigger the helm install command, the first thing I need to check is that if the action key has a valid value or not. If the action value is invalid, I want the release to be failed with a proper error message.
e.g.: In case the user has given action: action4, this is not valid and release should fail as .Values.action can only be action1, action2, or action3.
How I can achieve this use case and which file should be best to handle this validation considering the helm structure?
I was able to achieve the use case with below changes.
Added the following code in _helpers.tpl
{{- define "actionValidate" -}}
{{ $action := .Values.actions }}
{{- if or (eq $action "action1") (eq $action "action2") (eq $action "action3") -}}
true
{{- end -}}
{{- end -}}
Invoked this function from a .tpl file like this:-
{{ include "actionValidate" . | required "Action value is incorrect. The valid values are 'action1', 'action2', 'action3' " }}
With HelmV3 there is now an easier way. Just specify a schema that includes your values.
For example:
title: Values
type: object
properties:
action:
description: Some action
type: string
pattern: "^(action1|action2|action3)$"
Not enough rep to comment. However, in response to #Saurabh, you now must YAML comment out the function invocation. Otherwise, Go Template will encounter an invalid return type runtime error from that random true value existing in the middle of the invocation file.
Example
# validation.yaml
---
#{{ include "actionValidate" . | required "Action value is incorrect. The valid values are 'action1', 'action2', 'action3' " }}