chore: add fail_on_invalid_params helper (#470)

##### SUMMARY

Add a small helper to validate parameters while executing the module.

---------

Co-authored-by: Justin Jeffery <justin.jeffery@ipfabric.io>
This commit is contained in:
Jonas L 2024-03-11 18:03:26 +01:00 committed by GitHub
parent 46717e2d65
commit e781f48f15
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 69 additions and 7 deletions

View file

@ -10,6 +10,10 @@ from typing import Any, NoReturn
from ansible.module_utils.basic import AnsibleModule as AnsibleModuleBase, env_fallback
from ansible.module_utils.common.text.converters import to_native
from ansible.module_utils.common.validation import (
check_missing_parameters,
check_required_one_of,
)
from .client import ClientException, client_check_required_lib, client_get_by_name_or_id
from .vendor.hcloud import APIException, Client, HCloudException
@ -94,6 +98,29 @@ class AnsibleHCloud:
def _mark_as_changed(self) -> None:
self.result["changed"] = True
def fail_on_invalid_params(
self,
*,
required: list[str] | None = None,
required_one_of: list[list[str]] | None = None,
) -> None:
"""
Run additional validation that cannot be done in the argument spec validation.
:param required_params: Check that terms exists in the module params.
:param required_one_of: Check each list of terms to ensure at least one exists in the module parameters.
"""
try:
if required:
check_missing_parameters(self.module.params, required)
if required_one_of:
params_without_nones = {k: v for k, v in self.module.params.items() if v is not None}
check_required_one_of(required_one_of, params_without_nones)
except TypeError as e:
self.module.fail_json(msg=to_native(e))
@classmethod
def base_module_arguments(cls):
return {

15
tests/unit/conftest.py Normal file
View file

@ -0,0 +1,15 @@
from __future__ import annotations
from unittest.mock import MagicMock
import pytest
@pytest.fixture()
def module():
obj = MagicMock()
obj.params = {
"api_token": "dummy",
"api_endpoint": "https://api.hetzner.cloud/v1",
}
return obj

View file

@ -2,8 +2,8 @@ from __future__ import annotations
import traceback
from datetime import datetime, timezone
from unittest.mock import MagicMock
import pytest
from ansible_collections.hetzner.hcloud.plugins.module_utils.hcloud import AnsibleHCloud
from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud import (
APIException,
@ -16,12 +16,7 @@ from ansible_collections.hetzner.hcloud.plugins.module_utils.vendor.hcloud.actio
)
def test_hcloud_fail_json_hcloud():
module = MagicMock()
module.params = {
"api_token": "fake_token",
"api_endpoint": "https://api.hetzner.cloud/v1",
}
def test_hcloud_fail_json_hcloud(module):
AnsibleHCloud.represent = "hcloud_test"
hcloud = AnsibleHCloud(module)
@ -123,3 +118,28 @@ def test_hcloud_fail_json_hcloud():
}
},
)
@pytest.mark.parametrize(
("kwargs", "msg"),
[
({"required": ["key1"]}, None),
({"required": ["missing"]}, "missing required arguments: missing"),
({"required_one_of": [["key1", "missing"]]}, None),
({"required_one_of": [["missing1", "missing2"]]}, "one of the following is required: missing1, missing2"),
],
)
def test_hcloud_fail_on_invalid_params(module, kwargs, msg):
AnsibleHCloud.represent = "hcloud_test"
hcloud = AnsibleHCloud(module)
module.params = {
"key1": "value",
"key2": "value",
}
hcloud.fail_on_invalid_params(**kwargs)
if msg is None:
module.fail_json.assert_not_called()
else:
module.fail_json.assert_called_with(msg=msg)