add reset_then_reuse_values support to helm module (#802)

SUMMARY
Starting with version 3.14.0, Helm supports --reset-then-reuse-values. As discussed on the original PR. This greatly improves on --reuse-values as it allows to avoid templates errors when new features are added to an upgraded chart.
Closes #803
ISSUE TYPE

Feature Pull Request

COMPONENT NAME
helm
ADDITIONAL INFORMATION
This PR is greatly 'inspired' by #575 and because I wasn't sure how I could provide additional tests for it, I actually copied those build previously for --reuse-values (as it is an improvement on this feature.

Reviewed-by: Bikouo Aubin
Reviewed-by: Yuriy Novostavskiy
Reviewed-by: b0z02003
Reviewed-by: Bianca Henderson <beeankha@gmail.com>
This commit is contained in:
b0z02003
2025-04-28 17:11:58 +02:00
committed by GitHub
parent d329e7ee42
commit 00699ac3e5
11 changed files with 345 additions and 3 deletions

View File

@@ -0,0 +1,3 @@
---
minor_changes:
- helm - add reset_then_reuse_values support to helm module (https://github.com/ansible-collections/kubernetes.core/issues/803).

View File

@@ -435,6 +435,28 @@ Parameters
<div>mutually exclusive with with <code>history_max</code>.</div> <div>mutually exclusive with with <code>history_max</code>.</div>
</td> </td>
</tr> </tr>
<tr>
<td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div>
<b>reset_then_reuse_values</b>
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
<div style="font-size: small">
<span style="color: purple">boolean</span>
</div>
<div style="font-style: italic; font-size: small; color: darkgreen">added in 6.0.0</div>
</td>
<td>
<ul style="margin: 0; padding: 0"><b>Choices:</b>
<li><div style="color: blue"><b>no</b>&nbsp;&larr;</div></li>
<li>yes</li>
</ul>
</td>
<td>
<div>When upgrading package, reset the values to the ones built into the chart, apply the last release&#x27;s values and merge in any overrides from parameters O(release_values), O(values_files) or O(set_values).</div>
<div>If O(reset_values) or O(reuse_values) is set to V(True), this is ignored.</div>
<div>This feature requires helm diff &gt;= 3.9.12.</div>
</td>
</tr>
<tr> <tr>
<td colspan="2"> <td colspan="2">
<div class="ansibleOptionAnchor" id="parameter-"></div> <div class="ansibleOptionAnchor" id="parameter-"></div>

View File

@@ -145,6 +145,16 @@ options:
required: false required: false
default: True default: True
version_added: 3.0.0 version_added: 3.0.0
reset_then_reuse_values:
description:
- When upgrading package, reset the values to the ones built into the chart, apply the last release's values and merge in any overrides from
parameters O(release_values), O(values_files) or O(set_values).
- If O(reset_values) or O(reuse_values) is set to V(True), this is ignored.
- This feature requires helm diff >= 3.9.12.
type: bool
required: false
default: False
version_added: 6.0.0
#Helm options #Helm options
disable_hook: disable_hook:
@@ -509,6 +519,7 @@ def deploy(
set_value_args=None, set_value_args=None,
reuse_values=None, reuse_values=None,
reset_values=True, reset_values=True,
reset_then_reuse_values=False,
): ):
""" """
Install/upgrade/rollback release chart Install/upgrade/rollback release chart
@@ -526,6 +537,17 @@ def deploy(
if reuse_values is not None: if reuse_values is not None:
deploy_command += " --reuse-values=" + str(reuse_values) deploy_command += " --reuse-values=" + str(reuse_values)
if reset_then_reuse_values:
helm_version = module.get_helm_version()
if LooseVersion(helm_version) < LooseVersion("3.14.0"):
module.fail_json(
msg="reset_then_reuse_values requires helm >= 3.14.0, current version is {0}".format(
helm_version
)
)
else:
deploy_command += " --reset-then-reuse-values"
if wait: if wait:
deploy_command += " --wait" deploy_command += " --wait"
if wait_timeout is not None: if wait_timeout is not None:
@@ -642,6 +664,7 @@ def helmdiff_check(
set_value_args=None, set_value_args=None,
reuse_values=None, reuse_values=None,
reset_values=True, reset_values=True,
reset_then_reuse_values=False,
): ):
""" """
Use helm diff to determine if a release would change by upgrading a chart. Use helm diff to determine if a release would change by upgrading a chart.
@@ -676,6 +699,24 @@ def helmdiff_check(
if reuse_values: if reuse_values:
cmd += " --reuse-values" cmd += " --reuse-values"
if reset_then_reuse_values:
helm_diff_version = get_plugin_version("diff")
helm_version = module.get_helm_version()
fail_msg = ""
if LooseVersion(helm_diff_version) < LooseVersion("3.9.12"):
fail_msg = "reset_then_reuse_values requires helm diff >= 3.9.12, current version is {0}\n".format(
helm_diff_version
)
if LooseVersion(helm_version) < LooseVersion("3.14.0"):
fail_msg += "reset_then_reuse_values requires helm >= 3.14.0, current version is {0}\n".format(
helm_version
)
if fail_msg:
module.fail_json(msg=fail_msg)
else:
cmd += " --reset-then-reuse-values"
rc, out, err = module.run_helm_command(cmd) rc, out, err = module.run_helm_command(cmd)
return (len(out.strip()) > 0, out.strip()) return (len(out.strip()) > 0, out.strip())
@@ -735,6 +776,7 @@ def argument_spec():
set_values=dict(type="list", elements="dict"), set_values=dict(type="list", elements="dict"),
reuse_values=dict(type="bool"), reuse_values=dict(type="bool"),
reset_values=dict(type="bool", default=True), reset_values=dict(type="bool", default=True),
reset_then_reuse_values=dict(type="bool", default=False),
) )
) )
return arg_spec return arg_spec
@@ -787,6 +829,7 @@ def main():
set_values = module.params.get("set_values") set_values = module.params.get("set_values")
reuse_values = module.params.get("reuse_values") reuse_values = module.params.get("reuse_values")
reset_values = module.params.get("reset_values") reset_values = module.params.get("reset_values")
reset_then_reuse_values = module.params.get("reset_then_reuse_values")
if update_repo_cache: if update_repo_cache:
run_repo_update(module) run_repo_update(module)
@@ -883,6 +926,7 @@ def main():
set_value_args=set_value_args, set_value_args=set_value_args,
reuse_values=reuse_values, reuse_values=reuse_values,
reset_values=reset_values, reset_values=reset_values,
reset_then_reuse_values=reset_then_reuse_values,
) )
changed = True changed = True
@@ -908,6 +952,7 @@ def main():
set_value_args, set_value_args,
reuse_values=reuse_values, reuse_values=reuse_values,
reset_values=reset_values, reset_values=reset_values,
reset_then_reuse_values=reset_then_reuse_values,
) )
if would_change and module._diff: if would_change and module._diff:
opt_result["diff"] = {"prepared": prepared} opt_result["diff"] = {"prepared": prepared}
@@ -943,6 +988,7 @@ def main():
set_value_args=set_value_args, set_value_args=set_value_args,
reuse_values=reuse_values, reuse_values=reuse_values,
reset_values=reset_values, reset_values=reset_values,
reset_then_reuse_values=reset_then_reuse_values,
) )
changed = True changed = True

