Helm dependencies tags issue - kubernetes-helm

I have the following value in values.yaml, and changes are made on the deployment side depending on the situation.
test:
test1: false
default: true
ingress-nginx:
enabled: true
tags:
test.default: true
I don't want the dependencies in the Chart.yaml file to install when I set test1 to true. But no matter what I did it didn't work.
dependencies:
- name: ingress-nginx
version: "4.0"
repository: https://kubernetes.github.io/ingress-nginx
condition: ingress-nginx.enabled
tags:
- test.default: true
- test.test1: false

Helm doesn't support Boolean logic in the dependency setup. The only supported conditions are:
If dependencies: contains a condition:, that names a path into the values structure, and if it is true then the dependency is installed. If more than one path is specified in a comma-separated string, the first path that exists is used; if none of the paths exist, go to 2.
Otherwise, if dependencies: contains tags: and the values do as well, then if any of the values' tags matching the dependencies' tags are true, install the dependency.
In both cases, the logic is "if something is true then install the dependency". There is no way to tell Helm to install a dependency only if a value is false. In your example, since there's a condition:, that will usually take precedence (unless the ingress-nginx: { enabled: } values doesn't exist at all).
The easiest thing to do here is just use that enabled value. There are multiple sources of values, including the helm install --set option and additional values files passed via helm install -f; the chart's values.yaml file is used mostly as defaults. So you can set this dependency to "on" in the chart's values
# values.yaml
ingress-nginx:
enabled: true
but then have an add-on "profile" values that disables it
# test1.yaml
ingress-nginx:
enabled: false
and specify that additional values file when you install the chart
helm install myapp . -f test1.yaml
If you did want to use tags: here then you'd need to invert the value of the tag. In the dependencies: section you'd specify the inverted tag name as a string, and omit the condition:
# Chart.yaml
dependencies:
- name: ingress-nginx
tags:
- not-test1
# no condition:
In the top-level values file, you'd specify some default for it, probably "on"
# values.yaml
tags:
not-test1: true
Then when you install the chart, you can disable this. (An override values file as in the previous example would also work.)
helm install myapp . --set tags.not-test1=false

Related

How to override values from value.yaml file into value.dev.yaml file

I have some Helm value files.
There are value.yaml, value.dev.yaml, value.test.yaml, ... file.
In value.dev.yaml:
env:
"Environment" "development"
For some parameters in value.yaml file, I expected they override or insert them into pod parameters while deployment.
If I set up them into each value.dev.yaml, value.test.yaml,... it works with helm upgrade --install --set env.parameter=$variable
Now I want to define all variables in value.yaml file and expect them insert (override) them in to pods while deployment.
In value.yaml file :
env:
"Appconfig": "dev"
I'd like to combine them while deployment:
env:
"Environment": "development"
"Appconfig": "dev"
Apreciate your help !
You can specify the --values/-f flag multiple times. The priority will be given to the last (right-most) file specified. For example, if both myvalues.yaml and override.yaml contained a key called 'Test', the value set in override.yaml would take precedence:
$ helm install -f myvalues.yaml -f override.yaml myredis ./redis
Ref Helm Install Doc

helm chart - value file variables

