trigger pod restart on configmap change - kubernetes-helm

I have a configmap file defined as follows
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-dashboard-cm-conf
namespace: {{ .Release.Namespace }}
data:
{{ (tpl (.Files.Glob "conf/*").AsConfig . ) | indent 2 }}
As you can see above, it is taking up the content of the "conf" folder as a data.
Everything works fine, however the issue is observed when i am trying to implement "annotations" to trigger a "POD-restart" with the below lines in my "deployment file.
annotations:
checksum/config-map: {{ include (print .Template.BasePath "/dashboard-conf-map.yaml") . | sha256sum }}
The POD is not getting restarted, even when content of "conf" folder is changed && a "helm upgrade" is performed.
If i use a simple configmap with data defined as below, a change in parameter and "helm upgrade" does result in POD-restart
data:
parameter1: testparam1
parameter2: testparam2
I have the following question in here
Is there a way to perform checksum for the folder.
Is there a way get the output of linux-command like below in the configmap.
find dashboard/conf/ -type f -exec md5sum {} \; |md5sum
Can we perform checksum for a non-YAML file.
annotations:
checksum: {{ include (print .Template.BasePath "/logback-spring.xml") . | sha256sum }}
I get the below error
Error: YAML parse error on chart-2/charts/dashboar/templates/conf1/logback-spring.xml: error unmarshaling JSON: while decoding JSON: json: cannot unmarshal string into Go value of type releaseutil.SimpleHead
Can we perform checksum on file one directory above the ".Template.BasePath", i tried below combination all of them result in error.
checksum/config: {{ include (print .BasePath "../conf/values1.yaml") . | sha256sum }}
checksum/config: {{ include (print .Template.BasePath "/../../conf/values1.yaml") . | sha256sum }}
checksum/config: {{ include (print .Template.BasePath "/../conf/values1.yaml") . | sha256sum }}
error calling include: template: no template "chart-2/charts/dashboard/templates../conf/values1.yaml" associated with template "gotpl"
error calling include: template: no template "chart-2/charts/dashboard/templates/../conf/values1.yaml" associated with template "gotpl"
error calling include: template: no template "chart-2/charts/dashboard/templates/../../conf/values1.yaml" associated with template "gotpl"

The include template function is a Helm extension that executes a named template, just like the standard template directive, but returns the template's content as a string. It has nothing to do with reading files.
To read back files, you need to use the top-level .Files object. That specifically comes with a caveat that it cannot read files inside the chart's templates directory; prefixing file names with .Template.BasePath will not work, and you need to move the included files somewhere else.
Let's say you do create a subdirectory conf inside your main chart directory:
Chart.yaml
values.yaml
conf/
logback.xml
templates/
configmap.yaml
Many of the functions you list here – .Files.Get, .Files.Glob.AsConfig, tpl – return strings, so you can combine them together. For example, you can compute a checksum for the rendered content of the ConfigMap as:
annotations:
checksum/config-map: {{ (tpl (.Files.Glob "conf/*").AsConfig . ) | sha256sum }}
You could do it on a single non-YAML file if you wanted, too: .Files.Get returns a string, so
.Files.Get "conf/logback-spring.xml" | sha256sum
The root path for .Files.Get is the root of the chart. You can retrieve any file not in the templates directory, but you can't reach outside the chart.

If you want to do this with sub-chart.
kind: <ResourceKind> # Deployment, StatefulSet, etc
spec:
template:
metadata:
annotations:
checksum/config: {{ include ("mylibchart.configmap") . | sha256sum }}
Another option is https://github.com/stakater/Reloader
You can use regex to select the config based on this PR https://github.com/stakater/Reloader/pull/314

Related

Helm default value throws error converting YAML to JSON

