How to add spaces in helm set switch in kubernetes - kubernetes

How can I add space in --set switch with helm command.
I need spaces between "mongodb://datadog:'${DB_PASSWORD}'#%%host%%:%%port%%", and "replica_check": true, and also between "replica_check": true, and "additional_metrics": ["metrics.commands","tcmalloc","top","collection"]}]'
It gives me error as :
that set cannot end with ,
helm upgrade myservice helm/charts/myservice \
-f helm/charts/chat/values.yaml \
--set "mongodb-replicaset.podAnnotations.ad\.datadoghq\.com/mongodb-replicaset\.instances"='[{"server": "mongodb://datadog:'${DB_PASSWORD}'#%%host%%:%%port%%", "replica_check": true, "additional_metrics": ["metrics.commands","tcmalloc","top","collection"]}]' \
--wait --install```

If you're trying to pass something really complicated like that, it might be easier to package it up in a YAML file and pass it with the helm upgrade -f option.
mongodb-replicaset.podAnnotations.ad.datadoghq.com/mongodb-replicaset.instances: >-
[
{
"server": "mongodb://datadog:passw0rd#%%host%%:%%port%%",
"replica_check": true,
"additional_metrics": ["metrics.commands","tcmalloc","top","collection"]
}
]
(The >- marker is YAML syntax causing the following indented block to be processed as a string, folding newlines into spaces, and trimming leading and trailing newlines.)
Since valid JSON is valid YAML, if you're trying to launch this from a script, you could use your language-native JSON serializer.
import json, os
db_password = os.environ.get('DB_PASSWORD')
instances = [{
"server": "mongodb://datadog:" + db_password + "#%%host:%%port",
"replica_check": True,
"additional_metrics": ["metrics.commands", "tcmalloc", "top", "collection"]
}]
annotations = {
"mongodb-replicaset.podAnnotations.ad.datadoghq.com/mongodb-replicaset.instances": json.dumps(instances)
}
print(json.dumps(annotations))
Once you've done this you can pass the generated file to the helm upgrade -f option. (You don't need to include the chart's own values.yaml file, Helm includes this by default and your values override it.)
helm upgrade myservice helm/charts/myservice \
-f mongo-dd.yaml \
--wait --install
Yet another option is to generate this inside the chart itself. Helm includes an undocumented toJson template function; you can construct objects using the Sprig dict function.
{{- $server := printf "mongodb://datadog:%s#%%%%host%%%%:%%%%port%%%%" .Values.mongodbPassword -}}
{{- $metrics := list "metrics.commands" "tcmalloc" "top" "collection" -}}
{{- $instance := dict "server" $server "replica_check" true "additional_metrics" $metrics -}}
{{- $instances := list $instance -}}
mongodb-replicaset...instances: {{ toJson $instances }}
Your error message suggests your problem isn't the spaces per se, but that helm --set treats commas as separators between multiple key/value pairs. You can backslash-escape the commas
... --set 'mongodb-replicaset..."replica_check": true\, "additional_metrics": ["metrics.commands\,"tcmalloc"\,...]}]'

Related

Helm chart render string with special characters

I want to render following line as string in helm chart. It contain special characters.
text: '{{ template "slack.template.text" . }}'
I found the solution.
text: '{{"{{" }} template "slack.template.text" . {{"}}"}}'
you can use the {{ quote }} function to escape special characters in a string.
example:
text: '{{ quote (template "slack.template.text" . ) }}'
you can refer: https://helm.sh/docs/chart_template_guide/function_list/#quote-and-squote

Helm variables used at custom places

I am not able to reference variable inside a nested variable in Helm. Also, I am not able to do this as nested reference. I want to retrieve all client variables under client name using the value of the client_name variable. How can I do that?
Values.yaml
clients:
client1:
incomigBucket: databucket
outgoingBucket: tempbucket
webURL: http://example.com
client2:
incomingBucket: databucket
outgoingBucket: tempbucket
webURL: http://example.com
I want to store client variables values in one variable and want to use it at different places in my Json file. if I use range function then it create section twice(as I have mentioned 2 clients), is there any thing in Helm I can use which can store these variables dynamically and use it in custom places in json file?
Sample File Section:
"FileConfig": {
"Client1": {
"incomingLocationPath": "s3://{{ .Values.clients.client1.incomingBucket }}/dir1/dir2",
"outgoingLocationPath": "s3://{{ .Values.clients.client1.outgoingBucket }}/dir1/dir2",
},
"Client2": {
"incomingLocationPath": "s3://{{ .Values.clients.client2.incomingBucket }}/dir1/dir2",
"outgoingLocationPath": "s3://{{ .Values.clients.client2.outgoingBucket }}/dir1/dir2",
}
}
I am not entirely sure where you intend to use this snippet. I assume it is inside a configMap. At least, I am not aware of any resource that had FileConfig section. I wouldn't know why it should be JSON either.
The basic pattern could look like this.
fileConfig:
{{- range $client, $config := .Values.clients }}
{{ $client }}:
incomingLocationPath: "s3://{{ $config.incomingBucket }}/dir1/dir2"
outgoingLocationPath: "s3://{{ $config.outgoingBucket }}/dir1/dir2"
{{- end }}
In something like a configMap to create JSON it could look like this.
kind: ConfigMap
apiVersion: v1
metadata:
name: file-config-json
data:
config.json: |
"fileConfig": {
{{- range $client, $config := .Values.clients }}
"{{ $client }}": {
"incomingLocationPath": "s3://{{ $config.incomingBucket }}/dir1/dir2",
"outgoingLocationPath": "s3://{{ $config.outgoingBucket }}/dir1/dir2"
}
{{- end }}
}

How to override a multi-line string with --set in helm install command?

I need to install a helm with a dynamic "project_id" flag on deploy time inside the rawConfig multi-line string
Example values.yaml
sinks:
console:
type: "console"
inputs: ["kafka"]
rawConfig: |
target = "stdout"
encoding.codec = "json"
stackdriver:
type: "gcp_stackdriver_logs"
inputs: ["kafka"]
rawConfig: |
healthcheck = true
log_id = "mirth-channels-log"
project_id = "my_project"
resource.type = "k8s_cluster"
How do I override this value of project_id in rawConfig? I'm trying to do this:
helm install vector helm/vector --values helm/vector-agent/values.yaml -n my-namespace --set sinks.stackdriver.rawConfig='\nlog_id\ =\ "mirth-channels-log"\nproject_id\ =\ "my_project_test"\nresource.type\ =\ "k8s_cluster"\n'
But it does not work
Use second --values like following:
# values_patch.yaml
sinks:
stackdriver:
rawConfig: |
healthcheck = true
log_id = "mirth-channels-log"
project_id = "SOME_OTHER_PROJECT_ID"
resource.type = "k8s_cluster"
$ helm install [...] --values values_patch.yaml
Maybe not the best way, but you can use a separate multiline variable for that:
export MULTILINE_VALUE=$(cat <<EOF
healthcheck = true
log_id = "mirth-channels-log"
project_id = "my_project_test"
resource.type = "k8s_cluster"
EOF
)
helm install vector helm/vector --values helm/vector-agent/values.yaml -n my-namespace \
--set sinks.stackdriver.rawConfig=$MULTILINE_VALUE

Get array of strings from helm config

Ultimately i'm trying to get an array of strings e.g. ['foo', 'bar'] in my js app from my helm config.
./vars/dev/organizations.yaml
...
organizations:
- 'foo'
- 'bar'
...
./templates/configmap.yaml
...
data:
organizations.yaml: |
organizations: "{{ toYaml .Values.organizations | indent 4 }}"
...
./templates/deployment.yaml
...
containers:
args:
- "--organizations-config"
- "/etc/app/cfg/organizations.yaml"
...
index.js
...
const DEFAULT_ORGANIZATIONS_PATH = './vars/local/organizations.yaml'
const program = require('commander')
program
.option(
'--organizations-config <file path>',
'The path to the organizations config file.', DEFAULT_ORGANIZATIONS_PATH)
.parse(process.argv)
function readConfigs () {
return Promise.all(configs.map(path => {
return new Promise((resolve, reject) => {
fs.readFile(path, (err, data) => {
err ? reject(err) : resolve(yaml.safeLoad(data))
})
})
}))
}
readConfigs()
.then(configs => {
let organizationsConfig = configs[3]
console.log('organizationsConfig = ', organizationsConfig)
console.log('organizationsConfig.organizations = ', organizationsConfig.organizations)
...
The output from above is:
organizationsConfig = { organizations: ' - foo - bar' }
organizationsConfig.organizations = - foo - bar
How can I modify my helm config so that organizationsConfig.organizations will be ['foo', 'bar']
One way to get the output you're looking for is to change:
...
organizations:
- 'foo'
- 'bar'
...
To:
organizations: |
[ 'foo', 'bar']
So helm treats it as a single string. We happen to know that it contains array content but helm just thinks it's a string. Then we can set that string directly in the configmap:
organizations: {{ .Values.organizations | indent 4 }}
What this does is what the grafana chart does in that it forces the user to specify the list in the desired format in the first place. Perhaps you'd prefer to take an array from the helm values and convert it to your desired format, which appears to me to be json format. To do that you could follow the example of the vault chart. So the configmap line becomes:
organizations: {{ .Values.organizations | toJson | indent 4 }}
Then the yaml that the user puts in can be as you originally had it i.e. a true yaml array. I tried this and it works but I notice that it gives double-quoted content like ["foo","bar"]
The other way you can do it is with:
organizations:
{{- range .Values.organizations }}
- {{ . }}
{{- end }}
Sometimes the root cause is that you forget to surround each item by quotes:
organizations:
{{- range .Values.organizations }}
- {{ . | quote }} # <-- SEE Here
{{- end }}

Variable value as yaml key in helm chart

I want to choose config section from values.yaml by setting a variable in helm command line.
example part of values.yaml:
aaa:
x1: "az1"
x2: "az2"
bbb:
x1: "bz1"
x2: "bz2"
example part of configmap.yaml
data:
{{ .Values.outsideVal.x1 }}
Expected result should looks like this
data:
az1
Test helm output
helm template --set outsideVal=aaa mychart
And got this error
Error: render error in "./templates/configmap.yaml": template: ./templates/configmap.yaml:21:12: executing "./templates/configmap.yaml" at <.Values.outsideVal.x...>: can't evaluate field x1 in type interface {}
So the question is how get the result as expected?
I suspect you're looking for the text/template index function, which can look up a value in a map by a variable key.
{{ (index .Values .Values.outsideVal).x1 }}