I am using a helm chart (with sub-charts) to deploy my application.
I am using a value file for setting values.
I am looking a way to set variables in my value file (or any other place) that will be valid for my value file.
I have some sections (services) in my value files that I need to use the same value in it
so I am looking for a variable in my value file.
Is there any way that I can use variables for my value file?
Thx
Helm on its own can't do this.
If you control all of the charts and subcharts, you can allow specific values to have embedded Go templating. Helm includes a tpl extension function that will let you render an arbitrary string as a template. So if you have values
global:
commonKey: some value
otherKey: '{{ .Values.global.commonKey }}'
then you can render
- name: OTHER_KEY
value: '{{ tpl .Values.otherKey . }}'
But, you have to use tpl every place you access the key value(s); if you don't control the subcharts you may not be able to do this.
Higher-level tools may also let you do this. I'm familiar in particular with Helmfile which lets you declare multiple Helm charts and their settings, but also lets you use almost-Helm templating in many places. So your helmfile.yaml could specify:
environments:
default:
# These values are available when rendering templates in this file
values:
- commonKey: some value
releases:
- name: my-service
namespace: my-service
chart: ./charts/my-service
values:
# List items can be file names or YAML dictionaries.
# If it's a dictionary, arbitrary nested values.yaml content.
# If it's a *.yaml.gotmpl file name, templating is applied to the file.
- otherKey: '{{ .Values.commonKey }}'
yetAnotherKey: '{{ .Values.commonKey }}'
- ./my-service.yaml.gotmpl
Helmsman is simpler, but can only set chart values from environment variables; but I believe you can reference the same environment variable in different setString: options. You could also do something similar with the Terraform Helm provider, using Terraform's native expression syntax, particularly if you're already familiar with Terraform.

override config map in helm chart during azure devops deploy

We are using helm charts templates for deployment to kube and Azure devops for CI/CD.in my values.yaml data in below section will change as per environment and saved as config map in pod.
My question is how can I update it during deployment in azure pipeline. We are using Helm upgrade task OR any other way to handle it better.
environment:
enabled: true
env:
enabled: false
internalConfigMap:
enabled: true
**data:
AZ_DIRECTORY: xxx
MODEL_ID_SVM: xxx
MODEL_ID_MULTI: xxx
MODEL_THRESHOLD_SVM: 'xx'
SINGLE_ACC_ENDPT: 'xx'
MODEL_WT_SVM: 'xx'**
here is deployment task:(ignore indentation)
task: HelmDeploy#0
displayName: Helm upgrade
inputs:
command: upgrade
chartType: Name
chartName: chart/$(chartname)
releaseName: $(chartname)-${{ parameters.CI_ENVIRONMENT_SLUG }}
namespace: $(NAMESPACE)
connectionType: Azure Resource Manager
#azureSubscriptionEndpoint: ${{ variables.AZ_SUBSCRIPTION }}
#azureResourceGroup: $(AKS_RESOURCE_GROUP)
# kubernetesCluster: $(K8S_CLUSTER)
install: true
waitForExecution: true
useClusterAdmin: true
overrideValues: |
template.image.tag=$(imagetag)
Option 1: One value file per environment
If you have one values.yaml per environment (environment1-values.yaml, environment2-values.yaml etc) you can refer to different files for each stage in your pipeline.
The Helm Upgrade command accepts the parameter valueFile which you can use to point to the correct values.yaml for the environment you are deploying to
(Optional) Specify values in a YAML file or a URL. For example,
specifying myvalues.yaml will result in helm install
--values=myvals.yaml
Option 2: Override values on deployment
The Helm Upgrade command accepts the parameter overrideValues by which you can pass values directly to helm:
(Optional) Set values on the command line. You can specify multiple
values by separating values with commas. For example,
key1=val1,key2=val2. You can also specify multiple values by
delimiting them with newline as so: key1=val1 key2=val2 Please note
that if you have a value which itself contains newlines, use the
valueFile option, else the task will treat the newline as a delimiter.
The task will construct the helm command by using these set values.
For example, helm install --set key1=val1 ./redis
In your case this would mean
overrideValues: template.image.tag=$(imagetag),environment.internalConfigMap.data.AZ_DIRECTORY=xxx,environment.internalConfigMap.data.MODEL_ID_SVM=xxx

Update nested array value in yaml with yq

