Helm: override values from dependency chart - kubernetes-helm

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

Related

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

Helm adds release name to dependent charts

I have few dependencies like this
dependencies:
- name: some-chart
version: "1.2.3"
repository: "file://../some-chart"
And I install my chart like so
helm install my-chart .
However, it adds dependent charts my release name. so for example server-0 pod deploys like this
my-chart-some-chart-server-0
If I only install the dependent chart on its own, for example helm install some-chart ../some-chart it deploys 'server-0' like this
some-chart-server-0
Is there a way to deploy dependent charts without adding release name as its intended?
Some time has passed but this may be important information for other users -
As David has explained this can not be changed by helm and comes from the templates.
If you can find the following in the templates
{{- if .Values.fullnameOverride -}}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
then you can use the fullnameOverride for your needs.
You can override the values of the dependency by adding in the parent's (my-chart) values.yaml file the following:
some-chart:
fullnameOverride: some-chart
As a result, the parent's chart name (my-chart) will be dropped from the names of the resources and you will see your server-0 pod as some-chart-server-0 instead of as my-chart-some-chart-server-0.
This naming convention is part of the templates. Helm doesn't add it itself, and you can't change it without changing the templates (or doing complex post-processing).
If you run helm create, it creates a lot of infrastructure for you. Things like the Deployment are generally named
name: {{ include "<CHARTNAME>.fullname" . }}
That template, in turn, is also part of the generated _helpers.tpl file (trimmed slightly)
{{- define "<CHARTNAME>.fullname" -}}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
So if you helm install some-chart ../some-chart, the release name (the first some-chart argument) matches the chart name, and you get the "short" form of just the release name; but if you helm install other-chart ../some-chart, you'll get the release-name-chart-name-suffix format.
This has nothing to do with it being a dependency, only the name you're using to install the release. Compare:
helm install some-chart ../some-chart # using its "normal" name
helm install foo ../some-chart # using some other name
helm install my-chart . # "normal" name of parent, not dependency
helm install some-chart . # "normal" name of dependency, not parent
This last case should be interesting: if your parent chart uses the same convention, you will actually see names like some-chart-my-chart-deployment, but the some-chart dependency will see the release and chart names match and so within that dependency you'll just see some-chart-foo.

Recommended way to add features to a 3rd party helm chart?