View File

@@ -26,3 +26,4 @@ test_namespace:
- "helm-from-url" - "helm-from-url"
- "helm-reuse-values" - "helm-reuse-values"
- "helm-chart-with-space-into-name" - "helm-chart-with-space-into-name"
- "helm-reset-then-reuse-values"

View File

@@ -4,4 +4,4 @@
loop_control: loop_control:
loop_var: helm_version loop_var: helm_version
with_items: with_items:
- "v3.8.0" - "v3.16.0"

View File

@@ -28,6 +28,9 @@
- name: test helm upgrade with reuse_values - name: test helm upgrade with reuse_values
include_tasks: test_helm_reuse_values.yml include_tasks: test_helm_reuse_values.yml
- name: test helm upgrade with reset_then_reuse_values
include_tasks: test_helm_reset_then_reuse_values.yml
- name: test helm dependency update - name: test helm dependency update
include_tasks: test_up_dep.yml include_tasks: test_up_dep.yml

View File

@@ -0,0 +1,75 @@
---
- name: Test helm reset_then_reuse_values
vars:
helm_namespace: "{{ test_namespace[11] }}"
chart_release_values:
replica:
replicaCount: 3
master:
count: 1
kind: Deployment
chart_reset_then_reuse_values:
replica:
replicaCount: 1
master:
count: 3
block:
- name: Initial chart installation
helm:
binary_path: "{{ helm_binary }}"
chart_ref: oci://registry-1.docker.io/bitnamicharts/redis
release_name: test-redis
release_namespace: "{{ helm_namespace }}"
create_namespace: true
release_values: "{{ chart_release_values }}"
register: install
- name: Get value set as string
helm_info:
binary_path: "{{ helm_binary }}"
release_name: test-redis
release_namespace: "{{ helm_namespace }}"
register: release_value
- name: Validate that chart values are as expected
assert:
that:
- install is changed
- '"--reset-then-reuse-values" not in install.command'
- release_value["status"]["values"] == chart_release_values
- name: Upgrade chart using reset_then_reuse_values=true
helm:
binary_path: "{{ helm_binary }}"
chart_ref: oci://registry-1.docker.io/bitnamicharts/redis
release_name: test-redis
release_namespace: "{{ helm_namespace }}"
reuse_values: false
reset_values: false
reset_then_reuse_values: true
release_values: "{{ chart_reset_then_reuse_values }}"
register: upgrade
- name: Get value set as string
helm_info:
binary_path: "{{ helm_binary }}"
release_name: test-redis
release_namespace: "{{ helm_namespace }}"
register: release_value
- name: Validate that chart values are as expected
assert:
that:
- upgrade is changed
- '"--reset-then-reuse-values" in upgrade.command'
- '"--reuse-values " not in upgrade.command'
- '"--reset-values" not in upgrade.command'
- release_value["status"]["values"] == chart_release_values | combine(chart_reset_then_reuse_values, recursive=true)
always:
- name: Remove helm namespace
k8s:
api_version: v1
kind: Namespace
name: "{{ helm_namespace }}"
state: absent

