Skip to content

Instantly share code, notes, and snippets.

@miraculixx
Last active July 1, 2021 15:43
Show Gist options
  • Save miraculixx/bbba80793895f081204a05fbd5573eda to your computer and use it in GitHub Desktop.
Save miraculixx/bbba80793895f081204a05fbd5573eda to your computer and use it in GitHub Desktop.
helm update-values helper
# Details on usage see docstring
#
# Installation:
#
# $ pip install invoke
# $ (copy/paste this file to your local tasks.py)
#
# Usage:
#
# 1. amend your values.yaml with a #==tags.myfeature (at line end of line to update)
# 2. $ invoke update-values -v values.yaml --specs "tags.myfeature=true"
# 3. use helm as usual
#
# Disclaimer: quick & dirty approach avoiding the hassle of yaml parsing
#
# License: MIT
@task
def update_values(c, values_file=None, output_file=None, specs=None):
"""
Update a helm values.yaml file by a --set compatible values string
When setting tags in values.yaml where the tags are used as yaml anchors these are
not updated when helm is called, see https://github.com/helm/helm/issues/5589
This update-values task provides a solution.
Args:
c:
values_file (str): filename of values file
specs (str): commad separated key=values
Usage:
cloudmgr helm.update-values ./values.yaml --specs "tags.mytag=value"
this will update the values.yaml file on the line that indicates, at
line end:
#==tags.mytag
The corresponding line's value (the last string) is updated
accordingly.
Example:
# values.yaml
tags:
ssl: true #==tags.ssl
$ invoke update-values ./values.yaml --specs "tags.ssl=false"
will replace ssl: true with ssl: false
# values.yaml updated
tags:
ssl: fdalse #==tags.ssl
Otherwise the values file is left untouched. This is idempotent,
that is the #== indicator is not removed.
Only works with scalar/numeric and boolean values, strings not supported.
Notes:
* using jinja templating values.yaml does not help because jinja rendering is not
indempotent. this would require to permanently keep a tempalte and
a rendered version of values.yaml, which is confusing
* using yaml anchors (as tags/flags/scalar values) is convenient since
it allows to centralize global values in one place in values.yaml
* using {{ tpl ... }} is sometimes a solution, but does not work when the values.yaml
is driving imported helm charts that you don't want to or cannot change.
Returns:
saves updated values file
"""
spec_vars = dict([pair.strip().split('=') for pair in specs.split(',')])
with open(values_file) as fin:
lines = fin.readlines()
cur = None
updated_lines = []
for line in lines:
if '#==' in line:
orig, seek = line.split(' #==')
tokens = orig.rstrip().split(' ')
tokens[-1] = spec_vars[seek.replace('\n', '').strip()]
new_line = ' '.join(tokens) + ' #==' + seek
updated_lines.append(new_line)
else:
updated_lines.append(line)
with open(output_file or values_file, 'w') as fout:
fout.writelines(updated_lines)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment