mirror of
https://github.com/ansible-collections/kubernetes.core.git
synced 2026-05-07 21:42:38 +00:00
Add helm dependency update (#208)
Add helm dependency update SUMMARY Execute the helm dependency update under the hood when found dependencies block in Chart.yaml file. Support the execution of: Standalone dependency update by executing: helm dependency update CHART Inline dependency update when specifying the helm chart_repo_url by adding --dependency-update to the helm install command. ISSUE TYPE Feature Pull Request #191 COMPONENT NAME helm, helm_template ADDITIONAL INFORMATION There is a doc generated for history_max option for the helm module. I think that is not generated in the previous PR #164. There is others changes affect the docs/ folder when I run the collection_prep_add_docs -p . command. These changes are added in the last commit 64eab40. I let you decide rather we keep the commit or remove it. The --dependency-update insertion option is tested used a local helm chart repository create via docker. So here are the tasks that test this feature. Maybe if we create a GitHub repository for the helm chart, we can add this test code in the CI pipeline. # Test The update dependency with chart_repo_url - name: "Test chart without dependencies block and chart_repo_url defined" block: - name: "Test chart without dependencies block and chart_repo_url defined" helm: binary_path: "{{ helm_binary }}" name: test chart_ref: "ingress-nginx" chart_repo_url: https://kubernetes.github.io/ingress-nginx chart_version: "{{ chart_source_version | default(omit) }}" namespace: "{{ helm_namespace }}" create_namespace: yes register: release - assert: that: - "'--dependency-update' not in release.command" - "'upgrade' in release.command" success_msg: "Command does not contains '--dependency-update' options" fail_msg: "Command contains '--dependency-update' options" - name: "Test chart with dependencies block and chart_repo_url defined and replace True" block: - name: "Test chart with dependencies block and chart_repo_url defined and replace True" helm: binary_path: "{{ helm_binary }}" name: test1 chart_ref: "dep_up" chart_repo_url: http://repo:8080/charts chart_version: "{{ chart_source_version | default(omit) }}" namespace: "{{ helm_namespace }}" create_namespace: yes replace: true register: release - debug: var=release - assert: that: - "'--dependency-update' in release.command" - "'install' in release.command" success_msg: "Command contains '--dependency-update' options with helm install command" fail_msg: "Command not contains '--dependency-update' with helm install command" - name: "Test chart with dependencies block and chart_repo_url defined and replace False fails" block: - name: "Test chart with dependencies block and chart_repo_url defined and replace False fails" helm: binary_path: "{{ helm_binary }}" name: test2 chart_ref: "dep_up" chart_repo_url: http://repo:8080/charts chart_version: "{{ chart_source_version | default(omit) }}" namespace: "{{ helm_namespace }}" create_namespace: yes replace: false register: release ignore_errors: true - assert: that: - release.failed - release.msg == "'--dependency-update' hasn't been supported yet with 'helm upgrade'. Please use 'helm install' instead by adding 'replace' option" success_msg: "Command build fail when adding '--dependency-update' with the helm upgrade command" Reviewed-by: Mike Graves <mgraves@redhat.com> Reviewed-by: Wissem BEN CHAABANE <benchaaben.wissem@gmail.com> Reviewed-by: Bikouo Aubin <None>
This commit is contained in:
committed by
GitHub
parent
f2f4b66d77
commit
4fa1fb966b
2
changelogs/fragments/208-add-dependency-update.yaml
Normal file
2
changelogs/fragments/208-add-dependency-update.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
minor_changes:
|
||||||
|
- helm - add support for helm dependency update (https://github.com/ansible-collections/kubernetes.core/pull/208).
|
||||||
@@ -193,6 +193,30 @@ Parameters
|
|||||||
<div>Create the release namespace if not present.</div>
|
<div>Create the release namespace if not present.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>dependency_update</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Run standelone <code>helm dependency update CHART</code> before the operation.</div>
|
||||||
|
<div>Run inline <code>--dependency-update</code> with <code>helm install</code> command. This feature is not supported yet with the <code>helm upgrade</code> command.</div>
|
||||||
|
<div>So we should consider to use <em>dependency_update</em> options with <em>replace</em> option enabled when specifying <em>chart_repo_url</em>.</div>
|
||||||
|
<div>The <em>dependency_update</em> option require the add of <code>dependencies</code> block in <code>Chart.yaml/requirements.yaml</code> file.</div>
|
||||||
|
<div>For more information please visit <a href='https://helm.sh/docs/helm/helm_dependency/'>https://helm.sh/docs/helm/helm_dependency/</a></div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: dep_up</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
|||||||
@@ -96,6 +96,28 @@ Parameters
|
|||||||
<div>Chart version to use. If this is not specified, the latest version is installed.</div>
|
<div>Chart version to use. If this is not specified, the latest version is installed.</div>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="1">
|
||||||
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
<b>dependency_update</b>
|
||||||
|
<a class="ansibleOptionLink" href="#parameter-" title="Permalink to this option"></a>
|
||||||
|
<div style="font-size: small">
|
||||||
|
<span style="color: purple">boolean</span>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul style="margin: 0; padding: 0"><b>Choices:</b>
|
||||||
|
<li><div style="color: blue"><b>no</b> ←</div></li>
|
||||||
|
<li>yes</li>
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div>Run helm dependency update before the operation.</div>
|
||||||
|
<div>The <em>dependency_update</em> option require the add of <code>dependencies</code> block in <code>Chart.yaml/requirements.yaml</code> file.</div>
|
||||||
|
<div>For more information please visit <a href='https://helm.sh/docs/helm/helm_dependency/'>https://helm.sh/docs/helm/helm_dependency/</a></div>
|
||||||
|
<div style="font-size: small; color: darkgreen"><br/>aliases: dep_up</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="1">
|
<td colspan="1">
|
||||||
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
<div class="ansibleOptionAnchor" id="parameter-"></div>
|
||||||
|
|||||||
@@ -51,6 +51,17 @@ options:
|
|||||||
- Chart version to install. If this is not specified, the latest version is installed.
|
- Chart version to install. If this is not specified, the latest version is installed.
|
||||||
required: false
|
required: false
|
||||||
type: str
|
type: str
|
||||||
|
dependency_update:
|
||||||
|
description:
|
||||||
|
- Run standalone C(helm dependency update CHART) before the operation.
|
||||||
|
- Run inline C(--dependency-update) with C(helm install) command. This feature is not supported yet with the C(helm upgrade) command.
|
||||||
|
- So we should consider to use I(dependency_update) options with I(replace) option enabled when specifying I(chart_repo_url).
|
||||||
|
- The I(dependency_update) option require the add of C(dependencies) block in C(Chart.yaml/requirements.yaml) file.
|
||||||
|
- For more information please visit U(https://helm.sh/docs/helm/helm_dependency/)
|
||||||
|
default: false
|
||||||
|
type: bool
|
||||||
|
aliases: [ dep_up ]
|
||||||
|
version_added: "2.4.0"
|
||||||
release_name:
|
release_name:
|
||||||
description:
|
description:
|
||||||
- Release name to manage.
|
- Release name to manage.
|
||||||
@@ -322,6 +333,7 @@ command:
|
|||||||
sample: helm upgrade ...
|
sample: helm upgrade ...
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
import tempfile
|
import tempfile
|
||||||
import traceback
|
import traceback
|
||||||
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
from ansible_collections.kubernetes.core.plugins.module_utils.version import (
|
||||||
@@ -385,6 +397,14 @@ def run_repo_update(module, command):
|
|||||||
rc, out, err = run_helm(module, repo_update_command)
|
rc, out, err = run_helm(module, repo_update_command)
|
||||||
|
|
||||||
|
|
||||||
|
def run_dep_update(module, command, chart_ref):
|
||||||
|
"""
|
||||||
|
Run dependency update
|
||||||
|
"""
|
||||||
|
dep_update = command + " dependency update " + chart_ref
|
||||||
|
rc, out, err = run_helm(module, dep_update)
|
||||||
|
|
||||||
|
|
||||||
def fetch_chart_info(module, command, chart_ref):
|
def fetch_chart_info(module, command, chart_ref):
|
||||||
"""
|
"""
|
||||||
Get chart info
|
Get chart info
|
||||||
@@ -413,6 +433,7 @@ def deploy(
|
|||||||
post_renderer=None,
|
post_renderer=None,
|
||||||
skip_crds=False,
|
skip_crds=False,
|
||||||
timeout=None,
|
timeout=None,
|
||||||
|
dependency_update=None,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Install/upgrade/rollback release chart
|
Install/upgrade/rollback release chart
|
||||||
@@ -420,6 +441,8 @@ def deploy(
|
|||||||
if replace:
|
if replace:
|
||||||
# '--replace' is not supported by 'upgrade -i'
|
# '--replace' is not supported by 'upgrade -i'
|
||||||
deploy_command = command + " install"
|
deploy_command = command + " install"
|
||||||
|
if dependency_update:
|
||||||
|
deploy_command += " --dependency-update"
|
||||||
else:
|
else:
|
||||||
deploy_command = command + " upgrade -i" # install/upgrade
|
deploy_command = command + " upgrade -i" # install/upgrade
|
||||||
|
|
||||||
@@ -597,6 +620,7 @@ def main():
|
|||||||
chart_ref=dict(type="path"),
|
chart_ref=dict(type="path"),
|
||||||
chart_repo_url=dict(type="str"),
|
chart_repo_url=dict(type="str"),
|
||||||
chart_version=dict(type="str"),
|
chart_version=dict(type="str"),
|
||||||
|
dependency_update=dict(type="bool", default=False, aliases=["dep_up"]),
|
||||||
release_name=dict(type="str", required=True, aliases=["name"]),
|
release_name=dict(type="str", required=True, aliases=["name"]),
|
||||||
release_namespace=dict(type="str", required=True, aliases=["namespace"]),
|
release_namespace=dict(type="str", required=True, aliases=["namespace"]),
|
||||||
release_state=dict(
|
release_state=dict(
|
||||||
@@ -667,6 +691,7 @@ def main():
|
|||||||
chart_ref = module.params.get("chart_ref")
|
chart_ref = module.params.get("chart_ref")
|
||||||
chart_repo_url = module.params.get("chart_repo_url")
|
chart_repo_url = module.params.get("chart_repo_url")
|
||||||
chart_version = module.params.get("chart_version")
|
chart_version = module.params.get("chart_version")
|
||||||
|
dependency_update = module.params.get("dependency_update")
|
||||||
release_name = module.params.get("release_name")
|
release_name = module.params.get("release_name")
|
||||||
release_state = module.params.get("release_state")
|
release_state = module.params.get("release_state")
|
||||||
release_values = module.params.get("release_values")
|
release_values = module.params.get("release_values")
|
||||||
@@ -729,6 +754,36 @@ def main():
|
|||||||
# Fetch chart info to have real version and real name for chart_ref from archive, folder or url
|
# Fetch chart info to have real version and real name for chart_ref from archive, folder or url
|
||||||
chart_info = fetch_chart_info(module, helm_cmd, chart_ref)
|
chart_info = fetch_chart_info(module, helm_cmd, chart_ref)
|
||||||
|
|
||||||
|
if dependency_update:
|
||||||
|
if chart_info.get("dependencies"):
|
||||||
|
# Can't use '--dependency-update' with 'helm upgrade' that is the
|
||||||
|
# default chart install method, so if chart_repo_url is defined
|
||||||
|
# we can't use the dependency update command. But, in the near future
|
||||||
|
# we can get rid of this method and use only '--dependency-update'
|
||||||
|
# option. Please see https://github.com/helm/helm/pull/8810
|
||||||
|
if not chart_repo_url and not re.fullmatch(
|
||||||
|
r"^http[s]*://[\w.:/?&=-]+$", chart_ref
|
||||||
|
):
|
||||||
|
run_dep_update(module, helm_cmd_common, chart_ref)
|
||||||
|
|
||||||
|
# To not add --dependency-update option in the deploy function
|
||||||
|
dependency_update = False
|
||||||
|
else:
|
||||||
|
module.warn(
|
||||||
|
"This is a not stable feature with 'chart_repo_url'. Please consider to use dependency update with on-disk charts"
|
||||||
|
)
|
||||||
|
if not replace:
|
||||||
|
msg_fail = (
|
||||||
|
"'--dependency-update' hasn't been supported yet with 'helm upgrade'. "
|
||||||
|
"Please use 'helm install' instead by adding 'replace' option"
|
||||||
|
)
|
||||||
|
module.fail_json(msg=msg_fail)
|
||||||
|
else:
|
||||||
|
module.warn(
|
||||||
|
"There is no dependencies block defined in Chart.yaml. Dependency update will not be performed. "
|
||||||
|
"Please consider add dependencies block or disable dependency_update to remove this warning."
|
||||||
|
)
|
||||||
|
|
||||||
if release_status is None: # Not installed
|
if release_status is None: # Not installed
|
||||||
helm_cmd = deploy(
|
helm_cmd = deploy(
|
||||||
helm_cmd,
|
helm_cmd,
|
||||||
@@ -744,6 +799,7 @@ def main():
|
|||||||
create_namespace=create_namespace,
|
create_namespace=create_namespace,
|
||||||
post_renderer=post_renderer,
|
post_renderer=post_renderer,
|
||||||
replace=replace,
|
replace=replace,
|
||||||
|
dependency_update=dependency_update,
|
||||||
skip_crds=skip_crds,
|
skip_crds=skip_crds,
|
||||||
history_max=history_max,
|
history_max=history_max,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
@@ -800,6 +856,7 @@ def main():
|
|||||||
skip_crds=skip_crds,
|
skip_crds=skip_crds,
|
||||||
history_max=history_max,
|
history_max=history_max,
|
||||||
timeout=timeout,
|
timeout=timeout,
|
||||||
|
dependency_update=dependency_update,
|
||||||
)
|
)
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
|
|||||||
@@ -45,6 +45,15 @@ options:
|
|||||||
- Chart version to use. If this is not specified, the latest version is installed.
|
- Chart version to use. If this is not specified, the latest version is installed.
|
||||||
required: false
|
required: false
|
||||||
type: str
|
type: str
|
||||||
|
dependency_update:
|
||||||
|
description:
|
||||||
|
- Run helm dependency update before the operation.
|
||||||
|
- The I(dependency_update) option require the add of C(dependencies) block in C(Chart.yaml/requirements.yaml) file.
|
||||||
|
- For more information please visit U(https://helm.sh/docs/helm/helm_dependency/)
|
||||||
|
default: false
|
||||||
|
type: bool
|
||||||
|
aliases: [ dep_up ]
|
||||||
|
version_added: "2.4.0"
|
||||||
include_crds:
|
include_crds:
|
||||||
description:
|
description:
|
||||||
- Include custom resource descriptions in rendered templates.
|
- Include custom resource descriptions in rendered templates.
|
||||||
@@ -167,6 +176,7 @@ def template(
|
|||||||
chart_ref,
|
chart_ref,
|
||||||
chart_repo_url=None,
|
chart_repo_url=None,
|
||||||
chart_version=None,
|
chart_version=None,
|
||||||
|
dependency_update=None,
|
||||||
output_dir=None,
|
output_dir=None,
|
||||||
show_only=None,
|
show_only=None,
|
||||||
release_values=None,
|
release_values=None,
|
||||||
@@ -176,6 +186,9 @@ def template(
|
|||||||
):
|
):
|
||||||
cmd += " template " + chart_ref
|
cmd += " template " + chart_ref
|
||||||
|
|
||||||
|
if dependency_update:
|
||||||
|
cmd += " --dependency-update"
|
||||||
|
|
||||||
if chart_repo_url:
|
if chart_repo_url:
|
||||||
cmd += " --repo=" + chart_repo_url
|
cmd += " --repo=" + chart_repo_url
|
||||||
|
|
||||||
@@ -215,6 +228,7 @@ def main():
|
|||||||
chart_ref=dict(type="path", required=True),
|
chart_ref=dict(type="path", required=True),
|
||||||
chart_repo_url=dict(type="str"),
|
chart_repo_url=dict(type="str"),
|
||||||
chart_version=dict(type="str"),
|
chart_version=dict(type="str"),
|
||||||
|
dependency_update=dict(type="bool", default=False, aliases=["dep_up"]),
|
||||||
include_crds=dict(type="bool", default=False),
|
include_crds=dict(type="bool", default=False),
|
||||||
output_dir=dict(type="path"),
|
output_dir=dict(type="path"),
|
||||||
release_namespace=dict(type="str"),
|
release_namespace=dict(type="str"),
|
||||||
@@ -231,6 +245,7 @@ def main():
|
|||||||
chart_ref = module.params.get("chart_ref")
|
chart_ref = module.params.get("chart_ref")
|
||||||
chart_repo_url = module.params.get("chart_repo_url")
|
chart_repo_url = module.params.get("chart_repo_url")
|
||||||
chart_version = module.params.get("chart_version")
|
chart_version = module.params.get("chart_version")
|
||||||
|
dependency_update = module.params.get("dependency_update")
|
||||||
include_crds = module.params.get("include_crds")
|
include_crds = module.params.get("include_crds")
|
||||||
output_dir = module.params.get("output_dir")
|
output_dir = module.params.get("output_dir")
|
||||||
show_only = module.params.get("show_only")
|
show_only = module.params.get("show_only")
|
||||||
@@ -251,6 +266,7 @@ def main():
|
|||||||
tmpl_cmd = template(
|
tmpl_cmd = template(
|
||||||
helm_cmd,
|
helm_cmd,
|
||||||
chart_ref,
|
chart_ref,
|
||||||
|
dependency_update=dependency_update,
|
||||||
chart_repo_url=chart_repo_url,
|
chart_repo_url=chart_repo_url,
|
||||||
chart_version=chart_version,
|
chart_version=chart_version,
|
||||||
output_dir=output_dir,
|
output_dir=output_dir,
|
||||||
|
|||||||
@@ -25,3 +25,4 @@ test_namespace:
|
|||||||
- "helm-local-path-001"
|
- "helm-local-path-001"
|
||||||
- "helm-local-path-002"
|
- "helm-local-path-002"
|
||||||
- "helm-local-path-003"
|
- "helm-local-path-003"
|
||||||
|
- "helm-dep"
|
||||||
|
|||||||
10
tests/integration/targets/helm/files/dep-up/Chart.yaml
Normal file
10
tests/integration/targets/helm/files/dep-up/Chart.yaml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: v2
|
||||||
|
name: dep_up
|
||||||
|
description: A Helm chart for molecule test
|
||||||
|
type: application
|
||||||
|
version: 0.1.0
|
||||||
|
appVersion: "default"
|
||||||
|
dependencies:
|
||||||
|
- name: test-chart
|
||||||
|
repository: file://../test-chart
|
||||||
|
version: "0.1.0"
|
||||||
2
tests/integration/targets/helm/files/dep-up/values.yaml
Normal file
2
tests/integration/targets/helm/files/dep-up/values.yaml
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
chart-test:
|
||||||
|
myValue: helm update dependency test
|
||||||
@@ -27,6 +27,9 @@
|
|||||||
- from_repository
|
- from_repository
|
||||||
- from_url
|
- from_url
|
||||||
|
|
||||||
|
- name: test helm dependency update
|
||||||
|
include_tasks: test_up_dep.yml
|
||||||
|
|
||||||
- name: Test helm plugin
|
- name: Test helm plugin
|
||||||
include_tasks: tests_helm_plugin.yml
|
include_tasks: tests_helm_plugin.yml
|
||||||
|
|
||||||
|
|||||||
171
tests/integration/targets/helm/tasks/test_up_dep.yml
Normal file
171
tests/integration/targets/helm/tasks/test_up_dep.yml
Normal file
@@ -0,0 +1,171 @@
|
|||||||
|
# Helm module
|
||||||
|
- name: "Test dependency update for helm module"
|
||||||
|
block:
|
||||||
|
- name: copy chart
|
||||||
|
copy:
|
||||||
|
src: "{{ item }}"
|
||||||
|
dest: /tmp
|
||||||
|
loop:
|
||||||
|
- test-chart
|
||||||
|
- dep-up
|
||||||
|
|
||||||
|
- set_fact:
|
||||||
|
helm_namespace: "{{ test_namespace[10] }}"
|
||||||
|
|
||||||
|
- name: "Test chart with dependency_update false"
|
||||||
|
helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
name: test
|
||||||
|
chart_ref: "/tmp/test-chart"
|
||||||
|
chart_version: "{{ chart_source_version | default(omit) }}"
|
||||||
|
namespace: "{{ helm_namespace }}"
|
||||||
|
dependency_update: false
|
||||||
|
create_namespace: yes
|
||||||
|
register: release
|
||||||
|
|
||||||
|
- name: "Get stats of the subchart"
|
||||||
|
stat:
|
||||||
|
path: "/tmp/test-chart/Chart.lock"
|
||||||
|
register: stat_result
|
||||||
|
|
||||||
|
- name: "Check if the subchart not exist in chart"
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- not stat_result.stat.exists
|
||||||
|
success_msg: "subchart not exist in the chart directory"
|
||||||
|
fail_msg: "subchart exist in the charts directory"
|
||||||
|
|
||||||
|
- name: "Test chart without dependencies block and dependency_update true"
|
||||||
|
helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
name: test
|
||||||
|
chart_ref: "/tmp/test-chart"
|
||||||
|
chart_version: "{{ chart_source_version | default(omit) }}"
|
||||||
|
namespace: "{{ helm_namespace }}"
|
||||||
|
create_namespace: yes
|
||||||
|
dependency_update: true
|
||||||
|
ignore_errors: true
|
||||||
|
register: release
|
||||||
|
|
||||||
|
- assert:
|
||||||
|
that:
|
||||||
|
- release.warnings[0] == "There is no dependencies block defined in Chart.yaml. Dependency update will not be performed. Please consider add dependencies block or disable dependency_update to remove this warning."
|
||||||
|
success_msg: "warning when there is no dependencies block with dependency_update enabled"
|
||||||
|
|
||||||
|
- name: "Test chart with dependencies block and dependency_update true"
|
||||||
|
helm:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
name: test
|
||||||
|
chart_ref: "/tmp/dep-up"
|
||||||
|
chart_version: "{{ chart_source_version | default(omit) }}"
|
||||||
|
namespace: "{{ helm_namespace }}"
|
||||||
|
dependency_update: true
|
||||||
|
create_namespace: yes
|
||||||
|
register: release
|
||||||
|
|
||||||
|
- name: "Get stats of the subchart"
|
||||||
|
stat:
|
||||||
|
path: "/tmp/dep-up/Chart.lock"
|
||||||
|
register: stat_result
|
||||||
|
|
||||||
|
- name: "Check if the subchart exists in chart"
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- stat_result.stat.exists
|
||||||
|
success_msg: "subchart exist in the chart directory"
|
||||||
|
fail_msg: "subchart not exist in the charts directory"
|
||||||
|
always:
|
||||||
|
- name: Remove helm namespace
|
||||||
|
k8s:
|
||||||
|
api_version: v1
|
||||||
|
kind: Namespace
|
||||||
|
name: "{{ helm_namespace }}"
|
||||||
|
state: absent
|
||||||
|
wait: true
|
||||||
|
wait_timeout: 180
|
||||||
|
|
||||||
|
- name: "Remove charts"
|
||||||
|
file:
|
||||||
|
state: absent
|
||||||
|
path: "/tmp/{{ item }}"
|
||||||
|
loop:
|
||||||
|
- test-chart
|
||||||
|
- dep-up
|
||||||
|
|
||||||
|
# Helm_template module
|
||||||
|
- name: "Test dependency update for helm_template module"
|
||||||
|
block:
|
||||||
|
- name: copy chart
|
||||||
|
copy:
|
||||||
|
src: "{{ item }}"
|
||||||
|
dest: /tmp
|
||||||
|
loop:
|
||||||
|
- test-chart
|
||||||
|
- dep-up
|
||||||
|
|
||||||
|
- name: Test Helm dependency update true
|
||||||
|
helm_template:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "/tmp/dep-up"
|
||||||
|
chart_version: "{{ chart_source_version | default(omit) }}"
|
||||||
|
dependency_update: true
|
||||||
|
output_dir: "/tmp"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: "Get stats of the subchart"
|
||||||
|
stat:
|
||||||
|
path: "{{ item }}"
|
||||||
|
register: stat_result
|
||||||
|
loop:
|
||||||
|
- /tmp/dep-up/Chart.lock
|
||||||
|
- /tmp/dep_up/charts/test-chart/templates/configmap.yaml
|
||||||
|
|
||||||
|
- name: "Check if the subchart exist in chart"
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- stat_result.results[0].stat.exists
|
||||||
|
- stat_result.results[1].stat.exists
|
||||||
|
success_msg: "subchart exist in the charts directory"
|
||||||
|
fail_msg: "There is no Subchart pulled"
|
||||||
|
|
||||||
|
- name: Test Helm subchart not pulled when dependency_update false for helm_template
|
||||||
|
helm_template:
|
||||||
|
binary_path: "{{ helm_binary }}"
|
||||||
|
chart_ref: "/tmp/test-chart"
|
||||||
|
chart_version: "{{ chart_source_version | default(omit) }}"
|
||||||
|
dependency_update: false
|
||||||
|
output_dir: "/tmp"
|
||||||
|
register: result
|
||||||
|
|
||||||
|
- name: "Get stats of the subchart"
|
||||||
|
stat:
|
||||||
|
path: "{{ item }}"
|
||||||
|
register: stat_result
|
||||||
|
loop:
|
||||||
|
- /tmp/test-chart/Chart.lock
|
||||||
|
- /tmp/test-chart/templates/configmap.yaml
|
||||||
|
|
||||||
|
- name: "Check if the subchart not exist in chart"
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- not stat_result.results[0].stat.exists
|
||||||
|
- stat_result.results[1].stat.exists
|
||||||
|
success_msg: "subchart not exist in the charts directory"
|
||||||
|
fail_msg: "There is no Subchart pulled"
|
||||||
|
always:
|
||||||
|
- name: Remove helm namespace
|
||||||
|
k8s:
|
||||||
|
api_version: v1
|
||||||
|
kind: Namespace
|
||||||
|
name: "{{ helm_namespace }}"
|
||||||
|
state: absent
|
||||||
|
wait: true
|
||||||
|
wait_timeout: 180
|
||||||
|
|
||||||
|
- name: "Remove charts"
|
||||||
|
file:
|
||||||
|
state: absent
|
||||||
|
path: "/tmp/{{ item }}"
|
||||||
|
loop:
|
||||||
|
- test-chart
|
||||||
|
- dep-up
|
||||||
103
tests/unit/modules/test_helm_template_module.py
Normal file
103
tests/unit/modules/test_helm_template_module.py
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright: (c) 2021, Ansible Project
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from unittest.mock import patch
|
||||||
|
|
||||||
|
from ansible.module_utils import basic
|
||||||
|
from ansible_collections.kubernetes.core.plugins.modules import helm_template
|
||||||
|
from ansible_collections.kubernetes.core.tests.unit.utils.ansible_module_mock import (
|
||||||
|
AnsibleFailJson,
|
||||||
|
AnsibleExitJson,
|
||||||
|
exit_json,
|
||||||
|
fail_json,
|
||||||
|
get_bin_path,
|
||||||
|
set_module_args,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDependencyUpdateWithoutChartRepoUrlOption(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.mock_module_helper = patch.multiple(
|
||||||
|
basic.AnsibleModule,
|
||||||
|
exit_json=exit_json,
|
||||||
|
fail_json=fail_json,
|
||||||
|
get_bin_path=get_bin_path,
|
||||||
|
)
|
||||||
|
self.mock_module_helper.start()
|
||||||
|
|
||||||
|
# Stop the patch after test execution
|
||||||
|
# like tearDown but executed also when the setup failed
|
||||||
|
self.addCleanup(self.mock_module_helper.stop)
|
||||||
|
|
||||||
|
def test_module_fail_when_required_args_missing(self):
|
||||||
|
with self.assertRaises(AnsibleFailJson):
|
||||||
|
set_module_args({})
|
||||||
|
helm_template.main()
|
||||||
|
|
||||||
|
def test_dependency_update_option_not_defined(self):
|
||||||
|
set_module_args({"chart_ref": "/tmp/path"})
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = (
|
||||||
|
0,
|
||||||
|
"configuration updated",
|
||||||
|
"",
|
||||||
|
) # successful execution
|
||||||
|
with self.assertRaises(AnsibleExitJson) as result:
|
||||||
|
helm_template.main()
|
||||||
|
mock_run_command.assert_called_once_with(
|
||||||
|
"/usr/bin/helm template /tmp/path", environ_update={}
|
||||||
|
)
|
||||||
|
assert result.exception.args[0]["command"] == "/usr/bin/helm template /tmp/path"
|
||||||
|
|
||||||
|
def test_dependency_update_option_false(self):
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"chart_ref": "test",
|
||||||
|
"chart_repo_url": "https://charts.com/test",
|
||||||
|
"dependency_update": False,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = (
|
||||||
|
0,
|
||||||
|
"configuration updated",
|
||||||
|
"",
|
||||||
|
) # successful execution
|
||||||
|
with self.assertRaises(AnsibleExitJson) as result:
|
||||||
|
helm_template.main()
|
||||||
|
mock_run_command.assert_called_once_with(
|
||||||
|
"/usr/bin/helm template test --repo=https://charts.com/test",
|
||||||
|
environ_update={},
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
result.exception.args[0]["command"]
|
||||||
|
== "/usr/bin/helm template test --repo=https://charts.com/test"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_dependency_update_option_true(self):
|
||||||
|
set_module_args(
|
||||||
|
{"chart_ref": "https://charts/example.tgz", "dependency_update": True}
|
||||||
|
)
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = (
|
||||||
|
0,
|
||||||
|
"configuration updated",
|
||||||
|
"",
|
||||||
|
) # successful execution
|
||||||
|
with self.assertRaises(AnsibleExitJson) as result:
|
||||||
|
helm_template.main()
|
||||||
|
mock_run_command.assert_called_once_with(
|
||||||
|
"/usr/bin/helm template https://charts/example.tgz --dependency-update",
|
||||||
|
environ_update={},
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
result.exception.args[0]["command"]
|
||||||
|
== "/usr/bin/helm template https://charts/example.tgz --dependency-update"
|
||||||
|
)
|
||||||
497
tests/unit/modules/test_module_helm.py
Normal file
497
tests/unit/modules/test_module_helm.py
Normal file
@@ -0,0 +1,497 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright: (c) 2021, Ansible Project
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
from unittest.mock import MagicMock, patch, call
|
||||||
|
|
||||||
|
from ansible.module_utils import basic
|
||||||
|
from ansible_collections.kubernetes.core.plugins.modules import helm
|
||||||
|
from ansible_collections.kubernetes.core.tests.unit.utils.ansible_module_mock import (
|
||||||
|
AnsibleFailJson,
|
||||||
|
AnsibleExitJson,
|
||||||
|
exit_json,
|
||||||
|
fail_json,
|
||||||
|
get_bin_path,
|
||||||
|
set_module_args,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDependencyUpdateWithoutChartRepoUrlOption(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.mock_module_helper = patch.multiple(
|
||||||
|
basic.AnsibleModule,
|
||||||
|
exit_json=exit_json,
|
||||||
|
fail_json=fail_json,
|
||||||
|
get_bin_path=get_bin_path,
|
||||||
|
)
|
||||||
|
self.mock_module_helper.start()
|
||||||
|
|
||||||
|
# Stop the patch after test execution
|
||||||
|
# like tearDown but executed also when the setup failed
|
||||||
|
self.addCleanup(self.mock_module_helper.stop)
|
||||||
|
|
||||||
|
self.chart_info_without_dep = {
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"appVersion": "default",
|
||||||
|
"description": "A chart used in molecule tests",
|
||||||
|
"name": "test-chart",
|
||||||
|
"type": "application",
|
||||||
|
"version": "0.1.0",
|
||||||
|
}
|
||||||
|
|
||||||
|
self.chart_info_with_dep = {
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"appVersion": "default",
|
||||||
|
"description": "A chart used in molecule tests",
|
||||||
|
"name": "test-chart",
|
||||||
|
"type": "application",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"dependencies": [
|
||||||
|
{
|
||||||
|
"name": "test",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"repository": "file://../test-chart",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_module_fail_when_required_args_missing(self):
|
||||||
|
with self.assertRaises(AnsibleFailJson):
|
||||||
|
set_module_args({})
|
||||||
|
helm.main()
|
||||||
|
|
||||||
|
def test_dependency_update_option_not_defined(self):
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"release_name": "test",
|
||||||
|
"release_namespace": "test",
|
||||||
|
"chart_ref": "/tmp/path",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
helm.get_release_status = MagicMock(return_value=None)
|
||||||
|
helm.fetch_chart_info = MagicMock(return_value=self.chart_info_without_dep)
|
||||||
|
helm.run_dep_update = MagicMock()
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = (
|
||||||
|
0,
|
||||||
|
"configuration updated",
|
||||||
|
"",
|
||||||
|
) # successful execution
|
||||||
|
with self.assertRaises(AnsibleExitJson) as result:
|
||||||
|
helm.main()
|
||||||
|
helm.run_dep_update.assert_not_called()
|
||||||
|
mock_run_command.assert_called_once_with(
|
||||||
|
"/usr/bin/helm upgrade -i --reset-values test /tmp/path",
|
||||||
|
environ_update={"HELM_NAMESPACE": "test"},
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
result.exception.args[0]["command"]
|
||||||
|
== "/usr/bin/helm upgrade -i --reset-values test /tmp/path"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_dependency_update_option_false(self):
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"release_name": "test",
|
||||||
|
"release_namespace": "test",
|
||||||
|
"chart_ref": "/tmp/path",
|
||||||
|
"dependency_update": False,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
helm.get_release_status = MagicMock(return_value=None)
|
||||||
|
helm.fetch_chart_info = MagicMock(return_value=self.chart_info_without_dep)
|
||||||
|
helm.run_dep_update = MagicMock()
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = (
|
||||||
|
0,
|
||||||
|
"configuration updated",
|
||||||
|
"",
|
||||||
|
) # successful execution
|
||||||
|
with self.assertRaises(AnsibleExitJson) as result:
|
||||||
|
helm.main()
|
||||||
|
helm.run_dep_update.assert_not_called()
|
||||||
|
mock_run_command.assert_called_once_with(
|
||||||
|
"/usr/bin/helm upgrade -i --reset-values test /tmp/path",
|
||||||
|
environ_update={"HELM_NAMESPACE": "test"},
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
result.exception.args[0]["command"]
|
||||||
|
== "/usr/bin/helm upgrade -i --reset-values test /tmp/path"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_dependency_update_option_true(self):
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"release_name": "test",
|
||||||
|
"release_namespace": "test",
|
||||||
|
"chart_ref": "/tmp/path",
|
||||||
|
"dependency_update": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
helm.get_release_status = MagicMock(return_value=None)
|
||||||
|
helm.fetch_chart_info = MagicMock(return_value=self.chart_info_with_dep)
|
||||||
|
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = 0, "configuration updated", ""
|
||||||
|
with patch.object(basic.AnsibleModule, "warn") as mock_warn:
|
||||||
|
with self.assertRaises(AnsibleExitJson) as result:
|
||||||
|
helm.main()
|
||||||
|
mock_warn.assert_not_called()
|
||||||
|
mock_run_command.assert_has_calls(
|
||||||
|
[
|
||||||
|
call(
|
||||||
|
"/usr/bin/helm upgrade -i --reset-values test /tmp/path",
|
||||||
|
environ_update={"HELM_NAMESPACE": "test"},
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
result.exception.args[0]["command"]
|
||||||
|
== "/usr/bin/helm upgrade -i --reset-values test /tmp/path"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_dependency_update_option_true_without_dependencies_block(self):
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"release_name": "test",
|
||||||
|
"release_namespace": "test",
|
||||||
|
"chart_ref": "/tmp/path",
|
||||||
|
"dependency_update": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
helm.get_release_status = MagicMock(return_value=None)
|
||||||
|
helm.fetch_chart_info = MagicMock(return_value=self.chart_info_without_dep)
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = (
|
||||||
|
0,
|
||||||
|
"configuration updated",
|
||||||
|
"",
|
||||||
|
) # successful execution
|
||||||
|
with patch.object(basic.AnsibleModule, "warn") as mock_warn:
|
||||||
|
with self.assertRaises(AnsibleExitJson) as result:
|
||||||
|
helm.main()
|
||||||
|
mock_warn.assert_called_once()
|
||||||
|
mock_run_command.assert_has_calls(
|
||||||
|
[
|
||||||
|
call(
|
||||||
|
"/usr/bin/helm upgrade -i --reset-values test /tmp/path",
|
||||||
|
environ_update={"HELM_NAMESPACE": "test"},
|
||||||
|
)
|
||||||
|
]
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
result.exception.args[0]["command"]
|
||||||
|
== "/usr/bin/helm upgrade -i --reset-values test /tmp/path"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDependencyUpdateWithChartRepoUrlOption(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.mock_module_helper = patch.multiple(
|
||||||
|
basic.AnsibleModule,
|
||||||
|
exit_json=exit_json,
|
||||||
|
fail_json=fail_json,
|
||||||
|
get_bin_path=get_bin_path,
|
||||||
|
)
|
||||||
|
self.mock_module_helper.start()
|
||||||
|
|
||||||
|
# Stop the patch after test execution
|
||||||
|
# like tearDown but executed also when the setup failed
|
||||||
|
self.addCleanup(self.mock_module_helper.stop)
|
||||||
|
|
||||||
|
self.chart_info_without_dep = {
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"appVersion": "default",
|
||||||
|
"description": "A chart used in molecule tests",
|
||||||
|
"name": "test-chart",
|
||||||
|
"type": "application",
|
||||||
|
"version": "0.1.0",
|
||||||
|
}
|
||||||
|
|
||||||
|
self.chart_info_with_dep = {
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"appVersion": "default",
|
||||||
|
"description": "A chart used in molecule tests",
|
||||||
|
"name": "test-chart",
|
||||||
|
"type": "application",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"dependencies": [
|
||||||
|
{
|
||||||
|
"name": "test",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"repository": "file://../test-chart",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_dependency_update_option_not_defined(self):
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"release_name": "test",
|
||||||
|
"release_namespace": "test",
|
||||||
|
"chart_ref": "chart1",
|
||||||
|
"chart_repo_url": "http://repo.example/charts",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
helm.get_release_status = MagicMock(return_value=None)
|
||||||
|
helm.fetch_chart_info = MagicMock(return_value=self.chart_info_without_dep)
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = (
|
||||||
|
0,
|
||||||
|
"configuration updated",
|
||||||
|
"",
|
||||||
|
) # successful execution
|
||||||
|
with self.assertRaises(AnsibleExitJson) as result:
|
||||||
|
helm.main()
|
||||||
|
mock_run_command.assert_called_once_with(
|
||||||
|
"/usr/bin/helm --repo=http://repo.example/charts upgrade -i --reset-values test chart1",
|
||||||
|
environ_update={"HELM_NAMESPACE": "test"},
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
result.exception.args[0]["command"]
|
||||||
|
== "/usr/bin/helm --repo=http://repo.example/charts upgrade -i --reset-values test chart1"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_dependency_update_option_False(self):
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"release_name": "test",
|
||||||
|
"release_namespace": "test",
|
||||||
|
"chart_ref": "chart1",
|
||||||
|
"chart_repo_url": "http://repo.example/charts",
|
||||||
|
"dependency_update": False,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
helm.get_release_status = MagicMock(return_value=None)
|
||||||
|
helm.fetch_chart_info = MagicMock(return_value=self.chart_info_without_dep)
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = (
|
||||||
|
0,
|
||||||
|
"configuration updated",
|
||||||
|
"",
|
||||||
|
) # successful execution
|
||||||
|
with self.assertRaises(AnsibleExitJson) as result:
|
||||||
|
helm.main()
|
||||||
|
mock_run_command.assert_called_once_with(
|
||||||
|
"/usr/bin/helm --repo=http://repo.example/charts upgrade -i --reset-values test chart1",
|
||||||
|
environ_update={"HELM_NAMESPACE": "test"},
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
result.exception.args[0]["command"]
|
||||||
|
== "/usr/bin/helm --repo=http://repo.example/charts upgrade -i --reset-values test chart1"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_dependency_update_option_True_and_replace_option_disabled(self):
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"release_name": "test",
|
||||||
|
"release_namespace": "test",
|
||||||
|
"chart_ref": "chart1",
|
||||||
|
"chart_repo_url": "http://repo.example/charts",
|
||||||
|
"dependency_update": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
helm.get_release_status = MagicMock(return_value=None)
|
||||||
|
helm.fetch_chart_info = MagicMock(return_value=self.chart_info_with_dep)
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = (
|
||||||
|
0,
|
||||||
|
"configuration updated",
|
||||||
|
"",
|
||||||
|
) # successful execution
|
||||||
|
with self.assertRaises(AnsibleFailJson) as result:
|
||||||
|
helm.main()
|
||||||
|
# mock_run_command.assert_called_once_with('/usr/bin/helm --repo=http://repo.example/charts upgrade -i --reset-values test chart1',
|
||||||
|
# environ_update={'HELM_NAMESPACE': 'test'})
|
||||||
|
assert result.exception.args[0]["msg"] == (
|
||||||
|
"'--dependency-update' hasn't been supported yet with 'helm upgrade'. "
|
||||||
|
"Please use 'helm install' instead by adding 'replace' option"
|
||||||
|
)
|
||||||
|
assert result.exception.args[0]["failed"]
|
||||||
|
|
||||||
|
def test_dependency_update_option_True_and_replace_option_enabled(self):
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"release_name": "test",
|
||||||
|
"release_namespace": "test",
|
||||||
|
"chart_ref": "chart1",
|
||||||
|
"chart_repo_url": "http://repo.example/charts",
|
||||||
|
"dependency_update": True,
|
||||||
|
"replace": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
helm.get_release_status = MagicMock(return_value=None)
|
||||||
|
helm.fetch_chart_info = MagicMock(return_value=self.chart_info_without_dep)
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = (
|
||||||
|
0,
|
||||||
|
"configuration updated",
|
||||||
|
"",
|
||||||
|
) # successful execution
|
||||||
|
with self.assertRaises(AnsibleExitJson) as result:
|
||||||
|
helm.main()
|
||||||
|
mock_run_command.assert_called_once_with(
|
||||||
|
"/usr/bin/helm --repo=http://repo.example/charts install --dependency-update --replace test chart1",
|
||||||
|
environ_update={"HELM_NAMESPACE": "test"},
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
result.exception.args[0]["command"]
|
||||||
|
== "/usr/bin/helm --repo=http://repo.example/charts install --dependency-update --replace test chart1"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class TestDependencyUpdateWithChartRefIsUrl(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
self.mock_module_helper = patch.multiple(
|
||||||
|
basic.AnsibleModule,
|
||||||
|
exit_json=exit_json,
|
||||||
|
fail_json=fail_json,
|
||||||
|
get_bin_path=get_bin_path,
|
||||||
|
)
|
||||||
|
self.mock_module_helper.start()
|
||||||
|
|
||||||
|
# Stop the patch after test execution
|
||||||
|
# like tearDown but executed also when the setup failed
|
||||||
|
self.addCleanup(self.mock_module_helper.stop)
|
||||||
|
|
||||||
|
self.chart_info_without_dep = {
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"appVersion": "default",
|
||||||
|
"description": "A chart used in molecule tests",
|
||||||
|
"name": "test-chart",
|
||||||
|
"type": "application",
|
||||||
|
"version": "0.1.0",
|
||||||
|
}
|
||||||
|
|
||||||
|
self.chart_info_with_dep = {
|
||||||
|
"apiVersion": "v2",
|
||||||
|
"appVersion": "default",
|
||||||
|
"description": "A chart used in molecule tests",
|
||||||
|
"name": "test-chart",
|
||||||
|
"type": "application",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"dependencies": [
|
||||||
|
{
|
||||||
|
"name": "test",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"repository": "file://../test-chart",
|
||||||
|
}
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_dependency_update_option_not_defined(self):
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"release_name": "test",
|
||||||
|
"release_namespace": "test",
|
||||||
|
"chart_ref": "http://repo.example/charts/application.tgz",
|
||||||
|
}
|
||||||
|
)
|
||||||
|
helm.get_release_status = MagicMock(return_value=None)
|
||||||
|
helm.fetch_chart_info = MagicMock(return_value=self.chart_info_without_dep)
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = (
|
||||||
|
0,
|
||||||
|
"configuration updated",
|
||||||
|
"",
|
||||||
|
) # successful execution
|
||||||
|
with self.assertRaises(AnsibleExitJson) as result:
|
||||||
|
helm.main()
|
||||||
|
mock_run_command.assert_called_once_with(
|
||||||
|
"/usr/bin/helm upgrade -i --reset-values test http://repo.example/charts/application.tgz",
|
||||||
|
environ_update={"HELM_NAMESPACE": "test"},
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
result.exception.args[0]["command"]
|
||||||
|
== "/usr/bin/helm upgrade -i --reset-values test http://repo.example/charts/application.tgz"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_dependency_update_option_False(self):
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"release_name": "test",
|
||||||
|
"release_namespace": "test",
|
||||||
|
"chart_ref": "http://repo.example/charts/application.tgz",
|
||||||
|
"dependency_update": False,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
helm.get_release_status = MagicMock(return_value=None)
|
||||||
|
helm.fetch_chart_info = MagicMock(return_value=self.chart_info_without_dep)
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = (
|
||||||
|
0,
|
||||||
|
"configuration updated",
|
||||||
|
"",
|
||||||
|
) # successful execution
|
||||||
|
with self.assertRaises(AnsibleExitJson) as result:
|
||||||
|
helm.main()
|
||||||
|
mock_run_command.assert_called_once_with(
|
||||||
|
"/usr/bin/helm upgrade -i --reset-values test http://repo.example/charts/application.tgz",
|
||||||
|
environ_update={"HELM_NAMESPACE": "test"},
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
result.exception.args[0]["command"]
|
||||||
|
== "/usr/bin/helm upgrade -i --reset-values test http://repo.example/charts/application.tgz"
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_dependency_update_option_True_and_replace_option_disabled(self):
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"release_name": "test",
|
||||||
|
"release_namespace": "test",
|
||||||
|
"chart_ref": "http://repo.example/charts/application.tgz",
|
||||||
|
"dependency_update": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
helm.get_release_status = MagicMock(return_value=None)
|
||||||
|
helm.fetch_chart_info = MagicMock(return_value=self.chart_info_with_dep)
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = (
|
||||||
|
0,
|
||||||
|
"configuration updated",
|
||||||
|
"",
|
||||||
|
) # successful execution
|
||||||
|
with self.assertRaises(AnsibleFailJson) as result:
|
||||||
|
helm.main()
|
||||||
|
# mock_run_command.assert_called_once_with('/usr/bin/helm --repo=http://repo.example/charts upgrade -i --reset-values test chart1',
|
||||||
|
# environ_update={'HELM_NAMESPACE': 'test'})
|
||||||
|
assert result.exception.args[0]["msg"] == (
|
||||||
|
"'--dependency-update' hasn't been supported yet with 'helm upgrade'. "
|
||||||
|
"Please use 'helm install' instead by adding 'replace' option"
|
||||||
|
)
|
||||||
|
assert result.exception.args[0]["failed"]
|
||||||
|
|
||||||
|
def test_dependency_update_option_True_and_replace_option_enabled(self):
|
||||||
|
set_module_args(
|
||||||
|
{
|
||||||
|
"release_name": "test",
|
||||||
|
"release_namespace": "test",
|
||||||
|
"chart_ref": "http://repo.example/charts/application.tgz",
|
||||||
|
"dependency_update": True,
|
||||||
|
"replace": True,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
helm.get_release_status = MagicMock(return_value=None)
|
||||||
|
helm.fetch_chart_info = MagicMock(return_value=self.chart_info_without_dep)
|
||||||
|
with patch.object(basic.AnsibleModule, "run_command") as mock_run_command:
|
||||||
|
mock_run_command.return_value = (
|
||||||
|
0,
|
||||||
|
"configuration updated",
|
||||||
|
"",
|
||||||
|
) # successful execution
|
||||||
|
with self.assertRaises(AnsibleExitJson) as result:
|
||||||
|
helm.main()
|
||||||
|
mock_run_command.assert_called_once_with(
|
||||||
|
"/usr/bin/helm install --dependency-update --replace test http://repo.example/charts/application.tgz",
|
||||||
|
environ_update={"HELM_NAMESPACE": "test"},
|
||||||
|
)
|
||||||
|
assert (
|
||||||
|
result.exception.args[0]["command"]
|
||||||
|
== "/usr/bin/helm install --dependency-update --replace test http://repo.example/charts/application.tgz"
|
||||||
|
)
|
||||||
59
tests/unit/utils/ansible_module_mock.py
Normal file
59
tests/unit/utils/ansible_module_mock.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Copyright: (c) 2021, Ansible Project
|
||||||
|
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
|
||||||
|
|
||||||
|
# This module maock the AnsibleModule class for more information please visite
|
||||||
|
# https://docs.ansible.com/ansible/latest/dev_guide/testing_units_modules.html#module-argument-processing
|
||||||
|
|
||||||
|
from __future__ import absolute_import, division, print_function
|
||||||
|
|
||||||
|
__metaclass__ = type
|
||||||
|
|
||||||
|
import json
|
||||||
|
|
||||||
|
from ansible.module_utils import basic
|
||||||
|
from ansible.module_utils.common.text.converters import to_bytes
|
||||||
|
|
||||||
|
|
||||||
|
def set_module_args(args):
|
||||||
|
"""prepare arguments so that they will be picked up during module creation"""
|
||||||
|
args = json.dumps({"ANSIBLE_MODULE_ARGS": args})
|
||||||
|
basic._ANSIBLE_ARGS = to_bytes(args)
|
||||||
|
|
||||||
|
|
||||||
|
class AnsibleExitJson(Exception):
|
||||||
|
"""Exception class to be raised by module.exit_json and caught by the test case"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AnsibleFailJson(Exception):
|
||||||
|
"""Exception class to be raised by module.fail_json and caught by the test case"""
|
||||||
|
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def exit_json(*args, **kwargs):
|
||||||
|
"""function to patch over exit_json; package return data into an exception"""
|
||||||
|
if "changed" not in kwargs:
|
||||||
|
kwargs["changed"] = False
|
||||||
|
raise AnsibleExitJson(kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def fail_json(*args, **kwargs):
|
||||||
|
"""function to patch over fail_json; package return data into an exception"""
|
||||||
|
kwargs["failed"] = True
|
||||||
|
raise AnsibleFailJson(kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def get_bin_path(self, arg, required=False):
|
||||||
|
"""Mock AnsibleModule.get_bin_path"""
|
||||||
|
if arg.endswith("helm"):
|
||||||
|
return "/usr/bin/helm"
|
||||||
|
else:
|
||||||
|
if required:
|
||||||
|
fail_json(msg="%r not found !" % arg)
|
||||||
|
|
||||||
|
|
||||||
|
# def warn(self,msg):
|
||||||
|
# return msg
|
||||||
Reference in New Issue
Block a user