mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-02-04 07:51:50 +00:00
601 lines
22 KiB
Python
601 lines
22 KiB
Python
# Copyright (c) 2020, Ansible Project
|
|
# GNU General Public License v3.0+ (see LICENSES/GPL-3.0-or-later.txt or https://www.gnu.org/licenses/gpl-3.0.txt)
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
from __future__ import annotations
|
|
|
|
from contextlib import contextmanager
|
|
from unittest.mock import call, patch
|
|
|
|
from ansible_collections.community.internal_test_tools.tests.unit.plugins.modules.utils import (
|
|
AnsibleExitJson,
|
|
AnsibleFailJson,
|
|
ModuleTestCase,
|
|
set_module_args,
|
|
)
|
|
|
|
from ansible_collections.community.general.plugins.modules import ipa_pwpolicy
|
|
|
|
|
|
@contextmanager
|
|
def patch_ipa(**kwargs):
|
|
"""Mock context manager for patching the methods in PwPolicyIPAClient that contact the IPA server
|
|
|
|
Patches the `login` and `_post_json` methods
|
|
|
|
Keyword arguments are passed to the mock object that patches `_post_json`
|
|
|
|
No arguments are passed to the mock object that patches `login` because no tests require it
|
|
|
|
Example::
|
|
|
|
with patch_ipa(return_value={}) as (mock_login, mock_post):
|
|
...
|
|
"""
|
|
obj = ipa_pwpolicy.PwPolicyIPAClient
|
|
with patch.object(obj, "login") as mock_login:
|
|
with patch.object(obj, "_post_json", **kwargs) as mock_post:
|
|
yield mock_login, mock_post
|
|
|
|
|
|
class TestIPAPwPolicy(ModuleTestCase):
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.module = ipa_pwpolicy
|
|
|
|
def _test_base(self, module_args, return_value, mock_calls, changed):
|
|
"""Base function that's called by all the other test functions
|
|
|
|
module_args (dict):
|
|
Arguments passed to the module
|
|
|
|
return_value (dict):
|
|
Mocked return value of PwPolicyIPAClient.pwpolicy_find, as returned by the IPA API.
|
|
This should be set to the current state. It will be changed to the desired state using the above arguments.
|
|
(Technically, this is the return value of _post_json, but it's only checked by pwpolicy_find).
|
|
An empty dict means that the policy doesn't exist.
|
|
|
|
mock_calls (list/tuple of dicts):
|
|
List of calls made to PwPolicyIPAClient._post_json, in order.
|
|
_post_json is called by all of the pwpolicy_* methods of the class.
|
|
Pass an empty list if no calls are expected.
|
|
|
|
changed (bool):
|
|
Whether or not the module is supposed to be marked as changed
|
|
"""
|
|
with set_module_args(module_args):
|
|
# Run the module
|
|
with patch_ipa(return_value=return_value) as (mock_login, mock_post):
|
|
with self.assertRaises(AnsibleExitJson) as exec_info:
|
|
self.module.main()
|
|
|
|
# Verify that the calls to _post_json match what is expected
|
|
expected_call_count = len(mock_calls)
|
|
if expected_call_count > 1:
|
|
# Convert the call dicts to unittest.mock.call instances because `assert_has_calls` only accepts them
|
|
converted_calls = []
|
|
for call_dict in mock_calls:
|
|
converted_calls.append(call(**call_dict))
|
|
|
|
mock_post.assert_has_calls(converted_calls)
|
|
self.assertEqual(len(mock_post.mock_calls), expected_call_count)
|
|
elif expected_call_count == 1:
|
|
mock_post.assert_called_once_with(**mock_calls[0])
|
|
else: # expected_call_count is 0
|
|
mock_post.assert_not_called()
|
|
|
|
# Verify that the module's changed status matches what is expected
|
|
self.assertIs(exec_info.exception.args[0]["changed"], changed)
|
|
|
|
def test_add(self):
|
|
"""Add a new policy"""
|
|
module_args = {
|
|
"group": "admins",
|
|
"state": "present",
|
|
"priority": "10",
|
|
"maxpwdlife": "90",
|
|
"minpwdlife": "1",
|
|
"historylength": "8",
|
|
"minclasses": "3",
|
|
"minlength": "16",
|
|
"maxfailcount": "6",
|
|
"failinterval": "60",
|
|
"lockouttime": "600",
|
|
"gracelimit": 3,
|
|
"maxrepeat": 3,
|
|
"maxsequence": 3,
|
|
"dictcheck": True,
|
|
"usercheck": True,
|
|
}
|
|
return_value = {}
|
|
mock_calls = (
|
|
{"method": "pwpolicy_find", "name": None, "item": {"all": True, "cn": "admins"}},
|
|
{
|
|
"method": "pwpolicy_add",
|
|
"name": "admins",
|
|
"item": {
|
|
"cospriority": "10",
|
|
"krbmaxpwdlife": "90",
|
|
"krbminpwdlife": "1",
|
|
"krbpwdhistorylength": "8",
|
|
"krbpwdmindiffchars": "3",
|
|
"krbpwdminlength": "16",
|
|
"krbpwdmaxfailure": "6",
|
|
"krbpwdfailurecountinterval": "60",
|
|
"krbpwdlockoutduration": "600",
|
|
"passwordgracelimit": "3",
|
|
"ipapwdmaxrepeat": "3",
|
|
"ipapwdmaxsequence": "3",
|
|
"ipapwddictcheck": True,
|
|
"ipapwdusercheck": True,
|
|
},
|
|
},
|
|
)
|
|
changed = True
|
|
|
|
self._test_base(module_args, return_value, mock_calls, changed)
|
|
|
|
def test_aliases(self):
|
|
"""Same as test_add, but uses the `name` alias for the `group` option"""
|
|
module_args = {
|
|
"name": "admins",
|
|
"state": "present",
|
|
"priority": "10",
|
|
"maxpwdlife": "90",
|
|
"minpwdlife": "1",
|
|
"historylength": "8",
|
|
"minclasses": "3",
|
|
"minlength": "16",
|
|
"maxfailcount": "6",
|
|
"failinterval": "60",
|
|
"lockouttime": "600",
|
|
"gracelimit": 3,
|
|
"maxrepeat": 3,
|
|
"maxsequence": 3,
|
|
"dictcheck": True,
|
|
"usercheck": True,
|
|
}
|
|
return_value = {}
|
|
mock_calls = (
|
|
{"method": "pwpolicy_find", "name": None, "item": {"all": True, "cn": "admins"}},
|
|
{
|
|
"method": "pwpolicy_add",
|
|
"name": "admins",
|
|
"item": {
|
|
"cospriority": "10",
|
|
"krbmaxpwdlife": "90",
|
|
"krbminpwdlife": "1",
|
|
"krbpwdhistorylength": "8",
|
|
"krbpwdmindiffchars": "3",
|
|
"krbpwdminlength": "16",
|
|
"krbpwdmaxfailure": "6",
|
|
"krbpwdfailurecountinterval": "60",
|
|
"krbpwdlockoutduration": "600",
|
|
"passwordgracelimit": "3",
|
|
"ipapwdmaxrepeat": "3",
|
|
"ipapwdmaxsequence": "3",
|
|
"ipapwddictcheck": True,
|
|
"ipapwdusercheck": True,
|
|
},
|
|
},
|
|
)
|
|
changed = True
|
|
|
|
self._test_base(module_args, return_value, mock_calls, changed)
|
|
|
|
def test_mod_different_args(self):
|
|
"""Policy exists, but some of the args are different and need to be modified"""
|
|
module_args = {
|
|
"group": "sysops",
|
|
"state": "present",
|
|
"priority": "10",
|
|
"maxpwdlife": "60",
|
|
"minpwdlife": "24",
|
|
"historylength": "8",
|
|
"minclasses": "3",
|
|
"minlength": "12",
|
|
"maxfailcount": "8",
|
|
"failinterval": "60",
|
|
"lockouttime": "600",
|
|
"gracelimit": 3,
|
|
"maxrepeat": 3,
|
|
"maxsequence": 3,
|
|
"dictcheck": True,
|
|
"usercheck": True,
|
|
}
|
|
return_value = {
|
|
"cn": ["sysops"],
|
|
"cospriority": ["10"],
|
|
"krbmaxpwdlife": ["90"],
|
|
"krbminpwdlife": ["1"],
|
|
"krbpwdhistorylength": ["8"],
|
|
"krbpwdmindiffchars": ["3"],
|
|
"krbpwdminlength": ["16"],
|
|
"krbpwdmaxfailure": ["6"],
|
|
"krbpwdfailurecountinterval": ["60"],
|
|
"krbpwdlockoutduration": ["600"],
|
|
"passwordgracelimit": ["3"],
|
|
"ipapwdmaxrepeat": ["3"],
|
|
"ipapwdmaxsequence": ["3"],
|
|
"ipapwddictcheck": [True],
|
|
"ipapwdusercheck": [True],
|
|
"dn": "cn=sysops,cn=EXAMPLE.COM,cn=kerberos,dc=example,dc=com",
|
|
"objectclass": ["top", "nscontainer", "krbpwdpolicy"],
|
|
}
|
|
mock_calls = (
|
|
{"method": "pwpolicy_find", "name": None, "item": {"all": True, "cn": "sysops"}},
|
|
{
|
|
"method": "pwpolicy_mod",
|
|
"name": "sysops",
|
|
"item": {
|
|
"cospriority": "10",
|
|
"krbmaxpwdlife": "60",
|
|
"krbminpwdlife": "24",
|
|
"krbpwdhistorylength": "8",
|
|
"krbpwdmindiffchars": "3",
|
|
"krbpwdminlength": "12",
|
|
"krbpwdmaxfailure": "8",
|
|
"krbpwdfailurecountinterval": "60",
|
|
"krbpwdlockoutduration": "600",
|
|
"passwordgracelimit": "3",
|
|
"ipapwdmaxrepeat": "3",
|
|
"ipapwdmaxsequence": "3",
|
|
"ipapwddictcheck": True,
|
|
"ipapwdusercheck": True,
|
|
},
|
|
},
|
|
)
|
|
changed = True
|
|
|
|
self._test_base(module_args, return_value, mock_calls, changed)
|
|
|
|
def test_mod_missing_args(self):
|
|
"""Policy exists, but some of the args aren't set, so need to be added"""
|
|
module_args = {
|
|
"group": "sysops",
|
|
"state": "present",
|
|
"priority": "10",
|
|
"maxpwdlife": "90",
|
|
"minpwdlife": "1",
|
|
"historylength": "8",
|
|
"minclasses": "3",
|
|
"minlength": "16",
|
|
"maxfailcount": "6",
|
|
"failinterval": "60",
|
|
"lockouttime": "600",
|
|
"gracelimit": 3,
|
|
"maxrepeat": 3,
|
|
"maxsequence": 3,
|
|
"dictcheck": True,
|
|
"usercheck": True,
|
|
}
|
|
return_value = {
|
|
"cn": ["sysops"],
|
|
"cospriority": ["10"],
|
|
"krbmaxpwdlife": ["90"],
|
|
"krbpwdhistorylength": ["8"],
|
|
"krbpwdminlength": ["16"],
|
|
"krbpwdmaxfailure": ["6"],
|
|
"dn": "cn=sysops,cn=EXAMPLE.COM,cn=kerberos,dc=example,dc=com",
|
|
"objectclass": ["top", "nscontainer", "krbpwdpolicy"],
|
|
}
|
|
mock_calls = (
|
|
{"method": "pwpolicy_find", "name": None, "item": {"all": True, "cn": "sysops"}},
|
|
{
|
|
"method": "pwpolicy_mod",
|
|
"name": "sysops",
|
|
"item": {
|
|
"cospriority": "10",
|
|
"krbmaxpwdlife": "90",
|
|
"krbminpwdlife": "1",
|
|
"krbpwdhistorylength": "8",
|
|
"krbpwdmindiffchars": "3",
|
|
"krbpwdminlength": "16",
|
|
"krbpwdmaxfailure": "6",
|
|
"krbpwdfailurecountinterval": "60",
|
|
"krbpwdlockoutduration": "600",
|
|
"passwordgracelimit": "3",
|
|
"ipapwdmaxrepeat": "3",
|
|
"ipapwdmaxsequence": "3",
|
|
"ipapwddictcheck": True,
|
|
"ipapwdusercheck": True,
|
|
},
|
|
},
|
|
)
|
|
changed = True
|
|
|
|
self._test_base(module_args, return_value, mock_calls, changed)
|
|
|
|
def test_del(self):
|
|
"""Policy exists, and state is absent. Needs to be deleted"""
|
|
module_args = {
|
|
"group": "sysops",
|
|
"state": "absent",
|
|
# other arguments are ignored when state is `absent`
|
|
"priority": "10",
|
|
"maxpwdlife": "90",
|
|
"historylength": "8",
|
|
"minlength": "16",
|
|
"maxfailcount": "6",
|
|
}
|
|
return_value = {
|
|
"cn": ["sysops"],
|
|
"cospriority": ["10"],
|
|
"krbmaxpwdlife": ["90"],
|
|
"krbpwdhistorylength": ["8"],
|
|
"krbpwdminlength": ["16"],
|
|
"krbpwdmaxfailure": ["6"],
|
|
"dn": "cn=sysops,cn=EXAMPLE.COM,cn=kerberos,dc=example,dc=com",
|
|
"objectclass": ["top", "nscontainer", "krbpwdpolicy"],
|
|
}
|
|
mock_calls = (
|
|
{"method": "pwpolicy_find", "name": None, "item": {"all": True, "cn": "sysops"}},
|
|
{
|
|
"method": "pwpolicy_del",
|
|
"name": "sysops",
|
|
},
|
|
)
|
|
changed = True
|
|
|
|
self._test_base(module_args, return_value, mock_calls, changed)
|
|
|
|
def test_no_change(self):
|
|
"""Policy already exists. No changes needed"""
|
|
module_args = {
|
|
"group": "admins",
|
|
"state": "present",
|
|
"priority": "10",
|
|
"maxpwdlife": "90",
|
|
"minpwdlife": "1",
|
|
"historylength": "8",
|
|
"minclasses": "3",
|
|
"minlength": "16",
|
|
"maxfailcount": "6",
|
|
"failinterval": "60",
|
|
"lockouttime": "600",
|
|
"gracelimit": 3,
|
|
"maxrepeat": 3,
|
|
"maxsequence": 3,
|
|
"dictcheck": True,
|
|
"usercheck": True,
|
|
}
|
|
return_value = {
|
|
"cn": ["admins"],
|
|
"cospriority": ["10"],
|
|
"krbmaxpwdlife": ["90"],
|
|
"krbminpwdlife": ["1"],
|
|
"krbpwdhistorylength": ["8"],
|
|
"krbpwdmindiffchars": ["3"],
|
|
"krbpwdminlength": ["16"],
|
|
"krbpwdmaxfailure": ["6"],
|
|
"krbpwdfailurecountinterval": ["60"],
|
|
"krbpwdlockoutduration": ["600"],
|
|
"passwordgracelimit": ["3"],
|
|
"ipapwdmaxrepeat": ["3"],
|
|
"ipapwdmaxsequence": ["3"],
|
|
"ipapwddictcheck": [True],
|
|
"ipapwdusercheck": [True],
|
|
"dn": "cn=admins,cn=EXAMPLE.COM,cn=kerberos,dc=example,dc=com",
|
|
"objectclass": ["top", "nscontainer", "krbpwdpolicy"],
|
|
}
|
|
mock_calls = [{"method": "pwpolicy_find", "name": None, "item": {"all": True, "cn": "admins"}}]
|
|
changed = False
|
|
|
|
self._test_base(module_args, return_value, mock_calls, changed)
|
|
|
|
def test_del_no_change(self):
|
|
"""Policy doesn't exist, and state is absent. No change needed"""
|
|
module_args = {
|
|
"group": "sysops",
|
|
"state": "absent",
|
|
# other arguments are ignored when state is `absent`
|
|
"priority": "10",
|
|
"maxpwdlife": "90",
|
|
"historylength": "8",
|
|
"minlength": "16",
|
|
"maxfailcount": "6",
|
|
}
|
|
return_value = {}
|
|
mock_calls = [{"method": "pwpolicy_find", "name": None, "item": {"all": True, "cn": "sysops"}}]
|
|
changed = False
|
|
|
|
self._test_base(module_args, return_value, mock_calls, changed)
|
|
|
|
def test_global(self):
|
|
"""Modify the global policy"""
|
|
module_args = {
|
|
"maxpwdlife": "60",
|
|
"minpwdlife": "24",
|
|
"historylength": "8",
|
|
"minclasses": "3",
|
|
"minlength": "12",
|
|
"maxfailcount": "8",
|
|
"failinterval": "60",
|
|
"lockouttime": "600",
|
|
"gracelimit": 3,
|
|
"maxrepeat": 3,
|
|
"maxsequence": 3,
|
|
"dictcheck": True,
|
|
"usercheck": True,
|
|
}
|
|
return_value = {
|
|
"cn": ["global_policy"],
|
|
"krbmaxpwdlife": ["90"],
|
|
"krbminpwdlife": ["1"],
|
|
"krbpwdmindiffchars": ["3"],
|
|
"krbpwdminlength": ["16"],
|
|
"krbpwdmaxfailure": ["6"],
|
|
"krbpwdfailurecountinterval": ["60"],
|
|
"krbpwdlockoutduration": ["600"],
|
|
"passwordgracelimit": ["3"],
|
|
"ipapwdmaxrepeat": ["3"],
|
|
"ipapwdmaxsequence": ["3"],
|
|
"ipapwddictcheck": [True],
|
|
"ipapwdusercheck": [True],
|
|
"dn": "cn=global_policy,cn=EXAMPLE.COM,cn=kerberos,dc=example,dc=com",
|
|
"objectclass": ["top", "nscontainer", "krbpwdpolicy"],
|
|
}
|
|
mock_calls = (
|
|
{"method": "pwpolicy_find", "name": None, "item": {"all": True, "cn": "global_policy"}},
|
|
{
|
|
"method": "pwpolicy_mod",
|
|
"name": None,
|
|
"item": {
|
|
"krbmaxpwdlife": "60",
|
|
"krbminpwdlife": "24",
|
|
"krbpwdhistorylength": "8",
|
|
"krbpwdmindiffchars": "3",
|
|
"krbpwdminlength": "12",
|
|
"krbpwdmaxfailure": "8",
|
|
"krbpwdfailurecountinterval": "60",
|
|
"krbpwdlockoutduration": "600",
|
|
"passwordgracelimit": "3",
|
|
"ipapwdmaxrepeat": "3",
|
|
"ipapwdmaxsequence": "3",
|
|
"ipapwddictcheck": True,
|
|
"ipapwdusercheck": True,
|
|
},
|
|
},
|
|
)
|
|
changed = True
|
|
|
|
self._test_base(module_args, return_value, mock_calls, changed)
|
|
|
|
def test_global_no_change(self):
|
|
"""Global policy already matches the given arguments. No change needed"""
|
|
module_args = {
|
|
"maxpwdlife": "90",
|
|
"minpwdlife": "1",
|
|
"historylength": "8",
|
|
"minclasses": "3",
|
|
"minlength": "16",
|
|
"maxfailcount": "6",
|
|
"failinterval": "60",
|
|
"lockouttime": "600",
|
|
"gracelimit": 3,
|
|
"maxrepeat": 3,
|
|
"maxsequence": 3,
|
|
"dictcheck": True,
|
|
"usercheck": True,
|
|
}
|
|
return_value = {
|
|
"cn": ["global_policy"],
|
|
"krbmaxpwdlife": ["90"],
|
|
"krbminpwdlife": ["1"],
|
|
"krbpwdhistorylength": ["8"],
|
|
"krbpwdmindiffchars": ["3"],
|
|
"krbpwdminlength": ["16"],
|
|
"krbpwdmaxfailure": ["6"],
|
|
"krbpwdfailurecountinterval": ["60"],
|
|
"krbpwdlockoutduration": ["600"],
|
|
"passwordgracelimit": ["3"],
|
|
"ipapwdmaxrepeat": ["3"],
|
|
"ipapwdmaxsequence": ["3"],
|
|
"ipapwddictcheck": [True],
|
|
"ipapwdusercheck": [True],
|
|
"dn": "cn=global_policy,cn=EXAMPLE.COM,cn=kerberos,dc=example,dc=com",
|
|
"objectclass": ["top", "nscontainer", "krbpwdpolicy"],
|
|
}
|
|
mock_calls = [{"method": "pwpolicy_find", "name": None, "item": {"all": True, "cn": "global_policy"}}]
|
|
changed = False
|
|
|
|
self._test_base(module_args, return_value, mock_calls, changed)
|
|
|
|
def test_check_add(self):
|
|
"""Add a new policy in check mode. pwpolicy_add shouldn't be called"""
|
|
module_args = {
|
|
"_ansible_check_mode": True,
|
|
"group": "admins",
|
|
"state": "present",
|
|
"priority": "10",
|
|
"maxpwdlife": "90",
|
|
"minpwdlife": "1",
|
|
"historylength": "8",
|
|
"minclasses": "3",
|
|
"minlength": "16",
|
|
"maxfailcount": "6",
|
|
"failinterval": "60",
|
|
"lockouttime": "600",
|
|
"gracelimit": 3,
|
|
"maxrepeat": 3,
|
|
"maxsequence": 3,
|
|
"dictcheck": True,
|
|
"usercheck": True,
|
|
}
|
|
return_value = {}
|
|
mock_calls = [{"method": "pwpolicy_find", "name": None, "item": {"all": True, "cn": "admins"}}]
|
|
changed = True
|
|
|
|
self._test_base(module_args, return_value, mock_calls, changed)
|
|
|
|
def test_check_mod(self):
|
|
"""Modify a policy in check mode. pwpolicy_mod shouldn't be called"""
|
|
module_args = {
|
|
"_ansible_check_mode": True,
|
|
"group": "sysops",
|
|
"state": "present",
|
|
"priority": "10",
|
|
"maxpwdlife": "60",
|
|
"minpwdlife": "24",
|
|
"historylength": "8",
|
|
"minclasses": "3",
|
|
"minlength": "12",
|
|
"maxfailcount": "8",
|
|
"failinterval": "60",
|
|
"lockouttime": "600",
|
|
"gracelimit": 3,
|
|
"maxrepeat": 3,
|
|
"maxsequence": 3,
|
|
"dictcheck": True,
|
|
"usercheck": True,
|
|
}
|
|
return_value = {
|
|
"cn": ["sysops"],
|
|
"cospriority": ["10"],
|
|
"krbmaxpwdlife": ["90"],
|
|
"krbminpwdlife": ["1"],
|
|
"krbpwdhistorylength": ["8"],
|
|
"krbpwdmindiffchars": ["3"],
|
|
"krbpwdminlength": ["16"],
|
|
"krbpwdmaxfailure": ["6"],
|
|
"krbpwdfailurecountinterval": ["60"],
|
|
"krbpwdlockoutduration": ["600"],
|
|
"passwordgracelimit": ["3"],
|
|
"ipapwdmaxrepeat": ["3"],
|
|
"ipapwdmaxsequence": ["3"],
|
|
"ipapwddictcheck": [True],
|
|
"ipapwdusercheck": [True],
|
|
"dn": "cn=sysops,cn=EXAMPLE.COM,cn=kerberos,dc=example,dc=com",
|
|
"objectclass": ["top", "nscontainer", "krbpwdpolicy"],
|
|
}
|
|
mock_calls = [{"method": "pwpolicy_find", "name": None, "item": {"all": True, "cn": "sysops"}}]
|
|
changed = True
|
|
|
|
self._test_base(module_args, return_value, mock_calls, changed)
|
|
|
|
def test_check_del(self):
|
|
"""Delete a policy in check mode. pwpolicy_del shouldn't be called"""
|
|
module_args = {"_ansible_check_mode": True, "group": "sysops", "state": "absent"}
|
|
return_value = {
|
|
"cn": ["sysops"],
|
|
"cospriority": ["10"],
|
|
"krbmaxpwdlife": ["90"],
|
|
"krbpwdhistorylength": ["8"],
|
|
"krbpwdminlength": ["16"],
|
|
"krbpwdmaxfailure": ["6"],
|
|
"dn": "cn=sysops,cn=EXAMPLE.COM,cn=kerberos,dc=example,dc=com",
|
|
"objectclass": ["top", "nscontainer", "krbpwdpolicy"],
|
|
}
|
|
mock_calls = [{"method": "pwpolicy_find", "name": None, "item": {"all": True, "cn": "sysops"}}]
|
|
changed = True
|
|
|
|
self._test_base(module_args, return_value, mock_calls, changed)
|
|
|
|
def test_fail_post(self):
|
|
"""Fail due to an exception raised from _post_json"""
|
|
with set_module_args({"group": "admins", "state": "absent"}):
|
|
with patch_ipa(side_effect=Exception("ERROR MESSAGE")) as (mock_login, mock_post):
|
|
with self.assertRaises(AnsibleFailJson) as exec_info:
|
|
self.module.main()
|
|
|
|
self.assertEqual(exec_info.exception.args[0]["msg"], "ERROR MESSAGE")
|