how to pass array in helmfile - kubernetes-helm

I have helmfile
releases:
- name: controller
values:
- values/valuedata.yaml
hooks:
{{ toYaml .Values.hooks }}
file with values
hooks:
- events: [ "presync" ]
showlogs: true
command: "bash"
args: [ "args"]
I want to pass the hooks from values how I can do it ?
I tried many ways and I got an error
This is the command
helmfile --file ./myhelmfile.yaml sync
failed to read myhelmfile.yaml: reading document at index 1: yaml: line 26: did not find expected '-' indicator

What you try to do is to inline part of the values.yaml into your template. Therefore you need to take care of the indentation properly.
In your case I think it'll be something like this:
releases:
- name: controller
values:
- values/valuedata.yaml
hooks:
{{ toYaml .Values.hooks | indent 6 }}
You can find a working example of a similar case here.

Related

Helm complicated array variable

In values.yaml I have defined
data_fusion:
tags:
- tag1
- tag2
- tag3
instances:
- name: test
location: us-west1
creating_cron: #once
removing_cron: #once
config:
type: Developer
displayName: test
dataprocServiceAccount: 'my#project.iam.gserviceaccount.com'
pipelines:
- name: test_rep
pipeline: '{"my_json":{}}'
- name: test222
location: us-west1
creating_cron: #once
removing_cron: #once
config:
type: Basic
displayName: test222
dataprocServiceAccount: 'my222#project.iam.gserviceaccount.com'
pipelines:
- name: test_rep222
pipeline: '{"my_json222":{}}'
- name: test_rep333
pipeline: '{"my_json333":{}}'
- name: test_rep444
pipeline: '{"my_json444":{}}'
You guys can see I have 3 tags and 2 instances. The first instance contains 1 pipeline, the second instance contains 3 pipelines.
I want to pass tags and instances to my yaml file:
another_config: {{ .Values.blabla.blablabla }}
data_fusion:
tags:
- array of tags should be here
instances:
- array of instances (and associated pipelines) should be here
Or just simply
another_config: {{ .Values.blabla.blablabla }}
data_fusion:
{{.Whole.things.should.be.here}}
Could you guys please help? Since I'm new to helm so I don't know how to pass the complicated array (or the whole big section of yaml).
Helm includes an underdocumented toYaml function that converts an arbitrary object to YAML syntax. Since YAML is whitespace-sensitive, it's useful to note that toYaml's output starts at the first column and ends with a newline. You can combine this with the indent function to make the output appear at the correct indentation.
apiVersion: v1
type: ConfigMap
metadata: { ... }
data:
data_fusion: |-
{{ .Values.data_fusion | toYaml | indent 4 }}
Note that the last line includes indent 4 to indent the resulting YAML block (two spaces more than the previous line), and that there is no white space before the template invocation.
In this example I've included the content as a YAML block scalar (the |- on the second-to-last line) inside a ConfigMap, but you can use this same technique anywhere you've configured complex settings in Helm values, even if it's Kubernetes settings for things like resource constraints or ingress paths.

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 }}

Setting a list to a field in Helm

I have the following in my values.yaml
router:
env:
- name: JSON_LOGGING
value: True
In my Deployment I would simply like to set this list to the env field like so:
spec:
containers:
# ..
env: {{ $.Values.router.env }}
However, it appears that this produces an incorrect YAML file:
Error: UPGRADE FAILED: YAML parse error on translation/templates/translation-router.yaml: error converting YAML to JSON: yaml: line 35: did not find expected ',' or ']'
Is there a way to make this work?
You need to inline part of your configuration using toYaml.
spec:
containers:
# ..
env:
{{- toYaml .Values.rounter.env | nindent 6 }}

How to get values in helmfile

bases:
- common.yaml
releases:
- name: controller
values:
- values/controller-values.yaml
hooks:
- events: [ "presync" ]
....
- events: [ "postsync" ]
.....
common.yaml
environments:
default:
values:
- values/common-values.yaml
common-values
a:b
I want to move the values of the hooks to file when I added it to common.values it worked but I want to add it to different files and not to the common, so I tried to add base
bases:
- common.yaml
- hooks.yaml
releases:
- name: controller
values:
- values/controller-values.yaml
hooks:
{{ toYaml .Values.hooks | indent 6 }}
hooks.yaml
environments:
default:
values:
- values/hooks-values.yaml
hooks-values.yaml
hooks:
- events: [ "presync" ]
....
- events: [ "postsync" ]
.....
but I got an error
parsing: template: stringTemplate:21:21: executing "stringTemplate" at <.Values.hooks>: map has no entry for key "hooks"
I tried also to change it o
hooks:
- values/hooks-values.yaml
and I got an error
line 22: cannot unmarshal !!str values/... into event.Hook
I think the first issue is when specifying both common.yaml and hooks.yaml under bases:, they are not merged properly. Since they provide same keys, most probably the one that is included later under bases: overrides the other.
To solve that you can use a single entry in bases in helmfile:
bases:
- common.yaml
and then add your value files to common.yaml:
environments:
default:
values:
- values/common-values.yaml
- values/hooks-values.yaml
I don't claim this is best practice, but it should work :)
The second issue is that bases is treated specially, i.e. helmfile.yaml is rendered before base layering is processed, therefore your values (coming from bases) are not available at a point where you can reference them directly in the helmfile. If you embedded environments directly in the helmfile, it would be fine. But if you want to keep using bases, there seems to be couple of workarounds, and the simplest seemed to be adding --- after bases as explained in the next comment on the same thread.
So, a working version of your helmfile could be:
bases:
- common.yaml
---
releases:
- name: controller
chart: stable/nginx
version: 1.24.1
values:
- values/controller-values.yaml
hooks:
{{ toYaml .Values.hooks | nindent 6 }}
PS: chart: stable/nginx is just chosen randomly to be able to helmfile build.

Escaping helm yml for deployment

I am trying to figure out how to escape these pieces of a yml file in order to use with helm.
- name: SYSLOG_TAG
value: '{{ index .Container.Config.Labels "io.kubernetes.pod.namespace" }}[{{ index .Container.Config.Labels "io.kubernetes.pod.name" }}]'
- name: SYSLOG_HOSTNAME
value: '{{ index .Container.Config.Labels "io.kubernetes.container.name" }}'
The yml file is a DaemonSet for sending logs to papertrail with instructions here for a standard kubernetes manual deployment https://help.papertrailapp.com/kb/configuration/configuring-centralized-logging-from-kubernetes/ . Here is a link to the full yml file https://help.papertrailapp.com/assets/files/papertrail-logspout-daemonset.yml .
I found some answers on how to escape the curly braces and quotes, but still can't seem to get it to work. It would be easiest if there was some way to just get helm to not evaluate each entire value.
The last I tried was this, but still results in an error.
value: ''"{{" index .Container.Config.Labels \"io.kubernetes.pod.namespace\" "}}"["{{" index .Container.Config.Labels \"io.kubernetes.pod.name\" "}}"]''
- name: SYSLOG_HOSTNAME
value: ''"{{" index .Container.Config.Labels \"io.kubernetes.container.name\" "}}"''
This is the error:
Error: UPGRADE FAILED: YAML parse error on templates/papertrail-logspout-daemonset.yml: error converting YAML to JSON: yaml: line 21: did not find expected key
I can hardcode values for both of these and it works fine. I don't quite understand how these env variables work, but what happens is that logs are sent to papertrail for each pod in a node with the labels from each of those pods. Namespace, pod name, and container name.
env:
- name: ROUTE_URIS
value: "{{ .Values.backend.log.destination }}"
{{ .Files.Get "files/syslog_vars.yaml" | indent 13 }}
Two sensible approaches come to mind.
One is to define a template that expands to the string {{, at which point you can use that in your variable expansion. You don't need to specially escape }}.
{{- define "cc" }}{{ printf "{{" }}{{ end -}}
- name: SYSLOG_HOSTNAME
value: '{{cc}} index .Container.Config.Labels "io.kubernetes.container.name" }}'
A second approach, longer-winded but with less escaping, is to create an external file that has these environment variable fragments.
# I am files/syslog_vars.yaml
- name: SYSLOG_HOSTNAME
value: '{{ index .Container.Config.Labels "io.kubernetes.container.name" }}'
Then you can include the file. This doesn't apply any templating in the file, it just reads it as literal text.
env:
{{ .Files.Get "files/syslog_vars.yaml" | indent 2 }}
The important point with this last technique, and the problem you're encountering in the question, is that Helm reads an arbitrary file, expands all of the templating, and then tries to interpret the resulting text as YAML. The indent 2 part of this needs to match whatever the rest of your env: block has; if this is deep inside a deployment spec it might need to be 8 or 10 spaces. helm template will render a chart to text without trying to do additional processing, which is really helpful for debugging.