Add unit and sanity tests to GHA (#614)

* Add unit and sanity tests to GHA

Signed-off-by: GomathiselviS <gomathiselvi@gmail.com>

* Fix sanity issues

* Add sanity non voting

* Add changelog

* Fix typo

* Fix typo

* Use pytest-ansible

* Add support for pytest-ansible

---------

Signed-off-by: GomathiselviS <gomathiselvi@gmail.com>
This commit is contained in:
GomathiselviS
2023-05-17 12:47:11 -04:00
committed by GitHub
parent a624251bba
commit 54d8193972
13 changed files with 230 additions and 36 deletions

View File

@@ -22,6 +22,130 @@ jobs:
uses: ansible-network/github_actions/.github/workflows/changelog.yml@main uses: ansible-network/github_actions/.github/workflows/changelog.yml@main
linters: linters:
uses: abikouo/github_actions/.github/workflows/tox-linters.yml@tox_linters uses: abikouo/github_actions/.github/workflows/tox-linters.yml@tox_linters
sanity:
uses: ansible-network/github_actions/.github/workflows/sanity.yml@main
with:
matrix_include: "[]"
matrix_exclude: >-
[
{
"ansible-version": "stable-2.9"
},
{
"ansible-version": "stable-2.12",
"python-version": "3.7"
},
{
"ansible-version": "stable-2.12",
"python-version": "3.11"
},
{
"ansible-version": "stable-2.13",
"python-version": "3.7"
},
{
"ansible-version": "stable-2.13",
"python-version": "3.11"
},
{
"ansible-version": "stable-2.14",
"python-version": "3.7"
},
{
"ansible-version": "stable-2.14",
"python-version": "3.8"
},
{
"ansible-version": "stable-2.14",
"python-version": "3.11"
},
{
"ansible-version": "stable-2.15",
"python-version": "3.7"
},
{
"ansible-version": "stable-2.15",
"python-version": "3.8"
},
{
"ansible-version": "stable-2.15",
"python-version": "3.11"
},
{
"ansible-version": "milestone",
"python-version": "3.7"
},
{
"ansible-version": "milestone",
"python-version": "3.8"
},
{
"ansible-version": "devel",
"python-version": "3.7"
},
{
"ansible-version": "devel",
"python-version": "3.8"
}
]
unit-source:
uses: ansible-network/github_actions/.github/workflows/unit_source.yml@main
with:
matrix_exclude: >-
[
{
"python-version": "3.11"
},
{
"ansible-version": "stable-2.12",
"python-version": "3.7"
},
{
"ansible-version": "stable-2.13",
"python-version": "3.7"
},
{
"ansible-version": "stable-2.12",
"python-version": "3.8"
},
{
"ansible-version": "stable-2.13",
"python-version": "3.8"
},
{
"ansible-version": "stable-2.14",
"python-version": "3.7"
},
{
"ansible-version": "stable-2.14",
"python-version": "3.8"
},
{
"ansible-version": "stable-2.15",
"python-version": "3.7"
},
{
"ansible-version": "stable-2.15",
"python-version": "3.8"
},
{
"ansible-version": "milestone",
"python-version": "3.7"
},
{
"ansible-version": "milestone",
"python-version": "3.8"
},
{
"ansible-version": "devel",
"python-version": "3.7"
},
{
"ansible-version": "devel",
"python-version": "3.8"
}
]
collection_pre_install: ''
splitter: splitter:
env: env:
source_dir: "./source" source_dir: "./source"
@@ -165,3 +289,23 @@ jobs:
ansible_test_environment: | ansible_test_environment: |
ENABLE_TURBO_MODE=${{ matrix.enable-turbo-mode }} ENABLE_TURBO_MODE=${{ matrix.enable-turbo-mode }}
if: steps.read-targets.outputs.ansible_test_targets != '' if: steps.read-targets.outputs.ansible_test_targets != ''
all_green:
if: ${{ always() }}
needs:
- changelog
- linters
- sanity
- unit-source
- integration
runs-on: ubuntu-latest
steps:
- run: >-
python -c "assert set([
'${{ needs.changelog.result }}',
'${{ needs.linters.result }}',
'${{ needs.unit-source.result }}',
'${{ needs.integration.result }}'
]) == {'success'}"
- run: >-
python -c "assert '${{ needs.sanity.result }}'
in ['success', 'failure']"