Given a yaml file (helmfile) like the following
releases:
- chart: ../charts/foo
name: foo
namespace: '{{ .Values.stack }}'
values:
- ../config/templates/foo-values.yaml.gotmpl
set:
- name: image.tag
value: 22
- name: replicas
value: 1
- chart: ../charts/bar
name: bar
namespace: '{{ .Values.stack }}'
values:
- ../config/templates/bar-values.yaml.gotmpl
set:
- name: image.bar_proxy.tag
value: 46
- name: image.bar.tag
value: 29
- name: replicas
value: 1
I'm trying to figure out a clean way to update a specific image tag. For example, I'd like to update image.bar_proxy.tag from 46 to 51.
I have the following, which does the job, but it requires that you know the exact index of the array item:
yq -y '.releases[] |= if .name=="bar" then .set[0].value |= 51 else . end' helmfile-example.yaml
So if the array order were to change at some point this would break.
A preferred solution would be: "update image.bar_proxy.tag value from 46 to 51 where set[].name==image.bar_proxy.tag". Any ideas on how to achieve a more specific conditional selection like this?
FYI our yq version:
$ yq --version
yq 2.10.0
You can use the following filter to make it work. It works by dynamically selecting the index of the object where your tag exists. On the selected object .value=51 will update the value as you wanted. You can also use the -i flag to do in-place modification of the original file.
yq -y '.releases[].set |= map(select(.name == "image.bar_proxy.tag").value=51)' yaml
See the underlying jq filter acting on the JSON object at jq-playground
Given the context of using Helmfile, there are a couple of ways you can approach this without necessarily editing the helmfile.yaml. Helmfile allows using the Go text/template language in many places, similarly to the underlying Helm tool, and has some other features that can help.
One of the easiest things you can do is take advantage of values: being a list, and of unknown values generally being ignored. You (or your CI/CD system) can write a separate YAML file that contains just the tags (JSON may be easier to write and is valid YAML)
# tags.yaml
image:
tag: 22
bar: {tag: 29}
bar_proxy: {tag: 46}
and then include this file as an additional file in the helmfile.yaml. (This would be equivalent to using helm install -f with multiple local values files, rather than helm install --set individual values.)
releases:
- name: foo
values:
- ../config/templates/foo-values.yaml.gotmpl
- tags.yaml
# no `set:`
- name: bar
values:
- ../config/templates/bar-values.yaml.gotmpl
- tags.yaml
- replicas: 1
# no `set:`
Helmfile's templating extensions also include env and requiredEnv to read ordinary environment variables from the host system. Helm proper does not have these to try to minimize the number of implicit inputs to a chart, but for Helmfile it's a possible way to provide values at deploy time.
releases:
- name: bar
set:
- name: image.bar_proxy.tag
value: {{ env "BAR_PROXY_TAG" | default "46" }}
- name: image.bar.tag
value: {{ requiredEnv "BAR_TAG" }}

Concourse CI, git tag with constant value

I would like to tag my git commits as they are deployed to the various environments in my concourse pipeline with the name of the environment. For example, in my UAT deployment job, I would like to do something like:
- put: master-resource <-- a git resource
params:
repository: master <-- the resource local directory
tag: 'uat'
force: true <-- replace the tag, if it already exists
tag_only: true
This would seem like a common -or at least simple, thing to do however the value of the 'tag' parameter can only be the path to a file -there is no option to pass a constant/literal value.
I see two possible solutions but none of them seems 'simple' enough:
Create a file myself, but to do that (ideally?) I wish there were some kind of file resource that I could use to create the file.
The last alternative would be to create a custom task, and even there I was struggling to find a way to pass the name of the tag as a parameter.
Any suggestions on what would be the best way to accomplish my goal in the simplest way, or alternatively how to implement options 1 or 2?
Thanks!
The reason that tag takes in a file is so that you can dynamically set the tag of the commit based on information you imply during the course of the pipeline.
So, the best way I can see to do something like this would be workflow #2 that you described above.
So you would want something like this:
- task: generate-git-tag
params:
TAG: {{some-passed-in-tag}}
config:
platform: linux
image_resource:
type: docker-image
source:
repository: ruby
outputs:
- name: tag-file
params:
TAG:
run:
path: /bin/bash
args:
- -c
- |
echo "${TAG}" >> tag-file/tag.txt
- put: master-resource <-- a git resource
params:
repository: master <-- the resource local directory
tag: tag-file/tag.txt
force: true <-- replace the tag, if it already exists
tag_only: true