From b73dfe5b26adfe5f18009410aedb65fbfcdb0c70 Mon Sep 17 00:00:00 2001 From: Tomas Herfert Date: Mon, 14 Nov 2022 21:49:18 +0100 Subject: [PATCH 1/4] multiple api paths support and updates Signed-off-by: Tomas Herfert --- changelogs/fragments/131-api.yml | 15 +++ plugins/module_utils/_api_data.py | 208 +++++++++++++++++++++++++----- plugins/modules/api_info.py | 11 ++ plugins/modules/api_modify.py | 11 ++ 4 files changed, 212 insertions(+), 33 deletions(-) create mode 100644 changelogs/fragments/131-api.yml diff --git a/changelogs/fragments/131-api.yml b/changelogs/fragments/131-api.yml new file mode 100644 index 00000000..7e6ba596 --- /dev/null +++ b/changelogs/fragments/131-api.yml @@ -0,0 +1,15 @@ +minor_changes: + - api_modify, api_info - support API paths ``ipv6 address``, ``ipv6 dhcp-server``, ``ipv6 dhcp-server option``, ``ipv6 route``, ``queue tree``, ``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template``, ``routing pimsm instance``, ``routing pimsm interface-template`` + (https://github.com/ansible-collections/community.routeros/pull/131) + - api_modify, api_info - support for fields ``blackhole``, ``pref-src``, ``routing-table``, ``suppress-hw-offload``, ``type``, ``vrf-interface`` in ``ip route`` path + (https://github.com/ansible-collections/community.routeros/pull/131) +known_issues: + - api_modify - when limits for entries in ``queue tree`` are defined as human readable - e.g. 25M, the configuration will be correctly set in ROS, but the module will indicate the item is changed on every run even when there was no change done. This is caused by the ROS API which returns the number in bytes - e.g. 25000000 (which is inconsistent with the CLI behavior). In order to mitigate that, the limits have to be defined in bytes (those will still appear as human readable in the ROS CLI). + (https://github.com/ansible-collections/community.routeros/pull/131 + - ``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template`` paths are not fully implemeted for ROS6 due to the significat changes between ROS6 and ROS7. + (https://github.com/ansible-collections/community.routeros/pull/131) +bugfixes: + - ``queue interface`` path works with api_modify now + (https://github.com/ansible-collections/community.routeros/pull/131). + - ``ip route`` entry can be defined wihtout the need of ``gateway`` field (which is correct for unreachable/blackhole type of routes). + (https://github.com/ansible-collections/community.routeros/pull/131). diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index ad8ceb2f..f16cd42e 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -400,16 +400,22 @@ def join_path(path): ('ip', 'route'): APIData( fully_understood=True, fields={ + 'blackhole': KeyInfo(can_disable=True), 'check-gateway': KeyInfo(can_disable=True), 'comment': KeyInfo(can_disable=True, remove_value=''), 'disabled': KeyInfo(default=False), 'distance': KeyInfo(), 'dst-address': KeyInfo(), - 'gateway': KeyInfo(required=True), + 'gateway': KeyInfo(), + 'pref-src': KeyInfo(), + 'routing-table': KeyInfo(default='main'), 'route-tag': KeyInfo(can_disable=True), 'routing-mark': KeyInfo(can_disable=True), 'scope': KeyInfo(), + 'suppress-hw-offload': KeyInfo(default=False), 'target-scope': KeyInfo(), + 'type': KeyInfo(can_disable=True, remove_value='unicast'), + 'vrf-interface': KeyInfo(can_disable=True), }, ), ('ip', 'route', 'vrf'): APIData( @@ -437,45 +443,78 @@ def join_path(path): }, ), ('routing', 'ospf', 'instance'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), + fully_understood=True, + primary_keys=('name', ), fields={ - 'default': KeyInfo(), - 'disabled': KeyInfo(), - 'distribute-default': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), 'domain-id': KeyInfo(can_disable=True), 'domain-tag': KeyInfo(can_disable=True), - 'in-filter': KeyInfo(), - 'metric-bgp': KeyInfo(), - 'metric-connected': KeyInfo(), - 'metric-default': KeyInfo(), - 'metric-other-ospf': KeyInfo(), - 'metric-rip': KeyInfo(), - 'metric-static': KeyInfo(), + 'in-filter-chain': KeyInfo(can_disable=True), + 'mpls-te-address': KeyInfo(can_disable=True), 'mpls-te-area': KeyInfo(can_disable=True), - 'mpls-te-router-id': KeyInfo(can_disable=True), 'name': KeyInfo(), - 'out-filter': KeyInfo(), - 'redistribute-bgp': KeyInfo(), - 'redistribute-connected': KeyInfo(), - 'redistribute-other-ospf': KeyInfo(), - 'redistribute-rip': KeyInfo(), - 'redistribute-static': KeyInfo(), - 'router-id': KeyInfo(), + 'originate-default': KeyInfo(can_disable=True), + 'out-filter-chain': KeyInfo(can_disable=True), + 'out-filter-select': KeyInfo(can_disable=True), + 'redistribute': KeyInfo(can_disable=True), + 'router-id': KeyInfo(default='main'), 'routing-table': KeyInfo(can_disable=True), 'use-dn': KeyInfo(can_disable=True), + 'version': KeyInfo(default=2), + 'vrf': KeyInfo(default='main'), }, ), ('routing', 'ospf', 'area'): APIData( - unknown_mechanism=True, - # primary_keys=('default', ), + fully_understood=True, + primary_keys=('name', ), fields={ - 'default': KeyInfo(), - 'area-id': KeyInfo(), - 'disabled': KeyInfo(), - 'instance': KeyInfo(), + 'area-id': KeyInfo(default='0.0.0.0'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'default-cost': KeyInfo(can_disable=True), + 'disabled': KeyInfo(default=False), + 'instance': KeyInfo(required=True), 'name': KeyInfo(), - 'type': KeyInfo(), + 'no-summaries': KeyInfo(can_disable=True), + 'nssa-translator': KeyInfo(can_disable=True), + 'type': KeyInfo(default='default'), + }, + ), + ('routing', 'ospf', 'area', 'range'): APIData( + fully_understood=True, + primary_keys=('area', 'prefix', ), + fields={ + 'advertise': KeyInfo(default=True), + 'area': KeyInfo(), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'cost': KeyInfo(can_disable=True), + 'disabled': KeyInfo(default=False), + 'prefix': KeyInfo(), + }, + ), + ('routing', 'ospf', 'interface-template'): APIData( + fully_understood=True, + fields={ + 'area': KeyInfo(required=True), + 'auth': KeyInfo(can_disable=True), + 'auth-id': KeyInfo(can_disable=True), + 'auth-key': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'cost': KeyInfo(default=1), + 'dead-interval': KeyInfo(default='40s'), + 'disabled': KeyInfo(default=False), + 'hello-interval': KeyInfo(default='10s'), + 'instance-id': KeyInfo(default=0), + 'interfaces': KeyInfo(can_disable=True), + 'networks': KeyInfo(can_disable=True), + 'passive': KeyInfo(can_disable=True), + 'prefix-list': KeyInfo(can_disable=True), + 'priority': KeyInfo(default=128), + 'retransmit-interval': KeyInfo(default='5s'), + 'transmit-delay': KeyInfo(default='1s'), + 'type': KeyInfo(default='broadcast'), + 'vlink-neighbor-id': KeyInfo(can_disable=True), + 'vlink-transit-area': KeyInfo(can_disable=True), }, ), ('routing', 'ospf-v3', 'instance'): APIData( @@ -512,6 +551,40 @@ def join_path(path): 'type': KeyInfo(), }, ), + ('routing', 'pimsm', 'instance'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'afi': KeyInfo(default='ipv4'), + 'bsm-forward-back': KeyInfo(), + 'crp-advertise-contained': KeyInfo(), + 'disabled': KeyInfo(default=False), + 'name': KeyInfo(), + 'rp-hash-mask-length': KeyInfo(), + 'rp-static-override': KeyInfo(default=False), + 'ssm-range': KeyInfo(), + 'switch-to-spt': KeyInfo(default=True), + 'switch-to-spt-bytes': KeyInfo(default=0), + 'switch-to-spt-interval': KeyInfo(), + 'vrf': KeyInfo(default="main"), + }, + ), + ('routing', 'pimsm', 'interface-template'): APIData( + fully_understood=True, + fields={ + 'disabled': KeyInfo(default=False), + 'hello-delay': KeyInfo(default='5s'), + 'hello-period': KeyInfo(default='30s'), + 'instance': KeyInfo(required=True), + 'interfaces': KeyInfo(can_disable=True), + 'join-prune-period': KeyInfo(default='1m'), + 'join-tracking-support': KeyInfo(default=True), + 'override-interval': KeyInfo(default='2s500ms'), + 'priority': KeyInfo(default=1), + 'propagation-delay': KeyInfo(default='500ms'), + 'source-addresses': KeyInfo(can_disable=True), + }, + ), ('snmp', 'community'): APIData( unknown_mechanism=True, # primary_keys=('default', ), @@ -824,6 +897,19 @@ def join_path(path): 'tcp-syncookies': KeyInfo(default=False), }, ), + ('ipv6', 'address'): APIData( + fully_understood=True, + fields={ + 'address': KeyInfo(), + 'advertise': KeyInfo(default=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'eui-64': KeyInfo(default=False), + 'from-pool': KeyInfo(), + 'interface': KeyInfo(required=True), + 'no-dad': KeyInfo(default=False), + }, + ), ('ipv6', 'settings'): APIData( single_value=True, fully_understood=True, @@ -1467,6 +1553,36 @@ def join_path(path): 'use-peer-dns': KeyInfo(default=True), }, ), + ('ipv6', 'dhcp-server'): APIData( + fully_understood=True, + primary_keys=('name', ), + fields={ + 'address-pool': KeyInfo(required=True), + 'allow-dual-stack-queue': KeyInfo(can_disable=True, remove_value=True), + 'binding-script': KeyInfo(can_disable=True, remove_value=''), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'dhcp-option': KeyInfo(default=''), + 'disabled': KeyInfo(default=False), + 'insert-queue-before': KeyInfo(can_disable=True, remove_value='first'), + 'interface': KeyInfo(required=True), + 'lease-time': KeyInfo(default='3d'), + 'name': KeyInfo(), + 'parent-queue': KeyInfo(can_disable=True, remove_value='none'), + 'preference': KeyInfo(default=255), + 'rapid-commit': KeyInfo(default=True), + 'route-distance': KeyInfo(default=1), + 'use-radius': KeyInfo(default=False), + }, + ), + ('ipv6', 'dhcp-server', 'option'): APIData( + fully_understood=True, + primary_keys=('name',), + fields={ + 'code': KeyInfo(required=True), + 'name': KeyInfo(), + 'value': KeyInfo(default=''), + }, + ), ('ipv6', 'firewall', 'address-list'): APIData( fully_understood=True, primary_keys=('address', 'list', ), @@ -1562,6 +1678,7 @@ def join_path(path): }, ), ('ipv6', 'route'): APIData( + fully_understood=True, fields={ 'bgp-as-path': KeyInfo(can_disable=True), 'bgp-atomic-aggregate': KeyInfo(can_disable=True), @@ -1570,14 +1687,19 @@ def join_path(path): 'bgp-med': KeyInfo(can_disable=True), 'bgp-origin': KeyInfo(can_disable=True), 'bgp-prepend': KeyInfo(can_disable=True), + 'type': KeyInfo(can_disable=True, remove_value='unicast'), + 'blackhole': KeyInfo(can_disable=True), 'check-gateway': KeyInfo(can_disable=True), + 'comment': KeyInfo(can_disable=True, remove_value=''), 'disabled': KeyInfo(), - 'distance': KeyInfo(), + 'distance': KeyInfo(default=1), 'dst-address': KeyInfo(), 'gateway': KeyInfo(), 'route-tag': KeyInfo(can_disable=True), - 'scope': KeyInfo(), - 'target-scope': KeyInfo(), + 'routing-table': KeyInfo(default='main'), + 'scope': KeyInfo(default=30), + 'target-scope': KeyInfo(default=10), + 'vrf-interface': KeyInfo(can_disable=True), }, ), ('mpls', ): APIData( @@ -1977,13 +2099,33 @@ def join_path(path): }, ), ('queue', 'interface'): APIData( - primary_keys=('name', ), + primary_keys=('interface', ), fully_understood=True, + fixed_entries=True, fields={ - 'name': KeyInfo(required=True), + 'interface': KeyInfo(required=True), 'queue': KeyInfo(required=True), }, ), + ('queue', 'tree'): APIData( + primary_keys=('name', ), + fully_understood=True, + fields={ + 'bucket-size': KeyInfo(default='0.1'), + 'burst-limit': KeyInfo(default=0), + 'burst-threshold': KeyInfo(default=0), + 'burst-time': KeyInfo(default='0s'), + 'comment': KeyInfo(can_disable=True, remove_value=''), + 'disabled': KeyInfo(default=False), + 'limit-at': KeyInfo(default=0), + 'max-limit': KeyInfo(default=0), + 'name': KeyInfo(), + 'packet-mark': KeyInfo(default=''), + 'parent': KeyInfo(required=True), + 'priority': KeyInfo(default=8), + 'queue': KeyInfo(default='default-small'), + }, + ), ('interface', 'ethernet', 'switch'): APIData( fixed_entries=True, primary_keys=('name', ), diff --git a/plugins/modules/api_info.py b/plugins/modules/api_info.py index 92ca1a23..337f11c5 100644 --- a/plugins/modules/api_info.py +++ b/plugins/modules/api_info.py @@ -112,19 +112,30 @@ - ip traffic-flow - ip traffic-flow ipfix - ip upnp + - ipv6 address - ipv6 dhcp-client + - ipv6 dhcp-server + - ipv6 dhcp-server option - ipv6 firewall address-list - ipv6 firewall filter - ipv6 nd prefix default + - ipv6 route - ipv6 settings - mpls - mpls ldp - port firmware - ppp aaa - queue interface + - queue tree - radius incoming - routing bgp instance - routing mme + - routing ospf area + - routing ospf area range + - routing ospf instance + - routing ospf interface-template + - routing pimsm instance + - routing pimsm interface-template - routing rip - routing ripng - snmp diff --git a/plugins/modules/api_modify.py b/plugins/modules/api_modify.py index 4f3dbe8b..97f832da 100644 --- a/plugins/modules/api_modify.py +++ b/plugins/modules/api_modify.py @@ -117,19 +117,30 @@ - ip traffic-flow - ip traffic-flow ipfix - ip upnp + - ipv6 address - ipv6 dhcp-client + - ipv6 dhcp-server + - ipv6 dhcp-server option - ipv6 firewall address-list - ipv6 firewall filter - ipv6 nd prefix default + - ipv6 route - ipv6 settings - mpls - mpls ldp - port firmware - ppp aaa - queue interface + - queue tree - radius incoming - routing bgp instance - routing mme + - routing ospf area + - routing ospf area range + - routing ospf instance + - routing ospf interface-template + - routing pimsm instance + - routing pimsm interface-template - routing rip - routing ripng - snmp From 4fcf36677ff084175057293a09b03eb3ed8cb8cf Mon Sep 17 00:00:00 2001 From: Tomas Herfert Date: Mon, 14 Nov 2022 22:04:04 +0100 Subject: [PATCH 2/4] sanity fix Signed-off-by: Tomas Herfert --- changelogs/fragments/131-api.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/changelogs/fragments/131-api.yml b/changelogs/fragments/131-api.yml index 7e6ba596..316b7b76 100644 --- a/changelogs/fragments/131-api.yml +++ b/changelogs/fragments/131-api.yml @@ -6,10 +6,10 @@ minor_changes: known_issues: - api_modify - when limits for entries in ``queue tree`` are defined as human readable - e.g. 25M, the configuration will be correctly set in ROS, but the module will indicate the item is changed on every run even when there was no change done. This is caused by the ROS API which returns the number in bytes - e.g. 25000000 (which is inconsistent with the CLI behavior). In order to mitigate that, the limits have to be defined in bytes (those will still appear as human readable in the ROS CLI). (https://github.com/ansible-collections/community.routeros/pull/131 - - ``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template`` paths are not fully implemeted for ROS6 due to the significat changes between ROS6 and ROS7. - (https://github.com/ansible-collections/community.routeros/pull/131) + - "``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template`` paths are not fully implemeted for ROS6 due to the significat changes between ROS6 and ROS7. + (https://github.com/ansible-collections/community.routeros/pull/131)" bugfixes: - - ``queue interface`` path works with api_modify now - (https://github.com/ansible-collections/community.routeros/pull/131). - - ``ip route`` entry can be defined wihtout the need of ``gateway`` field (which is correct for unreachable/blackhole type of routes). - (https://github.com/ansible-collections/community.routeros/pull/131). + - "``queue interface`` path works with api_modify now + (https://github.com/ansible-collections/community.routeros/pull/131)." + - "``ip route`` entry can be defined wihtout the need of ``gateway`` field (which is correct for unreachable/blackhole type of routes). + (https://github.com/ansible-collections/community.routeros/pull/131)." From f9cb3e04877a95988b985e8b6d6bbf1341fc8bdc Mon Sep 17 00:00:00 2001 From: Tomas Herfert Date: Mon, 14 Nov 2022 22:10:58 +0100 Subject: [PATCH 3/4] another sanity fix Signed-off-by: Tomas Herfert --- plugins/module_utils/_api_data.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/module_utils/_api_data.py b/plugins/module_utils/_api_data.py index f16cd42e..fa4765dd 100644 --- a/plugins/module_utils/_api_data.py +++ b/plugins/module_utils/_api_data.py @@ -567,7 +567,7 @@ def join_path(path): 'switch-to-spt-bytes': KeyInfo(default=0), 'switch-to-spt-interval': KeyInfo(), 'vrf': KeyInfo(default="main"), - }, + }, ), ('routing', 'pimsm', 'interface-template'): APIData( fully_understood=True, From aefc31a127c725e80a2650a1e794e6ec1aebe071 Mon Sep 17 00:00:00 2001 From: Tomas Herfert <68421396+therfert@users.noreply.github.com> Date: Tue, 15 Nov 2022 21:46:01 +0100 Subject: [PATCH 4/4] Apply suggestions from code review Co-authored-by: Felix Fontein --- changelogs/fragments/131-api.yml | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/changelogs/fragments/131-api.yml b/changelogs/fragments/131-api.yml index 316b7b76..8e2ad1cd 100644 --- a/changelogs/fragments/131-api.yml +++ b/changelogs/fragments/131-api.yml @@ -1,15 +1,15 @@ minor_changes: - api_modify, api_info - support API paths ``ipv6 address``, ``ipv6 dhcp-server``, ``ipv6 dhcp-server option``, ``ipv6 route``, ``queue tree``, ``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template``, ``routing pimsm instance``, ``routing pimsm interface-template`` - (https://github.com/ansible-collections/community.routeros/pull/131) + (https://github.com/ansible-collections/community.routeros/pull/131). - api_modify, api_info - support for fields ``blackhole``, ``pref-src``, ``routing-table``, ``suppress-hw-offload``, ``type``, ``vrf-interface`` in ``ip route`` path - (https://github.com/ansible-collections/community.routeros/pull/131) + (https://github.com/ansible-collections/community.routeros/pull/131). known_issues: - - api_modify - when limits for entries in ``queue tree`` are defined as human readable - e.g. 25M, the configuration will be correctly set in ROS, but the module will indicate the item is changed on every run even when there was no change done. This is caused by the ROS API which returns the number in bytes - e.g. 25000000 (which is inconsistent with the CLI behavior). In order to mitigate that, the limits have to be defined in bytes (those will still appear as human readable in the ROS CLI). - (https://github.com/ansible-collections/community.routeros/pull/131 - - "``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template`` paths are not fully implemeted for ROS6 due to the significat changes between ROS6 and ROS7. - (https://github.com/ansible-collections/community.routeros/pull/131)" + - api_modify - when limits for entries in ``queue tree`` are defined as human readable - for example ``25M`` -, the configuration will be correctly set in ROS, but the module will indicate the item is changed on every run even when there was no change done. This is caused by the ROS API which returns the number in bytes - for example ``25000000`` (which is inconsistent with the CLI behavior). In order to mitigate that, the limits have to be defined in bytes (those will still appear as human readable in the ROS CLI) + (https://github.com/ansible-collections/community.routeros/pull/131). + - "api_modify, api_info - ``routing ospf area``, ``routing ospf area range``, ``routing ospf instance``, ``routing ospf interface-template`` paths are not fully implemeted for ROS6 due to the significat changes between ROS6 and ROS7 + (https://github.com/ansible-collections/community.routeros/pull/131)." bugfixes: - - "``queue interface`` path works with api_modify now + - "api_modify - ``queue interface`` path works now (https://github.com/ansible-collections/community.routeros/pull/131)." - - "``ip route`` entry can be defined wihtout the need of ``gateway`` field (which is correct for unreachable/blackhole type of routes). + - "api_modify - ``ip route`` entry can be defined without the need of ``gateway`` field, which is correct for unreachable/blackhole type of routes (https://github.com/ansible-collections/community.routeros/pull/131)."