Files
kubernetes.core/tests/unit/modules/test_module_helm.py
Yuriy Novostavskiy aee847431a helm_registry_auth module to authenticate in OCI registry (#800)
* new module helm_registry_auth

* Initial integration tests

* final update copyright and integration test before pr

* update link to pr in changelog fragment

* reformat plugins/module_utils/helm.py with black

to fix linters in actions

* attempt to fix unit test

unit test was missing initially

* fix https://pycqa.github.io/isort/ linter

* next attemp to fix unit-test

* remove unused and unsupported helm_args_common

* remove unused imports and fix other linters errors

* another fix for unit test

* fix issue introducied by commit ff02893a12a31f9c44b5c48f9a8bf85057295961

* add binary_path to arg_spec

* return helm_cmd in the output of check mode

remove changlog fragment

* description suggestion from reviewer/maintainer

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>

* description suggestion from reviewer/maintainer

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>

* description suggestion from reviewer/maintainer

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>

* description suggestion from reviewer/maintainer

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>

* description suggestion from reviewer/maintainer

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>

* description suggestion from reviewer/maintainer

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>

* description suggestion from reviewer/maintainer

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>

* description suggestion from reviewer/maintainer

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>

* remove changed from module return

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>

* remove redundant code

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>

* Update plugins/modules/helm_registry_auth.py

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>

* consider support of logout when user is not logged in

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>

* consider support helm < 3.0.0

* Revert "consider support helm < 3.0.0"

This reverts commit f20004d196.

* reintroduce support of helm version less than 3.8.0

reference: https://helm.sh/docs/topics/registries/#enabling-oci-support-prior-to-v380

* revert reintroducing support of helm < 3.8.0

reason: didn't find a quick way to deal with tests

* update documentation with the recent module updates

* Update plugins/modules/helm_registry_auth.py

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>

* add test of logout impendency

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>

* fix linters

* fix intendations in the integration tests

* create tests/integration/targets/helm_registry_auth/aliases

* fix integration test (typo)

* fix integration tests (test wrong cred)

* add stderr when module fail

* another attempt to fix integration test

* fix assertion in integration test to be not affceted by the #830

---------

Co-authored-by: Bikouo Aubin <79859644+abikouo@users.noreply.github.com>
2024-12-17 15:39:42 +01:00

507 lines
19 KiB
Python

# -*- 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, call, patch
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 (
AnsibleExitJson,
AnsibleFailJson,
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"},
data=None,
)
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"},
data=None,
)
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"},
data=None,
)
]
)
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"},
data=None,
)
]
)
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"},
data=None,
)
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"},
data=None,
)
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"},
data=None,
)
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"},
data=None,
)
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"},
data=None,
)
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"},
data=None,
)
assert (
result.exception.args[0]["command"]
== "/usr/bin/helm install --dependency-update --replace test 'http://repo.example/charts/application.tgz'"
)