helm template from array in values - json

i'm trying to get from an array in my values.yaml a working template i tried many thing but i always have some error does someone has an idea ?
values.yaml
zones: ["eu-west-3a"]
storageclass.yaml
allowedTopologies:
- matchLabelExpressions:
- key: failure-domain.beta.kubernetes.io/zone
{{- if .Values.zones }}
values: |-
{{- range .Values.zones }}
- {{ . }}
{{- end }}
{{- end -}}
Goal:
allowedTopologies:
- matchLabelExpressions:
- key: failure-domain.beta.kubernetes.io/zone
values:
- eu-west-3a
Error : Error: YAML parse error on storageclass/templates/storageclass.yaml: error converting YAML to JSON: yaml: line 15: did not find expected key
Edit:
This is how i fixed the problem :
allowedTopologies:
- matchLabelExpressions:
- key: failure-domain.beta.kubernetes.io/zone
{{ if .Values.zones -}}
values:
{{- range .Values.zones }}
- {{ . }}
{{- end -}}
{{- end -}}
thanks for your help

Use the print function to generate a list inside a range.
allowedTopologies:
- matchLabelExpressions:
- key: failure-domain.beta.kubernetes.io/zone
{{ if .Values.zones -}}
values:
{{- range .Values.zones }}
{{ print "- " . }}
{{- end }}
{{- end -}}

Related

How to use the third variable in range?

There are variables in values.yaml of my Helm Chart:
stand: dev-gfdz-loader
ingress1:
entrypoints: pdu
In Helm Chart I have:
{{- range $key, $value := $.Values.secretObjects }}
- secretKey: {{ $key | quote}}
objectName: {{ $value | quote }}
secretPath: "pdu/data/dev-gfdz-loader"
{{- end }}
This example is working.
In the line "pdu/data/dev-gfdz-loader" I need:
replace pdu with ingress1.entrypoints and
replace dev-gfdz-loader with stand
Finally, if I do this:
{{- range $key, $value := $.Values.secretObjects }}
- secretKey: {{ $key | quote}}
objectName: {{ $value | quote }}
secretPath: "{{ .Values.ingress1.entrypoints }}/data/{{ .Values.stand }}"
{{- end }}
Then I get an error:
Error: template: app/charts/rr/templates/secretproviderclass.yaml:23:31: executing "app/charts/rr/templates/secretproviderclass.yaml" at <.Values.ingress1.entrypoints>: can't evaluate field Values in type interface {} Use --debug flag to render out invalid YAML
My solution:
{{- $entrypoints := .Values.ingress1.entrypoints -}}
{{- $stand := .Values.stand -}}
{{- range $key, $value := $.Values.secretObjects }}
- secretKey: "{{ $key }}"
objectName: "{{ $value }}"
secretPath: "{{ $entrypoints }}/data/{{ $stand }}"
{{- end }}

Concatenate optional variables in Jinja without duplicating whitespace

Question
I want to concatenate variables in Jinja by separating them with exactly one space (' ') where some of the variables might be undefined (not known to the template which ones).
import jinja2
template = jinja2.Template('{{ title }} {{ first }} {{ middle }} {{ last }}')
result = template.render(first='John', last='Doe') # result == ' John Doe'
I've been searching for a template string alternative that returns 'John Doe' instead of ' John Doe' in this case.
First attempt
Use
{{ [title, first, middle, last]|reject("undefined")|join(" ") }}
as template (which actually works), however
it's confusing
once I want to use a macro on one of the arguments (that e.g. puts middle in brackets if it is not undefined) and therefore return an empty string instead of Undefined this stops working.
2nd attempt
Replace multiple spaces with one space
{% filter replace(" ", " ") -%}
{{ title }} {{ first }} {{ middle }} {{ last }}
{%- endfilter %}
which actually only would work in all cases with a regular expression search/replace like
{% filter regex_replace(" +", " ") -%}
{{ title }} {{ first }} {{ middle }} {{ last }}
{%- endfilter %}
but regex_replace is not built-in (but could be provided by a custom regular expression filter).
Still I would not consider this to be optimal as double spaces in the content of variables would be replaced as well.
you dont use the power of jinja2/python, use the if else and test if a variable is defined:
import jinja2
template = "{{ title ~ ' ' if title is defined else '' }}"
template += "{{first ~ ' ' if first is defined else '' }}"
template += "{{ middle ~ ' ' if middle is defined else '' }}"
template += "{{ last if last is defined else '' }}"
template = jinja2.Template(template)
result = template.render(first='John', last='Doe')
print("----------")
print(result)
print("----------")
result:
----------
John Doe
----------
if you want to use regex, use :
import re
:
:
template = jinja2.Template("{{ title }} {{ first }} {{ middle }} {{ last }}")
result = template.render(first='John', last='Doe')
result = re.sub(" +", " ", result.strip())
strip() deletes any leading and trailing whitespaces including tabs (\t)
or a mixed of both solutions to avoid to suppress spaces not wanted
import jinja2
template = "{{ title ~ ' ' if title is defined else '' }}"
template += "{{first ~ ' ' if first is defined else '' }}"
template += "{{ middle ~ ' ' if middle is defined else '' }}"
template += "{{ last if last is defined else '' }}"
template = jinja2.Template(template)
result = template.render(first='John', last='Doe').strip()
A variant of the accepted answer is to use a joiner in the Jinja template:
{%- set space = joiner(" ") %}
{%- if title %}{{ space() }}{{ title }}{% endif %}
{%- if first %}{{ space() }}{{ first }}{% endif %}
{%- if middle %}{{ space() }}{{ middle }}{% endif %}
{%- if last %}{{ space() }}{{ last }}{% endif %}
This works without any extensions, custom filters or post-processing but is relatively verbose.

Jinja2 go-to-column

I am using Jinja2 to perform code generation.
Besides the trivial problem to generate correctly indented code I also would like to perform certain in-line alignments; example use-cases would be:
start inline comments at a certain column
align operators in assignment series
A small excerpt of (1) would be:
Sound_Chime_t chime_array[] = {
{%- for k, cmd in commands.items() %}
{
"{{ cmd['Sound Command'] }}", // command
"{{ cmd['tag'] }}", // tag
{{ cmd['Priority'] }}, // priority
{{ cmd['Mix'] }}, // mix
{{ cmd['Loop'] }}, // loop
{{ cmd['region'] }}, // region
"{{ cmd['Sound File']}}" // filename
}{{ ',' if not loop.last else '' }}
{%- endfor %}
};
Of course //... is nicely aligned in template, but it won't be in generated code.
Is there some (not too convoluted) way to obtain this?
You can align the comments using two .format() calls. The second one is required by the occasional quotation marks and commas after a value. This will pad the values to 20:
Sound_Chime_t chime_array[] = {
{%- for k, cmd in commands.items() %}
{
{{ '{:<20} // command'.format('"{}",'.format(cmd['Sound Command'])) }}
{{ '{:<20} // tag'.format('"{},"'.format(cmd['tag'])) }}
{{ '{:<20} // priority'.format('{},'.format(cmd['Priority'])) }}
{{ '{:<20} // mix'.format('{},'.format(cmd['Mix'])) }}
{{ '{:<20} // loop'.format('{},'.format(cmd['Loop'])) }}
{{ '{:<20} // region'.format('{},'.format(cmd['region'])) }}
{{ '{:<20} // filename'.format('"{}"'.format(cmd['Sound File'])) }}
}{{ ',' if not loop.last else '' }}
{%- endfor %}
};

Whitespaces aren't being trimmed Golang templates

In the following code, the white spaces aren't being trimmed despite using {{--}}
{{$first := true}}
{{range $name, $value := .Labels}}
{{if $first}}
{{$first = false}}
{{else}}
,
{{end}}
{{$name}}={{$value -}}
{{end}}
So it prints like this: name=value , name2=value2
I'm not sure why the whitespaces aren't being trimmed... .Labels is a map[string]string
and the strings don't have spaces in them, since the following:
{{range $name, $value := .Labels}}
{{$name}}={{$value}},
{{end}}
prints without the leading space like this: name=value, name2=value2,
{{ $first := true -}}
{{ range $name, $value := .Labels -}}
{{ if $first -}}
{{ $first = false -}}
{{ else -}}
{{- ", " -}}
{{ end -}}
{{ $name }}={{ $value -}}
{{ end }}
https://play.golang.org/p/0r69PUj3mEi

Unable to get partial to return images generated from title - Hugo

Based on this blogpost, I am trying to generate a pseudo-random thumbnail for each new post. First, in my data folder I have a bg.json which contains information about the colours and SVGs like so:
{
"colours": [
"#dfe6e9",
"#00b894"
],
"patterns": [
"data:image/svg+xml..."
]
}
Next, in the partials folder, I created a new partial called thumbnail.html which contains the following code:
{{ $hash := split (md5 .Title) "" }}
{{ $totalColours := len .Site.Data.bg.colours }}
{{ $primaryIndex := index $hash 1 }}
{{ $basedPrimaryIndex := printf "%x" $primaryIndex }}
{{ $modIndex := mod $basedPrimaryIndex $totalColours }}
{{ $primary := index .Site.Data.bg.colours $modIndex }}
{{ $secondaryIndex := index $hash 2 }}
{{ $basedSecondaryIndex := printf "%x" $secondaryIndex }}
{{ $modIndex := mod $basedSecondaryIndex $totalColours }}
{{ $secondary := index .Site.Data.bg.colours $modIndex }}
{{ $bgIndex := mod (printf "%x" (index $hash 0)) (len .Site.Data.bg.patterns) }}
{{ $bg := replace (replace (replace (replace (index .Site.Data.bg.patterns $bgIndex) "%3C" "<") "%3E" ">") "%23" "" | safeHTML) "data:image/svg+xml," "" }}
{{ $colouredBg := replace $bg "9C92AC" $secondary }}
<style>
.post__header {
--color: {{ $primary }};
--bg: url("data:image/svg+xml;charset=utf-8;base64,{{ base64Encode $colouredBg }}");
}
</style>
My theme generates portfolio cards in another partial called portfolio.html. I looked through the file and replaced the original img src with a path to my partial like so:
<div class="box-masonry">
{{ if and (isset .Params "image") .Params.image }}
{{ if eq .Params.showonlyimage true }}
<a href="{{ .Permalink }}" title="" class="box-masonry-image with-hover-overlay">
{{ else }}
<a href="{{ .Permalink }}" title="" class="box-masonry-image with-hover-overlay with-hover-icon">
{{ end }}
<img src="{{ partial "thumbnail.html" . }}" alt="" class="img-responsive">
</a>
(...)
However, I am not seeing any images when I run my hugo server. I thought this would be the neatest way to approach things, but I think the post title (which is hashed to pick a random palette/pattern) is not being passed. How can I fix this?
My repo is hosted here: https://github.com/thedivtagguy/archives
The repo for the original blogpost's code is hosted here: https://github.com/trys/random-to-a-point