View File

@@ -0,0 +1,3 @@
---
trivial:
- add github workflow and fix sanity failures (https://github.com/ansible-collections/kubernetes.core/pull/614).

View File

@@ -52,6 +52,7 @@ options:
- If set to C(uninstalling), show releases that are currently being uninstalled. - If set to C(uninstalling), show releases that are currently being uninstalled.
type: list type: list
elements: str elements: str
default: []
version_added: "2.3.0" version_added: "2.3.0"
get_all_values: get_all_values:
description: description:

View File

@@ -98,6 +98,7 @@ options:
required: false required: false
type: list type: list
elements: str elements: str
default: []
version_added: 2.4.0 version_added: 2.4.0
values_files: values_files:
description: description:

View File

@@ -43,6 +43,7 @@ options:
type: str type: str
delete_options: delete_options:
type: dict type: dict
default: {}
description: description:
- Specify options to delete pods. - Specify options to delete pods.
- This option has effect only when C(state) is set to I(drain). - This option has effect only when C(state) is set to I(drain).

View File

@@ -38,10 +38,12 @@ options:
description: List of label selectors to use to filter results description: List of label selectors to use to filter results
type: list type: list
elements: str elements: str
default: []
field_selectors: field_selectors:
description: List of field selectors to use to filter results description: List of field selectors to use to filter results
type: list type: list
elements: str elements: str
default: []
extends_documentation_fragment: extends_documentation_fragment:
- kubernetes.core.k8s_auth_options - kubernetes.core.k8s_auth_options

View File

@@ -47,6 +47,7 @@ options:
- Only one of I(name) or I(label_selectors) may be provided. - Only one of I(name) or I(label_selectors) may be provided.
type: list type: list
elements: str elements: str
default: []
container: container:
description: description:
- Use to specify the container within a pod to grab the log from. - Use to specify the container within a pod to grab the log from.

View File

@@ -24,10 +24,12 @@ options:
description: List of label selectors to use to filter results. description: List of label selectors to use to filter results.
type: list type: list
elements: str elements: str
default: []
field_selectors: field_selectors:
description: List of field selectors to use to filter results. description: List of field selectors to use to filter results.
type: list type: list
elements: str elements: str
default: []
extends_documentation_fragment: extends_documentation_fragment:
- kubernetes.core.k8s_auth_options - kubernetes.core.k8s_auth_options
- kubernetes.core.k8s_name_options - kubernetes.core.k8s_name_options

View File

@@ -36,6 +36,7 @@ options:
description: List of label selectors to use to filter results. description: List of label selectors to use to filter results.
type: list type: list
elements: str elements: str
default: []
version_added: 2.0.0 version_added: 2.0.0
continue_on_error: continue_on_error:
description: description:

View File

@@ -6,3 +6,4 @@ pytest-xdist
pytest-mock pytest-mock
pytest-forked pytest-forked
virtualenv virtualenv
pytest-ansible

View File

@@ -16,11 +16,13 @@ plugins/module_utils/k8sdynamicclient.py import-3.8!skip
plugins/module_utils/k8sdynamicclient.py import-3.9!skip plugins/module_utils/k8sdynamicclient.py import-3.9!skip
plugins/module_utils/k8sdynamicclient.py import-3.10!skip plugins/module_utils/k8sdynamicclient.py import-3.10!skip
plugins/module_utils/k8sdynamicclient.py import-3.11!skip plugins/module_utils/k8sdynamicclient.py import-3.11!skip
plugins/module_utils/version.py pylint!skip
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc
plugins/modules/k8s_service.py validate-modules:parameter-type-not-in-doc plugins/modules/k8s_service.py validate-modules:parameter-type-not-in-doc
tests/unit/module_utils/fixtures/definitions.yml yamllint!skip tests/unit/module_utils/fixtures/definitions.yml yamllint!skip
tests/unit/module_utils/fixtures/deployments.yml yamllint!skip tests/unit/module_utils/fixtures/deployments.yml yamllint!skip
tests/integration/targets/k8s_delete/files/deployments.yaml yamllint!skip
tests/unit/module_utils/fixtures/pods.yml yamllint!skip tests/unit/module_utils/fixtures/pods.yml yamllint!skip
tests/integration/targets/helm/files/appversionless-chart-v2/templates/configmap.yaml yamllint!skip tests/integration/targets/helm/files/appversionless-chart-v2/templates/configmap.yaml yamllint!skip
tests/integration/targets/helm/files/appversionless-chart/templates/configmap.yaml yamllint!skip tests/integration/targets/helm/files/appversionless-chart/templates/configmap.yaml yamllint!skip

View File

@@ -0,0 +1,35 @@
plugins/module_utils/client/discovery.py import-3.6!skip
plugins/module_utils/client/discovery.py import-3.7!skip
plugins/module_utils/client/discovery.py import-3.8!skip
plugins/module_utils/client/discovery.py import-3.9!skip
plugins/module_utils/client/discovery.py import-3.10!skip
plugins/module_utils/client/discovery.py import-3.11!skip
plugins/module_utils/client/resource.py import-3.6!skip
plugins/module_utils/client/resource.py import-3.7!skip
plugins/module_utils/client/resource.py import-3.8!skip
plugins/module_utils/client/resource.py import-3.9!skip
plugins/module_utils/client/resource.py import-3.10!skip
plugins/module_utils/client/resource.py import-3.11!skip
plugins/module_utils/k8sdynamicclient.py import-3.6!skip
plugins/module_utils/k8sdynamicclient.py import-3.7!skip
plugins/module_utils/k8sdynamicclient.py import-3.8!skip
plugins/module_utils/k8sdynamicclient.py import-3.9!skip
plugins/module_utils/k8sdynamicclient.py import-3.10!skip
plugins/module_utils/k8sdynamicclient.py import-3.11!skip
plugins/modules/k8s.py validate-modules:parameter-type-not-in-doc
plugins/modules/k8s_scale.py validate-modules:parameter-type-not-in-doc
plugins/modules/k8s_service.py validate-modules:parameter-type-not-in-doc
tests/unit/module_utils/fixtures/definitions.yml yamllint!skip
tests/unit/module_utils/fixtures/deployments.yml yamllint!skip
tests/unit/module_utils/fixtures/pods.yml yamllint!skip
tests/integration/targets/helm/files/appversionless-chart-v2/templates/configmap.yaml yamllint!skip
tests/integration/targets/helm/files/appversionless-chart/templates/configmap.yaml yamllint!skip
tests/integration/targets/helm/files/test-chart-v2/templates/configmap.yaml yamllint!skip
tests/integration/targets/helm/files/test-chart/templates/configmap.yaml yamllint!skip
tests/integration/targets/helm_diff/files/test-chart/templates/configmap.yaml yamllint!skip
tests/integration/targets/k8s_scale/files/deployment.yaml yamllint!skip
tests/sanity/refresh_ignore_files shebang!skip
plugins/modules/k8s.py validate-modules:return-syntax-error
plugins/modules/k8s_scale.py validate-modules:return-syntax-error
plugins/modules/k8s_service.py validate-modules:return-syntax-error
plugins/modules/k8s_taint.py validate-modules:return-syntax-error

View File

@@ -22,7 +22,7 @@ import string
@pytest.fixture() @pytest.fixture()
def ansible_helm_module(): def _ansible_helm_module():
module = MagicMock() module = MagicMock()
module.params = { module.params = {
"api_key": None, "api_key": None,
@@ -139,31 +139,31 @@ def test_module_get_helm_binary_from_system():
assert helm_module.get_helm_binary() == helm_sys_binary_path assert helm_module.get_helm_binary() == helm_sys_binary_path
def test_module_get_helm_plugin_list(ansible_helm_module): def test_module_get_helm_plugin_list(_ansible_helm_module):
ansible_helm_module.run_helm_command = MagicMock() _ansible_helm_module.run_helm_command = MagicMock()
ansible_helm_module.run_helm_command.return_value = (0, "output", "error") _ansible_helm_module.run_helm_command.return_value = (0, "output", "error")
rc, out, err, command = ansible_helm_module.get_helm_plugin_list() rc, out, err, command = _ansible_helm_module.get_helm_plugin_list()
assert (rc, out, err) == (0, "output", "error") assert (rc, out, err) == (0, "output", "error")
assert command == "some/path/to/helm/executable plugin list" assert command == "some/path/to/helm/executable plugin list"
ansible_helm_module.get_helm_binary.assert_called_once() _ansible_helm_module.get_helm_binary.assert_called_once()
ansible_helm_module.run_helm_command.assert_called_once_with( _ansible_helm_module.run_helm_command.assert_called_once_with(
"some/path/to/helm/executable plugin list" "some/path/to/helm/executable plugin list"
) )
def test_module_get_helm_plugin_list_failure(ansible_helm_module): def test_module_get_helm_plugin_list_failure(_ansible_helm_module):
ansible_helm_module.run_helm_command = MagicMock() _ansible_helm_module.run_helm_command = MagicMock()
ansible_helm_module.run_helm_command.return_value = (-1, "output", "error") _ansible_helm_module.run_helm_command.return_value = (-1, "output", "error")
with pytest.raises(SystemExit): with pytest.raises(SystemExit):
ansible_helm_module.get_helm_plugin_list() _ansible_helm_module.get_helm_plugin_list()
ansible_helm_module.fail_json.assert_called_once_with( _ansible_helm_module.fail_json.assert_called_once_with(
msg="Failed to get Helm plugin info", msg="Failed to get Helm plugin info",
command="some/path/to/helm/executable plugin list", command="some/path/to/helm/executable plugin list",
stdout="output", stdout="output",
@@ -174,7 +174,7 @@ def test_module_get_helm_plugin_list_failure(ansible_helm_module):
@pytest.mark.parametrize("no_values", [True, False]) @pytest.mark.parametrize("no_values", [True, False])
@pytest.mark.parametrize("get_all", [True, False]) @pytest.mark.parametrize("get_all", [True, False])
def test_module_get_values(ansible_helm_module, no_values, get_all): def test_module_get_values(_ansible_helm_module, no_values, get_all):
expected = {"test": "units"} expected = {"test": "units"}
output = "---\ntest: units\n" output = "---\ntest: units\n"
@@ -183,19 +183,19 @@ def test_module_get_values(ansible_helm_module, no_values, get_all):
expected = {} expected = {}
output = "null" output = "null"
ansible_helm_module.run_helm_command = MagicMock() _ansible_helm_module.run_helm_command = MagicMock()
ansible_helm_module.run_helm_command.return_value = (0, output, "error") _ansible_helm_module.run_helm_command.return_value = (0, output, "error")
release_name = "".join( release_name = "".join(
random.choice(string.ascii_letters + string.digits) for x in range(10) random.choice(string.ascii_letters + string.digits) for x in range(10)
) )
result = ansible_helm_module.get_values(release_name, get_all=get_all) result = _ansible_helm_module.get_values(release_name, get_all=get_all)
ansible_helm_module.get_helm_binary.assert_called_once() _ansible_helm_module.get_helm_binary.assert_called_once()
command = f"some/path/to/helm/executable get values --output=yaml {release_name}" command = f"some/path/to/helm/executable get values --output=yaml {release_name}"
if get_all: if get_all:
command += " -a" command += " -a"
ansible_helm_module.run_helm_command.assert_called_once_with(command) _ansible_helm_module.run_helm_command.assert_called_once_with(command)
assert result == expected assert result == expected
@@ -210,20 +210,20 @@ def test_module_get_values(ansible_helm_module, no_values, get_all):
('Client: &version.Version{SemVer:"v3.12.3"', None), ('Client: &version.Version{SemVer:"v3.12.3"', None),
], ],
) )
def test_module_get_helm_version(ansible_helm_module, output, expected): def test_module_get_helm_version(_ansible_helm_module, output, expected):
ansible_helm_module.run_command = MagicMock() _ansible_helm_module.run_command = MagicMock()
ansible_helm_module.run_command.return_value = (0, output, "error") _ansible_helm_module.run_command.return_value = (0, output, "error")
result = ansible_helm_module.get_helm_version() result = _ansible_helm_module.get_helm_version()
ansible_helm_module.get_helm_binary.assert_called_once() _ansible_helm_module.get_helm_binary.assert_called_once()
command = "some/path/to/helm/executable version" command = "some/path/to/helm/executable version"
ansible_helm_module.run_command.assert_called_once_with(command) _ansible_helm_module.run_command.assert_called_once_with(command)
assert result == expected assert result == expected
def test_module_run_helm_command(ansible_helm_module): def test_module_run_helm_command(_ansible_helm_module):
error = "".join( error = "".join(
random.choice(string.ascii_letters + string.digits) for x in range(10) random.choice(string.ascii_letters + string.digits) for x in range(10)
@@ -232,26 +232,26 @@ def test_module_run_helm_command(ansible_helm_module):
random.choice(string.ascii_letters + string.digits) for x in range(10) random.choice(string.ascii_letters + string.digits) for x in range(10)
) )
ansible_helm_module.run_command.return_value = (0, output, error) _ansible_helm_module.run_command.return_value = (0, output, error)
ansible_helm_module._prepare_helm_environment = MagicMock() _ansible_helm_module._prepare_helm_environment = MagicMock()
env_update = {x: random.choice(string.ascii_letters) for x in range(10)} env_update = {x: random.choice(string.ascii_letters) for x in range(10)}
ansible_helm_module._prepare_helm_environment.return_value = env_update _ansible_helm_module._prepare_helm_environment.return_value = env_update
command = "".join( command = "".join(
random.choice(string.ascii_letters + string.digits) for x in range(10) random.choice(string.ascii_letters + string.digits) for x in range(10)
) )
rc, out, err = ansible_helm_module.run_helm_command(command) rc, out, err = _ansible_helm_module.run_helm_command(command)
assert (rc, out, err) == (0, output, error) assert (rc, out, err) == (0, output, error)
ansible_helm_module.run_command.assert_called_once_with( _ansible_helm_module.run_command.assert_called_once_with(
command, environ_update=env_update command, environ_update=env_update
) )
@pytest.mark.parametrize("fails_on_error", [True, False]) @pytest.mark.parametrize("fails_on_error", [True, False])
def test_module_run_helm_command_failure(ansible_helm_module, fails_on_error): def test_module_run_helm_command_failure(_ansible_helm_module, fails_on_error):
error = "".join( error = "".join(
random.choice(string.ascii_letters + string.digits) for x in range(10) random.choice(string.ascii_letters + string.digits) for x in range(10)
@@ -260,9 +260,9 @@ def test_module_run_helm_command_failure(ansible_helm_module, fails_on_error):
random.choice(string.ascii_letters + string.digits) for x in range(10) random.choice(string.ascii_letters + string.digits) for x in range(10)
) )
return_code = random.randint(1, 10) return_code = random.randint(1, 10)
ansible_helm_module.run_command.return_value = (return_code, output, error) _ansible_helm_module.run_command.return_value = (return_code, output, error)
ansible_helm_module._prepare_environment = MagicMock() _ansible_helm_module._prepare_environment = MagicMock()
command = "".join( command = "".join(
random.choice(string.ascii_letters + string.digits) for x in range(10) random.choice(string.ascii_letters + string.digits) for x in range(10)
@@ -270,10 +270,10 @@ def test_module_run_helm_command_failure(ansible_helm_module, fails_on_error):
if fails_on_error: if fails_on_error:
with pytest.raises(SystemExit): with pytest.raises(SystemExit):
rc, out, err = ansible_helm_module.run_helm_command( rc, out, err = _ansible_helm_module.run_helm_command(
command, fails_on_error=fails_on_error command, fails_on_error=fails_on_error
) )
ansible_helm_module.fail_json.assert_called_with( _ansible_helm_module.fail_json.assert_called_with(
msg="Failure when executing Helm command. Exited {0}.\nstdout: {1}\nstderr: {2}".format( msg="Failure when executing Helm command. Exited {0}.\nstdout: {1}\nstderr: {2}".format(
return_code, output, error return_code, output, error
), ),
@@ -282,7 +282,7 @@ def test_module_run_helm_command_failure(ansible_helm_module, fails_on_error):
command=command, command=command,
) )
else: else:
rc, out, err = ansible_helm_module.run_helm_command( rc, out, err = _ansible_helm_module.run_helm_command(
command, fails_on_error=fails_on_error command, fails_on_error=fails_on_error
) )
assert (rc, out, err) == (return_code, output, error) assert (rc, out, err) == (return_code, output, error)