currently we're adding features to 3rd party helm charts we're deploying (for example - in prometheus we're adding an authentication support as we use nginx ingress controller).
Obviously, this will cause us headaches when we want to upgrade those helm charts, we will need to perform "diffs" with our changes.
What's the recommended way to add functionality to existing 3rd party helm charts? Should i use umbrella charts and use prometheus as a dependency? then import value from the chart? (https://github.com/helm/helm/blob/master/docs/charts.md#importing-child-values-via-requirementsyaml)
Or any other recommended way?
-- EDIT --
Example - as you can see, i've added 3 nginx.ingress.* annotations to support basic auth on prometheus ingress resource - of course if i'll upgrade, i'll need to manually add them again, which will cause problems
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
{{- if .Values.prometheus.ingress.annotations }}
annotations:
{{ toYaml .Values.prometheus.ingress.annotations | indent 4 }}
{{- end }}
{{- if .Values.alertmanager.ingress.nginxBasicAuthEnabled }}
nginx.ingress.kubernetes.io/auth-realm: "Authentication Required - ok"
nginx.ingress.kubernetes.io/auth-secret: {{ template "prometheus-operator.fullname" . }}-prometheus-basicauth
nginx.ingress.kubernetes.io/auth-type: "basic"
{{- end }}
name: {{ $serviceName }}
labels:
app: {{ template "prometheus-operator.name" . }}-prometheus
{{ include "prometheus-operator.labels" . | indent 4 }}
{{- if .Values.prometheus.ingress.labels }}
{{ toYaml .Values.prometheus.ingress.labels | indent 4 }}
{{- end }}
spec:
rules:
{{- range $host := .Values.prometheus.ingress.hosts }}
- host: {{ . }}
http:
paths:
- path: "{{ $routePrefix }}"
backend:
serviceName: {{ $serviceName }}
servicePort: 9090
{{- end }}
{{- if .Values.prometheus.ingress.tls }}
tls:
{{ toYaml .Values.prometheus.ingress.tls | indent 4 }}
{{- end }}
{{- end }}
I think that might answer your question.
Subcharts and Globals
Requirements
Helm Dependencies
This led me to find the specific part I was looking for, where the parent chart can override sub-charts by specifying the chart name as a key in the parent values.yaml.
In the application chart's requirements.yaml:
dependencies:
- name: jenkins
# Can be found with "helm search jenkins"
version: '0.18.0'
# This is the binaries repository, as documented in the GitHub repo
repository: 'https://kubernetes-charts.storage.googleapis.com/'
Run:
helm dependency update
In the application chart's values.yaml:
# ...other normal config values
# Name matches the sub-chart
jenkins:
# This will be override "someJenkinsConfig" in the "jenkins" sub-chart
someJenkinsConfig: value
I would either fork and handle integrating the changes when you upgrade/rebase, or if possible disable the ingress elements for those you want to customise via the values.yaml file. Then create your own ingress instances manually with the customisations you need in another custom chart, and provide it the references it needs from the prometheus chart as normal values.yaml inputs.
Obviously this approach has it's limitations, if the customisations are too tightly coupled to the chart it might not be possible to split them out.
Hope this helps.

Conditionally deploying a secret based on --set parameter

I have a Helm chart that I am deploying to Azure Kubernetes Service, and minikube for development purposes.
When deploying to minikube, I need to add a secret so the cluster can speak with my Azure Container Registry. This is not necessary when I'm deploying to AKS.
Is there any way I can specify whether or not to include the secret through a --set value with helm install, or do I have to set up different helm charts?
You can put anything you want inside a Go text/template conditional block, even whole Kubernetes resources.
# templates/some-secret.yaml
{{ if .Values.theSecret }}
apiVersion: v1
kind: Secret
metadata:
name: {{ template "some.name" . }}-some-secret
labels:
{{ template "some.labels" . | indent 4 }}
data:
theSecret: {{ .Values.theSecret | b64enc }}
{{ end }}
Or, if you already have some shared Secret, you can make individual values conditional
data:
someValue: {{ .Values.someValue | b64enc }}
{{- if .Values.theSecret }}
theSecret: {{ .Values.theSecret | b64enc }}
{{- end }}
As the chart author you need to write this into the chart. If you're using a third-party chart, it's up to the chart author to provide this functionality.

How to reference a value defined in a template in a sub-chart in helm for kubernetes?

I'm starting to write helm charts for our services.
There are two things I'm not sure how they are supposed to work or what to do with them.
First: the release name. When installing a chart, you specify a name which helm uses to create a release. This release name is often referenced within a chart to properly isolate chart installs from each other? For example the postgres chart contains:
{{- define "postgresql.fullname" -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
Which is then used for the service:
metadata:
name: {{ template "postgresql.fullname" . }}
It does look like "myrelease-postgresql" in the end in kubernetes.
I wonder what a good release name is? What is typically used for this? A version? Or some code-name like the ubuntu releases?
Second: referencing values.
My chart uses postgresql as a sub-chart. I'd like to not duplicate the way the value for the name of the postgresql service is created (see snipped above).
Is there a way I can reference the service name of a sub-chart or that template define {{ template "postgresql.fullname" . }} in the parent chart? I need it to pass it into my service as database host (which works if I hardcode everything but that cannot be the meaning of this).
I tried:
env:
- name: DB_HOST
value: {{ template "mychart.postgresql.fullname" . }}
But that lead into an error message:
template "mychart.postgresql.fullname" not defined
I've seen examples of Charts doing similar things, like the odoo chart. But in here that logic how the postgresql host name is created is copied and an own define in the template is created.
So is there a way to access sub-chart names? Or values or template defines?
Thanks!
Update after some digging:
According to Subcharts and Globals the templates are shared between charts.
So what I can do is this:
In my chart in _helpers.tpl I add (overwrite) the postgres block:
{{- define "postgresql.fullname" -}}
{{- $name := .Values.global.name -}}
{{- printf "%s-%s" $name "postgresql" | trunc 63 | trimSuffix "-" -}}
{{- end -}}
So this value is used when the sub-chart is deployed. I cannot reference all values or the chart name in here as it will be different in the sub-chart - so I used a global value.
Like this I know the value of the service that is created in the sub-chart.
Not sure if this is the best way to do this :-/
Are you pulling in postgresql as a subchart of your chart (via your chart's requirements.yaml)? If so, both the postgresql (sub) chart and your chart will have the same .Release.Name - thus, you could specify your container's environment as
env:
- name: DB_HOST
value: {{ printf "%s-postgresql" .Release.Name }}
if you override postgresql's name by adding the following to your chart's values.yaml:
postgresql:
nameOverride: your-postgresql
then your container's env would be:
env:
- name: DB_HOST
value: {{ printf "%s-%s" .Release.Name .Values.postgresql.nameOverride }}
You can overwrite the values of the subchart with the values of the parent chart as described here:
https://helm.sh/docs/chart_template_guide/subcharts_and_globals/
I don't think it's possible (and it also doesn't make sense) to override the template name of the subchart.
What I would do is define the database service name in the .Values files both in the parent and sub charts and let helm override the one in the subchart - that way you will always have the database name in the parent chart. This would however mean that the service name of the database should not be {{ template "name" . }}, but something like {{ .Values.database.service.name }}
mychart/.Values
mysubchart:
service:
name: my-database
mychart/templates/deployment.yaml
env:
- name: DB_HOST
value: {{ .Values.mysubchart.service.name }}
mychart/charts/mysubchart/.Values
service:
name: my-database
mychart/charts/mysubchart/templates/service.yaml:
apiVersion: v1
kind: Service
metadata:
name: {{ .Values.service.name }}
Another way is to use global chart values, also described in https://helm.sh/docs/chart_template_guide/subcharts_and_globals/
For values in the helper.tpl instead of values.yaml
To access a value from a chart you do the following:
{{ template "keycloak.fullname" . }}
To access a value from a sub chart
{{ template "keycloak.fullname" .Subcharts.keycloak }}
You could import values from a sub chart as described here: https://helm.sh/docs/topics/charts/#importing-child-values-via-dependencies.
However there is a caveat. This works not for values defined at the root level in the values.yaml.
See this issue for more information: https://github.com/helm/helm/issues/9817