Skip to content

Commit

Permalink
API update (#128)
Browse files Browse the repository at this point in the history
* adding support for api fields that can be disabled and have default value at the same time

Signed-off-by: Tomas Herfert <herfik>

* api path support: interface gre

Signed-off-by: Tomas Herfert <herfik>

* docs

Signed-off-by: Tomas Herfert <herfik>

* unit test update & yamlling fix

Signed-off-by: Tomas Herfert <herfik>

* test fix

Signed-off-by: Tomas Herfert <herfik>

* sanity fix

Signed-off-by: Tomas Herfert <herfik>

* changelog

Signed-off-by: Tomas Herfert <herfik>

* Update per suggestion

Co-authored-by: Felix Fontein <[email protected]>

* api path support: interface eoip

Signed-off-by: Tomas Herfert <herfik>

* docs

Signed-off-by: Tomas Herfert <herfik>

* apply suggestion from code review

Signed-off-by: Tomas Herfert <herfik>

Signed-off-by: Tomas Herfert <herfik>
Co-authored-by: Tomas Herfert <herfik>
Co-authored-by: Felix Fontein <[email protected]>
  • Loading branch information
therfert and felixfontein authored Nov 17, 2022
1 parent 1353055 commit 23b3aa3
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 6 deletions.
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 @@ -352,7 +354,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 @@ -368,7 +370,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 @@ -380,6 +384,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

0 comments on commit 23b3aa3

Please sign in to comment.