View File

@@ -10,7 +10,7 @@
binary_path: "{{ helm_binary }}" binary_path: "{{ helm_binary }}"
state: present state: present
plugin_path: https://github.com/databus23/helm-diff plugin_path: https://github.com/databus23/helm-diff
plugin_version: 3.4.0 plugin_version: 3.9.13
- name: Copy test chart - name: Copy test chart
copy: copy:
@@ -324,3 +324,5 @@
ignore_errors: true ignore_errors: true
- include_tasks: reuse_values.yml - include_tasks: reuse_values.yml
- include_tasks: reset_then_reuse_values.yml

View File

@@ -0,0 +1,189 @@
---
- name: Create temporary directory for helm chart
tempfile:
suffix: .helm
state: directory
register: helm_dir
- name: Test helm diff functionality
vars:
test_chart_path: "{{ helm_dir.path }}/test-chart-reuse-values"
test_release_name: "myrelease"
block:
- name: Install helm diff
kubernetes.core.helm_plugin:
binary_path: "{{ helm_binary }}"
state: present
plugin_path: https://github.com/databus23/helm-diff
plugin_version: 3.9.14
- name: Copy test chart
ansible.builtin.copy:
src: "test-chart-reuse-values"
dest: "{{ helm_dir.path }}"
- name: Delete existing namespace
kubernetes.core.k8s:
state: absent
wait: true
kind: Namespace
name: "{{ helm_namespace }}"
ignore_errors: true
- name: Create helm release
kubernetes.core.helm:
state: present
binary_path: "{{ helm_binary }}"
chart_ref: "{{ test_chart_path }}"
release_name: "{{ test_release_name }}"
release_namespace: "{{ helm_namespace }}"
create_namespace: true
release_values:
ansible_version: devel
phase: ci
wait: true
- name: Upgrade helm release (reset_values=false and reuse_values=false and reset_then_reuse_values=true)
kubernetes.core.helm:
binary_path: "{{ helm_binary }}"
chart_ref: "{{ test_chart_path }}"
reset_values: false
reuse_values: false
reset_then_reuse_values: true
release_name: "{{ test_release_name }}"
release_namespace: "{{ helm_namespace }}"
values:
ansible_version: devel
register: helm_upgrade
- name: Ensure task did not reported change
assert:
that:
- helm_upgrade is not changed
- name: Upgrade helm release (reset_then_reuse_values=true with default value for reset_values and reuse_values=false)
kubernetes.core.helm:
binary_path: "{{ helm_binary }}"
chart_ref: "{{ test_chart_path }}"
reuse_values: false
reset_then_reuse_values: true
release_name: "{{ test_release_name }}"
release_namespace: "{{ helm_namespace }}"
values:
ansible_version: devel
register: helm_upgrade
- name: Ensure task reported change
assert:
that:
- helm_upgrade is changed
# Delete helm and helm diff to install older version
- name: Uninstall helm diff
helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: diff
ignore_errors: true
- name: Delete Helm folders
file:
path: /tmp/helm/
state: absent
- name: Init Helm folders
file:
path: /tmp/helm
state: directory
- name: Set Helm old version
set_fact:
helm_archive_name: "helm-v3.8.0-linux-amd64.tar.gz"
helm_diff_old_version: "3.8.0"
- name: Unarchive Helm binary
unarchive:
src: "https://get.helm.sh/{{ helm_archive_name | default(helm_default_archive_name) }}"
dest: /tmp/helm/
remote_src: yes
retries: 10
delay: 5
register: result
until: result is not failed
- name: Upgrade helm release (with reset_then_reuse_values=true)
kubernetes.core.helm:
binary_path: "{{ helm_binary }}"
chart_ref: "{{ test_chart_path }}"
reuse_values: false
reset_then_reuse_values: true
release_name: "{{ test_release_name }}"
release_namespace: "{{ helm_namespace }}"
values:
ansible_version: test
register: helm_upgrade
ignore_errors: true
- name: Debug
debug:
var: helm_upgrade
- name: Ensure warning for Helm version
assert:
that:
- helm_upgrade is failed
- '"reset_then_reuse_values requires helm >= 3.14.0, current version is" in helm_upgrade.msg'
- name: Install helm diff
helm_plugin:
binary_path: "{{ helm_binary }}"
state: present
plugin_path: https://github.com/databus23/helm-diff
plugin_version: "{{ helm_diff_old_version }}"
- name: Upgrade helm release (with reset_then_reuse_values=true)
kubernetes.core.helm:
binary_path: "{{ helm_binary }}"
chart_ref: "{{ test_chart_path }}"
reuse_values: false
reset_then_reuse_values: true
release_name: "{{ test_release_name }}"
release_namespace: "{{ helm_namespace }}"
values:
ansible_version: devel
register: helm_upgrade
ignore_errors: true
- name: Debug
debug:
var: helm_upgrade
- name: Ensure warning for Helm Diff version
assert:
that:
- helm_upgrade is failed
- '"reset_then_reuse_values requires helm diff >= 3.9.12, current version is" in helm_upgrade.msg'
always:
- name: Remove temporary directory
file:
path: "{{ helm_dir.path }}"
state: absent
ignore_errors: true
- name: Uninstall helm diff
kubernetes.core.helm_plugin:
binary_path: "{{ helm_binary }}"
state: absent
plugin_name: diff
ignore_errors: true
- name: Remove helm namespace
kubernetes.core.k8s:
api_version: v1
kind: Namespace
name: "{{ helm_namespace }}"
state: absent
wait: true
ignore_errors: true

View File

@@ -90,4 +90,5 @@
kind: Namespace kind: Namespace
name: "{{ helm_namespace }}" name: "{{ helm_namespace }}"
state: absent state: absent
wait: true
ignore_errors: true ignore_errors: true

View File

@@ -1,4 +1,4 @@
--- ---
helm_version: v3.8.0 helm_version: v3.16.4
helm_install_path: /tmp/helm helm_install_path: /tmp/helm
helm_default_archive_name: "helm-{{ helm_version }}-{{ ansible_system | lower }}-amd64.tar.gz" helm_default_archive_name: "helm-{{ helm_version }}-{{ ansible_system | lower }}-amd64.tar.gz"