mirror of
https://github.com/ansible-collections/community.routeros.git
synced 2025-06-20 17:15:46 +02:00
Allow to ignore dynamic and builtin entries. (#373)
This commit is contained in:
parent
bfd6b0bb13
commit
ab1026504c
3 changed files with 118 additions and 4 deletions
|
@ -0,0 +1,2 @@
|
||||||
|
minor_changes:
|
||||||
|
- "api_find_and_modify - allow to control whether ``dynamic`` and/or ``builtin`` entries are ignored with the new ``ignore_dynamic`` and ``ignore_builtin`` options (https://github.com/ansible-collections/community.routeros/issues/372, https://github.com/ansible-collections/community.routeros/pull/373)."
|
|
@ -75,6 +75,22 @@ options:
|
||||||
- Whether to allow that no match is found.
|
- Whether to allow that no match is found.
|
||||||
- If not specified, this value is induced from whether O(require_matches_min) is 0 or larger.
|
- If not specified, this value is induced from whether O(require_matches_min) is 0 or larger.
|
||||||
type: bool
|
type: bool
|
||||||
|
ignore_dynamic:
|
||||||
|
description:
|
||||||
|
- Whether to ignore dynamic entries.
|
||||||
|
- By default, they are considered. If set to V(true), they are not considered.
|
||||||
|
- It is generally recommended to set this to V(true) unless when you really need to modify dynamic entries.
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
|
version_added: 3.7.0
|
||||||
|
ignore_builtin:
|
||||||
|
description:
|
||||||
|
- Whether to ignore builtin entries.
|
||||||
|
- By default, they are considered. If set to V(true), they are not considered.
|
||||||
|
- It is generally recommended to set this to V(true) unless when you really need to modify builtin entries.
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
|
version_added: 3.7.0
|
||||||
seealso:
|
seealso:
|
||||||
- module: community.routeros.api
|
- module: community.routeros.api
|
||||||
- module: community.routeros.api_facts
|
- module: community.routeros.api_facts
|
||||||
|
@ -94,6 +110,10 @@ EXAMPLES = r"""
|
||||||
name: bridge
|
name: bridge
|
||||||
values:
|
values:
|
||||||
name: my-bridge
|
name: my-bridge
|
||||||
|
# Always ignore dynamic and builtin entries
|
||||||
|
# (not relevant for this path, but generally recommended)
|
||||||
|
ignore_dynamic: true
|
||||||
|
ignore_builtin: true
|
||||||
|
|
||||||
- name: Change IP address to 192.168.1.1 for interface bridge - assuming there is only one
|
- name: Change IP address to 192.168.1.1 for interface bridge - assuming there is only one
|
||||||
community.routeros.api_find_and_modify:
|
community.routeros.api_find_and_modify:
|
||||||
|
@ -105,10 +125,14 @@ EXAMPLES = r"""
|
||||||
interface: bridge
|
interface: bridge
|
||||||
values:
|
values:
|
||||||
address: "192.168.1.1/24"
|
address: "192.168.1.1/24"
|
||||||
# If there are zero entries, or more than one: fail! We expected that
|
# If there are zero entries, or more than one: fail! We expected that
|
||||||
# exactly one is configured.
|
# exactly one is configured.
|
||||||
require_matches_min: 1
|
require_matches_min: 1
|
||||||
require_matches_max: 1
|
require_matches_max: 1
|
||||||
|
# Always ignore dynamic and builtin entries
|
||||||
|
# (not relevant for this path, but generally recommended)
|
||||||
|
ignore_dynamic: true
|
||||||
|
ignore_builtin: true
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RETURN = r"""
|
RETURN = r"""
|
||||||
|
@ -185,6 +209,17 @@ def compose_api_path(api, path):
|
||||||
return api_path
|
return api_path
|
||||||
|
|
||||||
|
|
||||||
|
def filter_entries(entries, ignore_dynamic=False, ignore_builtin=False):
|
||||||
|
result = []
|
||||||
|
for entry in entries:
|
||||||
|
if ignore_dynamic and entry.get('dynamic', False):
|
||||||
|
continue
|
||||||
|
if ignore_builtin and entry.get('builtin', False):
|
||||||
|
continue
|
||||||
|
result.append(entry)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
DISABLED_MEANS_EMPTY_STRING = ('comment', )
|
DISABLED_MEANS_EMPTY_STRING = ('comment', )
|
||||||
|
|
||||||
|
|
||||||
|
@ -196,6 +231,8 @@ def main():
|
||||||
require_matches_min=dict(type='int', default=0),
|
require_matches_min=dict(type='int', default=0),
|
||||||
require_matches_max=dict(type='int'),
|
require_matches_max=dict(type='int'),
|
||||||
allow_no_matches=dict(type='bool'),
|
allow_no_matches=dict(type='bool'),
|
||||||
|
ignore_dynamic=dict(type='bool', default=False),
|
||||||
|
ignore_builtin=dict(type='bool', default=False),
|
||||||
)
|
)
|
||||||
module_args.update(api_argument_spec())
|
module_args.update(api_argument_spec())
|
||||||
|
|
||||||
|
@ -223,6 +260,9 @@ def main():
|
||||||
if key in values:
|
if key in values:
|
||||||
module.fail_json(msg='`values` must not contain both "{key}" and "!{key}"!'.format(key=key))
|
module.fail_json(msg='`values` must not contain both "{key}" and "!{key}"!'.format(key=key))
|
||||||
|
|
||||||
|
ignore_dynamic = module.params['ignore_dynamic']
|
||||||
|
ignore_builtin = module.params['ignore_builtin']
|
||||||
|
|
||||||
check_has_library(module)
|
check_has_library(module)
|
||||||
api = create_api(module)
|
api = create_api(module)
|
||||||
|
|
||||||
|
@ -230,7 +270,7 @@ def main():
|
||||||
|
|
||||||
api_path = compose_api_path(api, path)
|
api_path = compose_api_path(api, path)
|
||||||
|
|
||||||
old_data = list(api_path)
|
old_data = filter_entries(list(api_path), ignore_dynamic=ignore_dynamic, ignore_builtin=ignore_builtin)
|
||||||
new_data = [entry.copy() for entry in old_data]
|
new_data = [entry.copy() for entry in old_data]
|
||||||
|
|
||||||
# Find matching entries
|
# Find matching entries
|
||||||
|
@ -299,7 +339,7 @@ def main():
|
||||||
error=to_native(e),
|
error=to_native(e),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
new_data = list(api_path)
|
new_data = filter_entries(list(api_path), ignore_dynamic=ignore_dynamic, ignore_builtin=ignore_builtin)
|
||||||
|
|
||||||
# Produce return value
|
# Produce return value
|
||||||
more = {}
|
more = {}
|
||||||
|
|
|
@ -94,6 +94,52 @@ START_IP_FIREWALL_FILTER = [
|
||||||
|
|
||||||
START_IP_FIREWALL_FILTER_OLD_DATA = massage_expected_result_data(START_IP_FIREWALL_FILTER, ('ip', 'firewall', 'filter'), keep_all=True)
|
START_IP_FIREWALL_FILTER_OLD_DATA = massage_expected_result_data(START_IP_FIREWALL_FILTER, ('ip', 'firewall', 'filter'), keep_all=True)
|
||||||
|
|
||||||
|
START_IP_SERVICE = [
|
||||||
|
# I removed all entryes not for 'api' and 'api-ssl'
|
||||||
|
{
|
||||||
|
"certificate": None,
|
||||||
|
"tls-version": None,
|
||||||
|
".id": "*7",
|
||||||
|
"address": "",
|
||||||
|
"disabled": True,
|
||||||
|
"dynamic": False,
|
||||||
|
"invalid": True,
|
||||||
|
"name": "api",
|
||||||
|
"port": 8728,
|
||||||
|
"proto": "tcp",
|
||||||
|
"vrf": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
".id": "*9",
|
||||||
|
"address": "192.168.1.0/24",
|
||||||
|
"certificate": "mycert",
|
||||||
|
"dynamic": False,
|
||||||
|
"invalid": False,
|
||||||
|
"name": "api-ssl",
|
||||||
|
"port": 8729,
|
||||||
|
"proto": "tcp",
|
||||||
|
"tls-version": "only-1.2",
|
||||||
|
"vrf": "main"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"address": None,
|
||||||
|
"certificate": None,
|
||||||
|
"max-sessions": None,
|
||||||
|
"tls-version": None,
|
||||||
|
".id": "*13",
|
||||||
|
"connection": True,
|
||||||
|
"dynamic": True,
|
||||||
|
"invalid": False,
|
||||||
|
"local": "192.168.1.1",
|
||||||
|
"name": "api-ssl",
|
||||||
|
"port": 8729,
|
||||||
|
"proto": "tcp",
|
||||||
|
"remote": "192.168.1.2:12346"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
START_IP_SERVICE_OLD_DATA = massage_expected_result_data(START_IP_SERVICE, ('ip', 'service'), keep_all=True)
|
||||||
|
|
||||||
|
|
||||||
class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
|
|
||||||
|
@ -685,3 +731,29 @@ class TestRouterosApiFindAndModifyModule(ModuleTestCase):
|
||||||
])
|
])
|
||||||
self.assertEqual(result['match_count'], 3)
|
self.assertEqual(result['match_count'], 3)
|
||||||
self.assertEqual(result['modify_count'], 2)
|
self.assertEqual(result['modify_count'], 2)
|
||||||
|
|
||||||
|
@patch('ansible_collections.community.routeros.plugins.modules.api_find_and_modify.compose_api_path',
|
||||||
|
new=create_fake_path(('ip', 'service'), START_IP_SERVICE))
|
||||||
|
def test_change_ignore_dynamic(self):
|
||||||
|
with self.assertRaises(AnsibleExitJson) as exc:
|
||||||
|
args = self.config_module_args.copy()
|
||||||
|
args.update({
|
||||||
|
'path': 'ip service',
|
||||||
|
'find': {
|
||||||
|
'name': 'api-ssl',
|
||||||
|
},
|
||||||
|
'values': {
|
||||||
|
'address': '192.168.1.0/24',
|
||||||
|
},
|
||||||
|
'ignore_dynamic': True,
|
||||||
|
'_ansible_diff': True,
|
||||||
|
})
|
||||||
|
with set_module_args(args):
|
||||||
|
self.module.main()
|
||||||
|
|
||||||
|
result = exc.exception.args[0]
|
||||||
|
self.assertEqual(result['changed'], False)
|
||||||
|
self.assertEqual(result['old_data'], [entry for entry in START_IP_SERVICE_OLD_DATA if entry["dynamic"] is False])
|
||||||
|
self.assertEqual(result['new_data'], [entry for entry in START_IP_SERVICE_OLD_DATA if entry["dynamic"] is False])
|
||||||
|
self.assertEqual(result['match_count'], 1)
|
||||||
|
self.assertEqual(result['modify_count'], 0)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue