Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

API update #128

Merged
merged 11 commits into from
Nov 17, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions changelogs/fragments/128-api.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
minor_changes:
- api_modify, api_info - support for API fields that can be disabled and have default value at the same time, support API paths ``interface gre``, ``interface eoip``
(https://github.com/ansible-collections/community.routeros/pull/128).
49 changes: 47 additions & 2 deletions plugins/module_utils/_api_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,10 @@ class KeyInfo(object):
def __init__(self, _dummy=None, can_disable=False, remove_value=None, absent_value=None, default=None, required=False, automatically_computed_from=None):
if _dummy is not None:
raise ValueError('KeyInfo() does not have positional arguments')
if sum([required, default is not None, automatically_computed_from is not None, can_disable]) > 1:
raise ValueError('required, default, automatically_computed_from, and can_disable are mutually exclusive')
if sum([required, default is not None or can_disable, automatically_computed_from is not None]) > 1:
raise ValueError(
'required, default, automatically_computed_from, and can_disable are mutually exclusive ' +
'besides default and can_disable which can be set together')
if not can_disable and remove_value is not None:
raise ValueError('remove_value can only be specified if can_disable=True')
if absent_value is not None and any([default is not None, automatically_computed_from is not None, can_disable]):
Expand Down Expand Up @@ -106,6 +108,31 @@ def join_path(path):
'vlan-filtering': KeyInfo(default=False),
},
),
('interface', 'eoip'): APIData(
fully_understood=True,
primary_keys=('name',),
fields={
'allow-fast-path': KeyInfo(default=True),
'arp': KeyInfo(default='enabled'),
'arp-timeout': KeyInfo(default='auto'),
'clamp-tcp-mss': KeyInfo(default=True),
'comment': KeyInfo(can_disable=True, remove_value=''),
'disabled': KeyInfo(default=False),
'dont-fragment': KeyInfo(default=False),
'dscp': KeyInfo(default='inherit'),
'ipsec-secret': KeyInfo(can_disable=True),
'keepalive': KeyInfo(default='10s,10', can_disable=True),
'local-address': KeyInfo(default='0.0.0.0'),
'loop-protect': KeyInfo(default='default'),
'loop-protect-disable-time': KeyInfo(default='5m'),
'loop-protect-send-interval': KeyInfo(default='5s'),
'mac-address': KeyInfo(),
'mtu': KeyInfo(default='auto'),
'name': KeyInfo(),
'remote-address': KeyInfo(required=True),
'tunnel-id': KeyInfo(required=True),
},
),
('interface', 'ethernet'): APIData(
fixed_entries=True,
fully_understood=True,
Expand Down Expand Up @@ -145,6 +172,24 @@ def join_path(path):
'tx-flow-control': KeyInfo(default='off'),
},
),
('interface', 'gre'): APIData(
fully_understood=True,
primary_keys=('name', ),
fields={
'allow-fast-path': KeyInfo(default=True),
'clamp-tcp-mss': KeyInfo(default=True),
'comment': KeyInfo(can_disable=True, remove_value=''),
'disabled': KeyInfo(default=False),
'dont-fragment': KeyInfo(default=False),
'dscp': KeyInfo(default='inherit'),
'ipsec-secret': KeyInfo(can_disable=True),
'keepalive': KeyInfo(default='10s,10', can_disable=True),
'local-address': KeyInfo(default='0.0.0.0'),
'mtu': KeyInfo(default='auto'),
'name': KeyInfo(),
'remote-address': KeyInfo(required=True),
},
),
('interface', 'list'): APIData(
primary_keys=('name', ),
fully_understood=True,
Expand Down
2 changes: 2 additions & 0 deletions plugins/modules/api_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@
- interface bridge settings
- interface bridge vlan
- interface detect-internet
- interface eoip
- interface ethernet
- interface ethernet switch
- interface ethernet switch port
- interface gre
- interface l2tp-server server
- interface list
- interface list member
Expand Down
13 changes: 11 additions & 2 deletions plugins/modules/api_modify.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,11 @@
- interface bridge settings
- interface bridge vlan
- interface detect-internet
- interface eoip
- interface ethernet
- interface ethernet switch
- interface ethernet switch port
- interface gre
- interface l2tp-server server
- interface list
- interface list member
Expand Down Expand Up @@ -336,7 +338,7 @@ def find_modifications(old_entry, new_entry, path_info, module, for_text='', ret
modifications['!%s' % disabled_k] = ''
del updated_entry[disabled_k]
continue
if k not in old_entry and path_info.fields[k].default == v:
if k not in old_entry and path_info.fields[k].default == v and not path_info.fields[k].can_disable:
continue
if k not in old_entry or old_entry[k] != v:
modifications[k] = v
Expand All @@ -352,7 +354,9 @@ def find_modifications(old_entry, new_entry, path_info, module, for_text='', ret
if field_info.remove_value is not None and field_info.remove_value == old_entry[k]:
continue
if field_info.can_disable:
if field_info.remove_value is not None:
if field_info.default is not None:
modifications[k] = field_info.default
elif field_info.remove_value is not None:
modifications[k] = field_info.remove_value
else:
modifications['!%s' % k] = ''
Expand All @@ -364,6 +368,11 @@ def find_modifications(old_entry, new_entry, path_info, module, for_text='', ret
if return_none_instead_of_fail:
return None, None
module.fail_json(msg='Key "{key}" cannot be removed{for_text}.'.format(key=k, for_text=for_text))
for k in path_info.fields:
field_info = path_info.fields[k]
if k not in old_entry and k not in new_entry and field_info.can_disable and field_info.default is not None:
modifications[k] = field_info.default
updated_entry[k] = field_info.default
return modifications, updated_entry


Expand Down
10 changes: 9 additions & 1 deletion tests/unit/plugins/module_utils/test__api_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,19 @@ def test_key_info_errors():
('can_disable', True),
]

params_allowed_together = [
'default',
'can_disable',
]

emsg = 'required, default, automatically_computed_from, and can_disable are mutually exclusive besides default and can_disable which can be set together'
for index, (param, param_value) in enumerate(values):
for param2, param2_value in values[index + 1:]:
if param in params_allowed_together and param2 in params_allowed_together:
continue
with pytest.raises(ValueError) as exc:
KeyInfo(**{param: param_value, param2: param2_value})
assert exc.value.args[0] == 'required, default, automatically_computed_from, and can_disable are mutually exclusive'
assert exc.value.args[0] == emsg

with pytest.raises(ValueError) as exc:
KeyInfo('foo')
Expand Down
2 changes: 1 addition & 1 deletion tests/unit/plugins/modules/fake_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def str_return(self):

def _normalize_entry(entry, path_info):
for key, data in path_info.fields.items():
if key not in entry and data.default is not None:
if key not in entry and data.default is not None and not data.can_disable:
entry[key] = data.default
if data.can_disable:
if key in entry and entry[key] in (None, data.remove_value):
Expand Down