I have a basic kubernetes helm template like below
apiVersion: v1
kind: ConfigMap
metadata:
name: test
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/version: {{ .Chart.AppVersion }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/instance: {{ .Release.Name }}
data:
config.tpl: |
{{- default ((tpl .Values.configTpl .) | indent 4) (tpl (.Files.Get "files/config.tpl") . | indent 4) -}}
and the values.yml file
configTpl: |
{{ x=8gwifi.org }}
When i apply the helm chart it throw me an error
❯ helm upgrade mychart . --namespace=test --create-namespace --debug
upgrade.go:142: [debug] preparing upgrade for mychart
Error: UPGRADE FAILED: YAML parse error on 8gwifi.org-test/templates/configmap-logfilegen.yaml: error converting YAML to JSON: yaml: line 11: did not find expected comment or line break
helm.go:84: [debug] error converting YAML to JSON: yaml: line 11: did not find expected comment or line break
I tried different configuration
config.tpl: |
{{- default (tpl .Values.configTpl . | indent 4) (tpl (.Files.Get "files/config.tpl") . | indent 4) -}}
still resulting in same error, Is there a way to specify a config value if none is passed then used the hardcoded one
I'm sure it's an YAML syntx issue couldn't figure it out checked all cases
Based on David suggestion
Template debug is showing this
data:
config.tpl: |-
x := 8gwifi.org
y := "functions"
I can cleary see y is not indent and throwing YAML syntax error, not sure how to fix this
This is the updated definition
data:
config.tpl: |-
{{ (tpl .Values.configTpl . | indent 4) | default (tpl (.Files.Get "files/config.tpl") . | indent 4) -}}
values.yml
configTpl: |
x := "8gwifi.org"
y := "function"
You're hitting problems with whitespace in the first line of the block scalar. You should check two things:
The template block containing indent must not itself be indented, it must start at the first column of its line; and
The template block containing indent must not have a - inside the opening curly braces.
{{- $configTpl := .Values.configTpl | default (.Files.Get "tiles/config.tpl") }}
config.tpl: |
{{ tpl $configTpl . | indent 4 }}
The templating language isn't really aware of YAML syntax as it runs. If you have spaces in front of the indent line, they will get emitted, and then indent adds its own leading space, resulting in the last output you get where the first line is indented extra. The - whitespace control marker will also consume the preceding newline, resulting in the first line of the output being on the same line as the YAML block scalar marker.

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

Helm's v3 Example Doesn't Show Multi-line Properties. Get YAML to JSON parse error

In Helm's v3 documentation: Accessing Files Inside Templates, the author gives an example of 3 properties (toml) files; where each file has only one key/value pair.
The configmap.yaml looks like this. I'm only adding one config.toml for simplicity.
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-config
data:
{{- $files := .Files }}
{{- range tuple "config.toml" }}
{{ . }}: |-
{{ $files.Get . }}
{{- end }}
This works fine, until I add a second line to the config.toml file.
config.toml
replicaCount=1
foo=bar
Then I get an Error: INSTALLATION FAILED: YAML parse error on deploy/templates/configmap.yaml: error converting YAML to JSON: yaml: line 9: could not find expected ':'
Any thoughts will be appreciated.
Thanks
Helm will read in that file, but it is (for good or bad) a text templating engine. It does not understand that you are trying to compose a YAML file and thus it will not help you. That's actually why you will see so many, many templates in the wild with {{ .thing | indent 8 }} or {{ .otherThing | toYaml }} -- because you need to help Helm know in what context it is emitting the text
Thus, in your specific case, you'll want the indent filter with a value of 4 because your current template has two spaces for the key indent level, and two more spaces for the value block scalar
data:
{{- $files := .Files }}
{{- range tuple "config.toml" }}
{{ . }}: |-
{{ $files.Get . | indent 4 }}
{{/* notice this ^^^ template expression is flush left,
because the 'indent' is handling whitespace, not the golang template itself */}}
{{- end }}
Also, while this is the specific answer to your question, don't overlook the .AsConfig section on that page which seems much more likely to be what you really want to happen, and requires less indent math

Helm: override values from dependency chart

I'm using a chart it's using other chart as dependency.
Its chart.yaml file is:
annotations:
category: Infrastructure
apiVersion: v2
appVersion: 3.7.0
dependencies:
- name: common
repository: https://charts.bitnami.com/bitnami
tags:
- bitnami-common
version: 1.x.x
...
It's using this dependecy into its templates like:
apiVersion: v1
kind: Service
metadata:
...
labels: {{- include "common.labels.standard" . | nindent 4 }}
app.kubernetes.io/component: zookeeper
{{- if .Values.commonLabels }}
{{- include "common.tplvalues.render" ( dict "value" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- end }}
...
As you can see it's using:
labels: {{- include "common.labels.standard" . | nindent 4 }}
How can I override those values inherited from common.
The Bitnami Common Library Chart is a library chart: it doesn't provide any Kubernetes resources of its own, just a library of template functions you can call (with include or template). That also means it doesn't have its own set of values in the way Helm dependency charts normally do; it uses whatever .Values are in the object you pass to the template.
The implementation of common.labels.standard is pretty straightforward; it provides a set of standard labels that almost every chart should have. You don't usually need to edit these, and you can't change their outputs without copying and pasting the template contents.
Note that one consequence of this is that, if you have a parent chart and a subchart that both include "common.labels.standard" ., they will get different values. .Release.Name will be the same for both, but .Chart.Name will depend on the specific chart being installed (parent or dependency), and in the subchart, .Values will be narrowed to that subchart's settings in the top-level values.
If you need to add labels, this change is easy, and you demonstrate it above. Helm's general operation is to run the template engine naïvely to produce a text document, then hope it's a valid YAML file. If you want additional labels, just include them in the template.
metadata:
labels:
{{-/* the generated labels from the Common chart */}}
{{- include "common.labels.standard" . | indent 4 }}
{{-/* and then any additional labels (correctly indented) */}}
example.com/additional-label: is-present

Create configmap with outside yaml files for kubernetes

I'm quite new for kubernetes. I am trying to create configmap with using yaml file which was user defined.
helm upgrade --install test --namespace test --create-namespace . -f xxx/user-defined.yaml
user can add any yaml file with using 'f' option.
for example;
cars.yaml
cars:
- name: Mercedes
model: E350
So command will be;
helm upgrade --install test --namespace test --create-namespace . -f xxx/cars.yaml
My question is, I want to create configmap which is name 'mercedes-configmap'
I need to read that values from cars.yaml and create automaticaly configmap with name and data of cars.yaml
Update,
I've created below configmap template;
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Values.cars.name }}-configmap
data:
{{- range .Files }}
{{ .Files.Get . | toYaml | quote }}
{{- end }}
The only issue that I faced, I couldnt get the whole file data.
Welcome to the community!
I have created a helm template for configmap. It works this way: you can pass configmap name - name and file name - fname where data is stored and/or it can read files from a specific folder.
Please find the template (first 3 lines are commented, it's two working implementations of logic to check values existing):
{{/*
{{ if not (or (empty .Values.name) (empty .Values.fname)) }}
*/}}
{{ if and (not (empty .Values.name)) (not (empty .Values.fname)) }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Values.name }}-configmap
data:
{{- ( .Files.Glob .Values.fname ).AsConfig | nindent 2 }}
---
{{ end }}
{{ $currentScope := .}}
{{ range $path, $_ := .Files.Glob "userfiles/*.yaml" }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ base $path | trimSuffix ".yaml" }}-configmap
data:
{{- with $currentScope}}
{{ base $path }}: |
{{- ( .Files.Get $path ) | nindent 4 }}
{{- end }}
---
{{ end }}
First part of the template checks if configmap name and file name are set and if so, it renders it. Second part goes to userfiles directory and gets all yamls within.
You find github repo where I shared file examples and configmap.
To render the template with cars2.yaml and with/without files within userfiles directory:
helm template . --set name=cars2 --set fname=cars2.yaml
To render the same template with only files in userfiles directory:
helm template .
P.S. helm v3.5.4 was used
Useful links:
Accessing files in helm
Flow control
File path functions