summaryrefslogtreecommitdiffstats
path: root/ansible_collections/community/routeros/plugins/modules
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-18 05:52:35 +0000
commit7fec0b69a082aaeec72fee0612766aa42f6b1b4d (patch)
treeefb569b86ca4da888717f5433e757145fa322e08 /ansible_collections/community/routeros/plugins/modules
parentReleasing progress-linux version 7.7.0+dfsg-3~progress7.99u1. (diff)
downloadansible-7fec0b69a082aaeec72fee0612766aa42f6b1b4d.tar.xz
ansible-7fec0b69a082aaeec72fee0612766aa42f6b1b4d.zip
Merging upstream version 9.4.0+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'ansible_collections/community/routeros/plugins/modules')
-rw-r--r--ansible_collections/community/routeros/plugins/modules/api.py58
-rw-r--r--ansible_collections/community/routeros/plugins/modules/api_facts.py46
-rw-r--r--ansible_collections/community/routeros/plugins/modules/api_find_and_modify.py16
-rw-r--r--ansible_collections/community/routeros/plugins/modules/api_info.py100
-rw-r--r--ansible_collections/community/routeros/plugins/modules/api_modify.py175
-rw-r--r--ansible_collections/community/routeros/plugins/modules/command.py12
-rw-r--r--ansible_collections/community/routeros/plugins/modules/facts.py52
7 files changed, 345 insertions, 114 deletions
diff --git a/ansible_collections/community/routeros/plugins/modules/api.py b/ansible_collections/community/routeros/plugins/modules/api.py
index f9c619fc1..4857a3cd9 100644
--- a/ansible_collections/community/routeros/plugins/modules/api.py
+++ b/ansible_collections/community/routeros/plugins/modules/api.py
@@ -17,7 +17,7 @@ description:
- Ansible module for RouterOS API with the Python C(librouteros) library.
- This module can add, remove, update, query and execute arbitrary command in RouterOS via API.
notes:
- - I(add), I(remove), I(update), I(cmd) and I(query) are mutually exclusive.
+ - O(add), O(remove), O(update), O(cmd), and O(query) are mutually exclusive.
- Use the M(community.routeros.api_modify) and M(community.routeros.api_find_and_modify) modules
for more specific modifications, and the M(community.routeros.api_info) module for a more controlled
way of returning all entries for a path.
@@ -40,26 +40,26 @@ options:
description:
- Main path for all other arguments.
- If other arguments are not set, api will return all items in selected path.
- - Example C(ip address). Equivalent of RouterOS CLI C(/ip address print).
+ - Example V(ip address). Equivalent of RouterOS CLI C(/ip address print).
required: true
type: str
add:
description:
- Will add selected arguments in selected path to RouterOS config.
- - Example C(address=1.1.1.1/32 interface=ether1).
+ - Example V(address=1.1.1.1/32 interface=ether1).
- Equivalent in RouterOS CLI C(/ip address add address=1.1.1.1/32 interface=ether1).
type: str
remove:
description:
- Remove config/value from RouterOS by '.id'.
- - Example C(*03) will remove config/value with C(id=*03) in selected path.
+ - Example V(*03) will remove config/value with C(id=*03) in selected path.
- Equivalent in RouterOS CLI C(/ip address remove numbers=1).
- Note C(number) in RouterOS CLI is different from C(.id).
type: str
update:
description:
- Update config/value in RouterOS by '.id' in selected path.
- - Example C(.id=*03 address=1.1.1.3/32) and path C(ip address) will replace existing ip address with C(.id=*03).
+ - Example V(.id=*03 address=1.1.1.3/32) and path V(ip address) will replace existing ip address with C(.id=*03).
- Equivalent in RouterOS CLI C(/ip address set address=1.1.1.3/32 numbers=1).
- Note C(number) in RouterOS CLI is different from C(.id).
type: str
@@ -67,11 +67,11 @@ options:
description:
- Query given path for selected query attributes from RouterOS aip.
- WHERE is key word which extend query. WHERE format is key operator value - with spaces.
- - WHERE valid operators are C(==) or C(eq), C(!=) or C(not), C(>) or C(more), C(<) or C(less).
- - Example path C(ip address) and query C(.id address) will return only C(.id) and C(address) for all items in C(ip address) path.
- - Example path C(ip address) and query C(.id address WHERE address == 1.1.1.3/32).
- will return only C(.id) and C(address) for items in C(ip address) path, where address is eq to 1.1.1.3/32.
- - Example path C(interface) and query C(mtu name WHERE mut > 1400) will
+ - WHERE valid operators are V(==) or V(eq), V(!=) or V(not), V(>) or V(more), V(<) or V(less).
+ - Example path V(ip address) and query V(.id address) will return only C(.id) and C(address) for all items in V(ip address) path.
+ - Example path V(ip address) and query V(.id address WHERE address == 1.1.1.3/32).
+ will return only C(.id) and C(address) for items in V(ip address) path, where address is eq to 1.1.1.3/32.
+ - Example path V(interface) and query V(mtu name WHERE mut > 1400) will
return only interfaces C(mtu,name) where mtu is bigger than 1400.
- Equivalent in RouterOS CLI C(/interface print where mtu > 1400).
type: str
@@ -84,65 +84,69 @@ options:
attributes:
description:
- The list of attributes to return.
- - Every attribute used in a I(where) clause need to be listed here.
+ - Every attribute used in a O(extended_query.where[]) clause need to be listed here.
type: list
elements: str
required: true
where:
description:
- Allows to restrict the objects returned.
- - The conditions here must all match. An I(or) condition needs at least one of its conditions to match.
+ - The conditions here must all match. An O(extended_query.where[].or) condition needs at least one of its conditions to match.
type: list
elements: dict
suboptions:
attribute:
description:
- - The attribute to match. Must be part of I(attributes).
- - Either I(or) or all of I(attribute), I(is), and I(value) have to be specified.
+ - The attribute to match. Must be part of O(extended_query.attributes).
+ - Either O(extended_query.where[].or) or all of O(extended_query.where[].attribute), O(extended_query.where[].is),
+ and O(extended_query.where[].value) have to be specified.
type: str
is:
description:
- The operator to use for matching.
- - For equality use C(==) or C(eq). For less use C(<) or C(less). For more use C(>) or C(more).
- - Use C(in) to check whether the value is part of a list. In that case, I(value) must be a list.
- - Either I(or) or all of I(attribute), I(is), and I(value) have to be specified.
+ - For equality use V(==) or V(eq). For less use V(<) or V(less). For more use V(>) or V(more).
+ - Use V(in) to check whether the value is part of a list. In that case, O(extended_query.where[].value) must be a list.
+ - Either O(extended_query.where[].or) or all of O(extended_query.where[].attribute), O(extended_query.where[].is),
+ and O(extended_query.where[].value) have to be specified.
type: str
choices: ["==", "!=", ">", "<", "in", "eq", "not", "more", "less"]
value:
description:
- - The value to compare to. Must be a list for I(is=in).
- - Either I(or) or all of I(attribute), I(is), and I(value) have to be specified.
+ - The value to compare to. Must be a list for O(extended_query.where[].is=in).
+ - Either O(extended_query.where[].or) or all of O(extended_query.where[].attribute), O(extended_query.where[].is),
+ and O(extended_query.where[].value) have to be specified.
type: raw
or:
description:
- A list of conditions so that at least one of them has to match.
- - Either I(or) or all of I(attribute), I(is), and I(value) have to be specified.
+ - Either O(extended_query.where[].or) or all of O(extended_query.where[].attribute), O(extended_query.where[].is),
+ and O(extended_query.where[].value) have to be specified.
type: list
elements: dict
suboptions:
attribute:
description:
- - The attribute to match. Must be part of I(attributes).
+ - The attribute to match. Must be part of O(extended_query.attributes).
type: str
required: true
is:
description:
- The operator to use for matching.
- - For equality use C(==) or C(eq). For less use C(<) or C(less). For more use C(>) or C(more).
- - Use C(in) to check whether the value is part of a list. In that case, I(value) must be a list.
+ - For equality use V(==) or V(eq). For less use V(<) or V(less). For more use V(>) or V(more).
+ - Use V(in) to check whether the value is part of a list. In that case, O(extended_query.where[].or[].value) must be a list.
type: str
choices: ["==", "!=", ">", "<", "in", "eq", "not", "more", "less"]
required: true
value:
description:
- - The value to compare to. Must be a list for I(is=in).
+ - The value to compare to. Must be a list for O(extended_query.where[].or[].is=in).
type: raw
required: true
cmd:
description:
- Execute any/arbitrary command in selected path, after the command we can add C(.id).
- - Example path C(system script) and cmd C(run .id=*03) is equivalent in RouterOS CLI C(/system script run number=0).
- - Example path C(ip address) and cmd C(print) is equivalent in RouterOS CLI C(/ip address print).
+ - Example path V(system script) and cmd V(run .id=*03) is equivalent in RouterOS CLI C(/system script run number=0).
+ - Example path V(ip address) and cmd V(print) is equivalent in RouterOS CLI C(/ip address print).
type: str
seealso:
- ref: ansible_collections.community.routeros.docsite.quoting
@@ -220,7 +224,7 @@ EXAMPLES = '''
ansible.builtin.debug:
msg: '{{ extended_queryout }}'
-- name: Update example - ether2 ip addres with ".id = *14"
+- name: Update example - ether2 ip address with ".id = *14"
community.routeros.api:
hostname: "{{ hostname }}"
password: "{{ password }}"
diff --git a/ansible_collections/community/routeros/plugins/modules/api_facts.py b/ansible_collections/community/routeros/plugins/modules/api_facts.py
index f29723667..296621ea6 100644
--- a/ansible_collections/community/routeros/plugins/modules/api_facts.py
+++ b/ansible_collections/community/routeros/plugins/modules/api_facts.py
@@ -41,9 +41,9 @@ options:
description:
- When supplied, this argument will restrict the facts collected
to a given subset. Possible values for this argument include
- C(all), C(hardware), C(interfaces), and C(routing).
+ V(all), V(hardware), V(interfaces), and V(routing).
- Can specify a list of values to include a larger subset.
- Values can also be used with an initial C(!) to specify that a
+ Values can also be used with an initial V(!) to specify that a
specific subset should not be collected.
required: false
default:
@@ -89,93 +89,93 @@ ansible_facts:
# default
ansible_net_model:
description: The model name returned from the device.
- returned: I(gather_subset) contains C(default)
+ returned: O(gather_subset) contains V(default)
type: str
ansible_net_serialnum:
description: The serial number of the remote device.
- returned: I(gather_subset) contains C(default)
+ returned: O(gather_subset) contains V(default)
type: str
ansible_net_version:
description: The operating system version running on the remote device.
- returned: I(gather_subset) contains C(default)
+ returned: O(gather_subset) contains V(default)
type: str
ansible_net_hostname:
description: The configured hostname of the device.
- returned: I(gather_subset) contains C(default)
+ returned: O(gather_subset) contains V(default)
type: str
ansible_net_arch:
description: The CPU architecture of the device.
- returned: I(gather_subset) contains C(default)
+ returned: O(gather_subset) contains V(default)
type: str
ansible_net_uptime:
description: The uptime of the device.
- returned: I(gather_subset) contains C(default)
+ returned: O(gather_subset) contains V(default)
type: str
ansible_net_cpu_load:
description: Current CPU load.
- returned: I(gather_subset) contains C(default)
+ returned: O(gather_subset) contains V(default)
type: str
# hardware
ansible_net_spacefree_mb:
description: The available disk space on the remote device in MiB.
- returned: I(gather_subset) contains C(hardware)
+ returned: O(gather_subset) contains V(hardware)
type: dict
ansible_net_spacetotal_mb:
description: The total disk space on the remote device in MiB.
- returned: I(gather_subset) contains C(hardware)
+ returned: O(gather_subset) contains V(hardware)
type: dict
ansible_net_memfree_mb:
description: The available free memory on the remote device in MiB.
- returned: I(gather_subset) contains C(hardware)
+ returned: O(gather_subset) contains V(hardware)
type: int
ansible_net_memtotal_mb:
description: The total memory on the remote device in MiB.
- returned: I(gather_subset) contains C(hardware)
+ returned: O(gather_subset) contains V(hardware)
type: int
# interfaces
ansible_net_all_ipv4_addresses:
description: All IPv4 addresses configured on the device.
- returned: I(gather_subset) contains C(interfaces)
+ returned: O(gather_subset) contains V(interfaces)
type: list
ansible_net_all_ipv6_addresses:
description: All IPv6 addresses configured on the device.
- returned: I(gather_subset) contains C(interfaces)
+ returned: O(gather_subset) contains V(interfaces)
type: list
ansible_net_interfaces:
description: A hash of all interfaces running on the system.
- returned: I(gather_subset) contains C(interfaces)
+ returned: O(gather_subset) contains V(interfaces)
type: dict
ansible_net_neighbors:
description: The list of neighbors from the remote device.
- returned: I(gather_subset) contains C(interfaces)
+ returned: O(gather_subset) contains V(interfaces)
type: dict
# routing
ansible_net_bgp_peer:
description: A dictionary with BGP peer information.
- returned: I(gather_subset) contains C(routing)
+ returned: O(gather_subset) contains V(routing)
type: dict
ansible_net_bgp_vpnv4_route:
description: A dictionary with BGP vpnv4 route information.
- returned: I(gather_subset) contains C(routing)
+ returned: O(gather_subset) contains V(routing)
type: dict
ansible_net_bgp_instance:
description: A dictionary with BGP instance information.
- returned: I(gather_subset) contains C(routing)
+ returned: O(gather_subset) contains V(routing)
type: dict
ansible_net_route:
description: A dictionary for routes in all routing tables.
- returned: I(gather_subset) contains C(routing)
+ returned: O(gather_subset) contains V(routing)
type: dict
ansible_net_ospf_instance:
description: A dictionary with OSPF instances.
- returned: I(gather_subset) contains C(routing)
+ returned: O(gather_subset) contains V(routing)
type: dict
ansible_net_ospf_neighbor:
description: A dictionary with OSPF neighbors.
- returned: I(gather_subset) contains C(routing)
+ returned: O(gather_subset) contains V(routing)
type: dict
"""
diff --git a/ansible_collections/community/routeros/plugins/modules/api_find_and_modify.py b/ansible_collections/community/routeros/plugins/modules/api_find_and_modify.py
index 0be3f7039..176c9437f 100644
--- a/ansible_collections/community/routeros/plugins/modules/api_find_and_modify.py
+++ b/ansible_collections/community/routeros/plugins/modules/api_find_and_modify.py
@@ -21,7 +21,7 @@ description:
or change multiple entries in different ways in one step.
notes:
- "If you want to change values based on their old values (like change all comments 'foo' to 'bar') and make sure that
- there are at least N such values, you can use I(require_matches_min=N) together with I(allow_no_matches=true).
+ there are at least N such values, you can use O(require_matches_min=N) together with O(allow_no_matches=true).
This will make the module fail if there are less than N such entries, but not if there is no match. The latter case
is needed for idempotency of the task: once the values have been changed, there should be no further match."
extends_documentation_fragment:
@@ -40,21 +40,21 @@ options:
path:
description:
- Path to query.
- - An example value is C(ip address). This is equivalent to running C(/ip address) in the RouterOS CLI.
+ - An example value is V(ip address). This is equivalent to running C(/ip address) in the RouterOS CLI.
required: true
type: str
find:
description:
- Fields to search for.
- - The module will only consider entries in the given I(path) that match all fields provided here.
- - Use YAML C(~), or prepend keys with C(!), to specify an unset value.
+ - The module will only consider entries in the given O(path) that match all fields provided here.
+ - Use YAML V(~), or prepend keys with V(!), to specify an unset value.
- Note that if the dictionary specified here is empty, every entry in the path will be matched.
required: true
type: dict
values:
description:
- - On all entries matching the conditions in I(find), set the keys of this option to the values specified here.
- - Use YAML C(~), or prepend keys with C(!), to specify to unset a value.
+ - On all entries matching the conditions in O(find), set the keys of this option to the values specified here.
+ - Use YAML V(~), or prepend keys with V(!), to specify to unset a value.
required: true
type: dict
require_matches_min:
@@ -72,7 +72,7 @@ options:
allow_no_matches:
description:
- Whether to allow that no match is found.
- - If not specified, this value is induced from whether I(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
seealso:
- module: community.routeros.api
@@ -146,7 +146,7 @@ new_data:
returned: success
match_count:
description:
- - The number of entries that matched the criteria in I(find).
+ - The number of entries that matched the criteria in O(find).
sample: 1
type: int
returned: success
diff --git a/ansible_collections/community/routeros/plugins/modules/api_info.py b/ansible_collections/community/routeros/plugins/modules/api_info.py
index 50228c063..f9a39464f 100644
--- a/ansible_collections/community/routeros/plugins/modules/api_info.py
+++ b/ansible_collections/community/routeros/plugins/modules/api_info.py
@@ -18,9 +18,9 @@ version_added: 2.2.0
description:
- Allows to retrieve information for a path using the API.
- This can be used to backup a path to restore it with the M(community.routeros.api_modify) module.
- - Entries are normalized, dynamic and builtin entries are not returned. Use the I(handle_disabled) and
- I(hide_defaults) options to control normalization, the I(include_dynamic) and I(include_builtin) options to also return
- dynamic resp. builtin entries, and use I(unfiltered) to return all fields including counters.
+ - Entries are normalized, dynamic and builtin entries are not returned. Use the O(handle_disabled) and
+ O(hide_defaults) options to control normalization, the O(include_dynamic) and O(include_builtin) options to also return
+ dynamic resp. builtin entries, and use O(unfiltered) to return all fields including counters.
- B(Note) that this module is still heavily in development, and only supports B(some) paths.
If you want to support new paths, or think you found problems with existing paths, please first
L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/).
@@ -37,16 +37,18 @@ options:
path:
description:
- Path to query.
- - An example value is C(ip address). This is equivalent to running C(/ip address print) in the RouterOS CLI.
+ - An example value is V(ip address). This is equivalent to running C(/ip address print) in the RouterOS CLI.
required: true
type: str
choices:
# BEGIN PATH LIST
- caps-man aaa
- caps-man access-list
+ - caps-man channel
- caps-man configuration
- caps-man datapath
- caps-man manager
+ - caps-man manager interface
- caps-man provisioning
- caps-man security
- certificate settings
@@ -69,18 +71,47 @@ options:
- interface l2tp-server server
- interface list
- interface list member
+ - interface ovpn-client
- interface ovpn-server server
+ - interface ppp-client
- interface pppoe-client
- interface pptp-server server
- interface sstp-server server
- interface vlan
- interface vrrp
+ - interface wifi
+ - interface wifi aaa
+ - interface wifi access-list
+ - interface wifi cap
+ - interface wifi capsman
+ - interface wifi channel
+ - interface wifi configuration
+ - interface wifi datapath
+ - interface wifi interworking
+ - interface wifi provisioning
+ - interface wifi security
+ - interface wifi steering
+ - interface wifiwave2
+ - interface wifiwave2 aaa
+ - interface wifiwave2 access-list
+ - interface wifiwave2 cap
+ - interface wifiwave2 capsman
+ - interface wifiwave2 channel
+ - interface wifiwave2 configuration
+ - interface wifiwave2 datapath
+ - interface wifiwave2 interworking
+ - interface wifiwave2 provisioning
+ - interface wifiwave2 security
+ - interface wifiwave2 steering
- interface wireguard
- interface wireguard peers
+ - interface wireless
- interface wireless align
- interface wireless cap
+ - interface wireless security-profiles
- interface wireless sniffer
- interface wireless snooper
+ - iot modbus
- ip accounting
- ip accounting web-access
- ip address
@@ -93,6 +124,8 @@ options:
- ip dhcp-server config
- ip dhcp-server lease
- ip dhcp-server network
+ - ip dhcp-server option
+ - ip dhcp-server option sets
- ip dns
- ip dns static
- ip firewall address-list
@@ -123,7 +156,10 @@ options:
- ip tftp settings
- ip traffic-flow
- ip traffic-flow ipfix
+ - ip traffic-flow target
- ip upnp
+ - ip upnp interfaces
+ - ip vrf
- ipv6 address
- ipv6 dhcp-client
- ipv6 dhcp-server
@@ -131,6 +167,7 @@ options:
- ipv6 firewall address-list
- ipv6 firewall filter
- ipv6 firewall mangle
+ - ipv6 firewall nat
- ipv6 firewall raw
- ipv6 nd
- ipv6 nd prefix default
@@ -139,11 +176,19 @@ options:
- mpls
- mpls ldp
- port firmware
+ - port remote-access
- ppp aaa
+ - ppp profile
- queue interface
- queue tree
+ - radius
- radius incoming
+ - routing bgp connection
- routing bgp instance
+ - routing bgp template
+ - routing filter rule
+ - routing filter select-rule
+ - routing id
- routing mme
- routing ospf area
- routing ospf area range
@@ -153,6 +198,8 @@ options:
- routing pimsm interface-template
- routing rip
- routing ripng
+ - routing rule
+ - routing table
- snmp
- snmp community
- system clock
@@ -175,15 +222,20 @@ options:
- tool bandwidth-server
- tool e-mail
- tool graphing
+ - tool graphing interface
+ - tool graphing resource
- tool mac-server
- tool mac-server mac-winbox
- tool mac-server ping
+ - tool netwatch
- tool romon
- tool sms
- tool sniffer
- tool traffic-generator
+ - user
- user aaa
- user group
+ - user settings
# END PATH LIST
unfiltered:
description:
@@ -194,9 +246,9 @@ options:
handle_disabled:
description:
- How to handle unset values.
- - C(exclamation) prepends the keys with C(!) in the output with value C(null).
- - C(null-value) uses the regular key with value C(null).
- - C(omit) omits these values from the result.
+ - V(exclamation) prepends the keys with V(!) in the output with value V(null).
+ - V(null-value) uses the regular key with value V(null).
+ - V(omit) omits these values from the result.
type: str
choices:
- exclamation
@@ -212,17 +264,24 @@ options:
description:
- Whether to include dynamic values.
- By default, they are not returned, and the C(dynamic) keys are omitted.
- - If set to C(true), they are returned as well, and the C(dynamic) keys are returned as well.
+ - If set to V(true), they are returned as well, and the C(dynamic) keys are returned as well.
type: bool
default: false
include_builtin:
description:
- Whether to include builtin values.
- By default, they are not returned, and the C(builtin) keys are omitted.
- - If set to C(true), they are returned as well, and the C(builtin) keys are returned as well.
+ - If set to V(true), they are returned as well, and the C(builtin) keys are returned as well.
type: bool
default: false
version_added: 2.4.0
+ include_read_only:
+ description:
+ - Whether to include read-only fields.
+ - By default, they are not returned.
+ type: bool
+ default: false
+ version_added: 2.10.0
seealso:
- module: community.routeros.api
- module: community.routeros.api_facts
@@ -271,6 +330,7 @@ from ansible_collections.community.routeros.plugins.module_utils.api import (
api_argument_spec,
check_has_library,
create_api,
+ get_api_version,
)
from ansible_collections.community.routeros.plugins.module_utils._api_data import (
@@ -301,6 +361,7 @@ def main():
hide_defaults=dict(type='bool', default=True),
include_dynamic=dict(type='bool', default=False),
include_builtin=dict(type='bool', default=False),
+ include_read_only=dict(type='bool', default=False),
)
module_args.update(api_argument_spec())
@@ -313,14 +374,24 @@ def main():
api = create_api(module)
path = split_path(module.params['path'])
- path_info = PATHS.get(tuple(path))
- if path_info is None:
+ versioned_path_info = PATHS.get(tuple(path))
+ if versioned_path_info is None:
module.fail_json(msg='Path /{path} is not yet supported'.format(path='/'.join(path)))
+ if versioned_path_info.needs_version:
+ api_version = get_api_version(api)
+ supported, not_supported_msg = versioned_path_info.provide_version(api_version)
+ if not supported:
+ msg = 'Path /{path} is not supported for API version {api_version}'.format(path='/'.join(path), api_version=api_version)
+ if not_supported_msg:
+ msg = '{0}: {1}'.format(msg, not_supported_msg)
+ module.fail_json(msg=msg)
+ path_info = versioned_path_info.get_data()
handle_disabled = module.params['handle_disabled']
hide_defaults = module.params['hide_defaults']
include_dynamic = module.params['include_dynamic']
include_builtin = module.params['include_builtin']
+ include_read_only = module.params['include_read_only']
try:
api_path = compose_api_path(api, path)
@@ -344,7 +415,10 @@ def main():
if k not in path_info.fields:
entry.pop(k)
if handle_disabled != 'omit':
- for k in path_info.fields:
+ for k, field_info in path_info.fields.items():
+ if field_info.write_only:
+ entry.pop(k, None)
+ continue
if k not in entry:
if handle_disabled == 'exclamation':
k = '!%s' % k
@@ -355,6 +429,8 @@ def main():
entry.pop(k)
if field_info.absent_value and k not in entry:
entry[k] = field_info.absent_value
+ if not include_read_only and k in entry and field_info.read_only:
+ entry.pop(k)
result.append(entry)
module.exit_json(result=result)
diff --git a/ansible_collections/community/routeros/plugins/modules/api_modify.py b/ansible_collections/community/routeros/plugins/modules/api_modify.py
index 5d410e9fb..d71750073 100644
--- a/ansible_collections/community/routeros/plugins/modules/api_modify.py
+++ b/ansible_collections/community/routeros/plugins/modules/api_modify.py
@@ -24,6 +24,10 @@ description:
- B(Note) that this module is still heavily in development, and only supports B(some) paths.
If you want to support new paths, or think you found problems with existing paths, please first
L(create an issue in the community.routeros Issue Tracker,https://github.com/ansible-collections/community.routeros/issues/).
+notes:
+ - If write-only fields are present in the path, the module is B(not idempotent) in a strict sense,
+ since it is not able to verify the current value of these fields. The behavior the module should
+ assume can be controlled with the O(handle_write_only) option.
requirements:
- Needs L(ordereddict,https://pypi.org/project/ordereddict) for Python 2.6
extends_documentation_fragment:
@@ -42,16 +46,18 @@ options:
path:
description:
- Path to query.
- - An example value is C(ip address). This is equivalent to running modification commands in C(/ip address) in the RouterOS CLI.
+ - An example value is V(ip address). This is equivalent to running modification commands in C(/ip address) in the RouterOS CLI.
required: true
type: str
choices:
# BEGIN PATH LIST
- caps-man aaa
- caps-man access-list
+ - caps-man channel
- caps-man configuration
- caps-man datapath
- caps-man manager
+ - caps-man manager interface
- caps-man provisioning
- caps-man security
- certificate settings
@@ -74,18 +80,47 @@ options:
- interface l2tp-server server
- interface list
- interface list member
+ - interface ovpn-client
- interface ovpn-server server
+ - interface ppp-client
- interface pppoe-client
- interface pptp-server server
- interface sstp-server server
- interface vlan
- interface vrrp
+ - interface wifi
+ - interface wifi aaa
+ - interface wifi access-list
+ - interface wifi cap
+ - interface wifi capsman
+ - interface wifi channel
+ - interface wifi configuration
+ - interface wifi datapath
+ - interface wifi interworking
+ - interface wifi provisioning
+ - interface wifi security
+ - interface wifi steering
+ - interface wifiwave2
+ - interface wifiwave2 aaa
+ - interface wifiwave2 access-list
+ - interface wifiwave2 cap
+ - interface wifiwave2 capsman
+ - interface wifiwave2 channel
+ - interface wifiwave2 configuration
+ - interface wifiwave2 datapath
+ - interface wifiwave2 interworking
+ - interface wifiwave2 provisioning
+ - interface wifiwave2 security
+ - interface wifiwave2 steering
- interface wireguard
- interface wireguard peers
+ - interface wireless
- interface wireless align
- interface wireless cap
+ - interface wireless security-profiles
- interface wireless sniffer
- interface wireless snooper
+ - iot modbus
- ip accounting
- ip accounting web-access
- ip address
@@ -98,6 +133,8 @@ options:
- ip dhcp-server config
- ip dhcp-server lease
- ip dhcp-server network
+ - ip dhcp-server option
+ - ip dhcp-server option sets
- ip dns
- ip dns static
- ip firewall address-list
@@ -128,7 +165,10 @@ options:
- ip tftp settings
- ip traffic-flow
- ip traffic-flow ipfix
+ - ip traffic-flow target
- ip upnp
+ - ip upnp interfaces
+ - ip vrf
- ipv6 address
- ipv6 dhcp-client
- ipv6 dhcp-server
@@ -136,6 +176,7 @@ options:
- ipv6 firewall address-list
- ipv6 firewall filter
- ipv6 firewall mangle
+ - ipv6 firewall nat
- ipv6 firewall raw
- ipv6 nd
- ipv6 nd prefix default
@@ -144,11 +185,19 @@ options:
- mpls
- mpls ldp
- port firmware
+ - port remote-access
- ppp aaa
+ - ppp profile
- queue interface
- queue tree
+ - radius
- radius incoming
+ - routing bgp connection
- routing bgp instance
+ - routing bgp template
+ - routing filter rule
+ - routing filter select-rule
+ - routing id
- routing mme
- routing ospf area
- routing ospf area range
@@ -158,6 +207,8 @@ options:
- routing pimsm interface-template
- routing rip
- routing ripng
+ - routing rule
+ - routing table
- snmp
- snmp community
- system clock
@@ -180,15 +231,20 @@ options:
- tool bandwidth-server
- tool e-mail
- tool graphing
+ - tool graphing interface
+ - tool graphing resource
- tool mac-server
- tool mac-server mac-winbox
- tool mac-server ping
+ - tool netwatch
- tool romon
- tool sms
- tool sniffer
- tool traffic-generator
+ - user
- user aaa
- user group
+ - user settings
# END PATH LIST
data:
description:
@@ -200,15 +256,15 @@ options:
elements: dict
ensure_order:
description:
- - Whether to ensure the same order of the config as present in I(data).
- - Requires I(handle_absent_entries=remove).
+ - Whether to ensure the same order of the config as present in O(data).
+ - Requires O(handle_absent_entries=remove).
type: bool
default: false
handle_absent_entries:
description:
- - How to handle entries that are present in the current config, but not in I(data).
- - C(ignore) ignores them.
- - C(remove) removes them.
+ - How to handle entries that are present in the current config, but not in O(data).
+ - V(ignore) ignores them.
+ - V(remove) removes them.
type: str
choices:
- ignore
@@ -216,18 +272,48 @@ options:
default: ignore
handle_entries_content:
description:
- - For a single entry in I(data), this describes how to handle fields that are not mentioned
+ - For a single entry in O(data), this describes how to handle fields that are not mentioned
in that entry, but appear in the actual config.
- - If C(ignore), they are not modified.
- - If C(remove), they are removed. If at least one cannot be removed, the module will fail.
- - If C(remove_as_much_as_possible), all that can be removed will be removed. The ones that
+ - If V(ignore), they are not modified.
+ - If V(remove), they are removed. If at least one cannot be removed, the module will fail.
+ - If V(remove_as_much_as_possible), all that can be removed will be removed. The ones that
cannot be removed will be kept.
+ - Note that V(remove) and V(remove_as_much_as_possible) do not apply to write-only fields.
type: str
choices:
- ignore
- remove
- remove_as_much_as_possible
default: ignore
+ handle_read_only:
+ description:
+ - How to handle values passed in for read-only fields.
+ - If V(ignore), they are not passed to the API.
+ - If V(validate), the values are not passed for creation, and for updating they are compared to the value returned for the object.
+ If they differ, the module fails.
+ - If V(error), the module will fail if read-only fields are provided.
+ type: str
+ choices:
+ - ignore
+ - validate
+ - error
+ default: error
+ version_added: 2.10.0
+ handle_write_only:
+ description:
+ - How to handle values passed in for write-only fields.
+ - If V(create_only), they are passed on creation, and ignored for updating.
+ - If V(always_update), they are always passed to the API. This means that if such a value is present,
+ the module will always result in C(changed) since there is no way to validate whether the value
+ actually changed.
+ - If V(error), the module will fail if write-only fields are provided.
+ type: str
+ choices:
+ - create_only
+ - always_update
+ - error
+ default: create_only
+ version_added: 2.10.0
seealso:
- module: community.routeros.api
- module: community.routeros.api_facts
@@ -320,6 +406,7 @@ from ansible_collections.community.routeros.plugins.module_utils.api import (
api_argument_spec,
check_has_library,
create_api,
+ get_api_version,
)
from ansible_collections.community.routeros.plugins.module_utils._api_data import (
@@ -373,6 +460,18 @@ def find_modifications(old_entry, new_entry, path_info, module, for_text='', ret
continue
if k not in old_entry and path_info.fields[k].default == v and not path_info.fields[k].can_disable:
continue
+ key_info = path_info.fields[k]
+ if key_info.read_only:
+ # handle_read_only must be 'validate'
+ if old_entry.get(k) != v:
+ module.fail_json(
+ msg='Read-only key "{key}" has value "{old_value}", but should have new value "{new_value}"{for_text}.'.format(
+ key=k, old_value=old_entry.get(k), new_value=v, for_text=for_text))
+ continue
+ if key_info.write_only:
+ if module.params['handle_write_only'] == 'create_only':
+ # do not update this value
+ continue
if k not in old_entry or old_entry[k] != v:
modifications[k] = v
updated_entry[k] = v
@@ -441,6 +540,18 @@ def essentially_same_weight(old_entry, new_entry, path_info, module):
return weight
+def remove_read_only(entry, path_info):
+ to_remove = []
+ for real_k, v in entry.items():
+ k = real_k
+ if k.startswith('!'):
+ k = k[1:]
+ if path_info.fields[k].read_only:
+ to_remove.append(real_k)
+ for k in to_remove:
+ entry.pop(k)
+
+
def format_pk(primary_keys, values):
return ', '.join('{pk}="{value}"'.format(pk=pk, value=value) for pk, value in zip(primary_keys, values))
@@ -448,6 +559,7 @@ def format_pk(primary_keys, values):
def polish_entry(entry, path_info, module, for_text):
if '.id' in entry:
entry.pop('.id')
+ to_remove = []
for key, value in entry.items():
real_key = key
disabled_key = False
@@ -467,6 +579,16 @@ def polish_entry(entry, path_info, module, for_text):
elif value is None:
if not key_info.can_disable:
module.fail_json(msg='Key "{key}" must not be disabled (value null/~/None){for_text}.'.format(key=key, for_text=for_text))
+ if key_info.read_only:
+ if module.params['handle_read_only'] == 'error':
+ module.fail_json(msg='Key "{key}" is read-only{for_text}, and handle_read_only=error.'.format(key=key, for_text=for_text))
+ if module.params['handle_read_only'] == 'ignore':
+ to_remove.append(real_key)
+ if key_info.write_only:
+ if module.params['handle_write_only'] == 'error':
+ module.fail_json(msg='Key "{key}" is write-only{for_text}, and handle_write_only=error.'.format(key=key, for_text=for_text))
+ for key in to_remove:
+ entry.pop(key)
for key, field_info in path_info.fields.items():
if field_info.required and key not in entry:
module.fail_json(msg='Key "{key}" must be present{for_text}.'.format(key=key, for_text=for_text))
@@ -622,6 +744,7 @@ def sync_list(module, api, path, path_info):
new_data.append((old_index, updated_entry))
new_entry['.id'] = old_entry['.id']
else:
+ remove_read_only(new_entry, path_info)
create_list.append(new_entry)
if handle_absent_entries == 'remove':
@@ -814,6 +937,7 @@ def sync_with_primary_keys(module, api, path, path_info):
for primary_key in primary_keys
]),
))
+ remove_read_only(new_entry, path_info)
create_list.append(new_entry)
new_entry = new_entry.copy()
for key in list(new_entry):
@@ -992,14 +1116,31 @@ def get_backend(path_info):
return None
+def has_backend(versioned_path_info):
+ if not versioned_path_info.fully_understood:
+ return False
+
+ if versioned_path_info.unversioned is not None:
+ return get_backend(versioned_path_info.unversioned) is not None
+
+ if versioned_path_info.versioned is not None:
+ for dummy, dummy, unversioned in versioned_path_info.versioned:
+ if unversioned and not isinstance(unversioned, str) and get_backend(unversioned) is not None:
+ return True
+
+ return False
+
+
def main():
- path_choices = sorted([join_path(path) for path, path_info in PATHS.items() if get_backend(path_info) is not None])
+ path_choices = sorted([join_path(path) for path, versioned_path_info in PATHS.items() if has_backend(versioned_path_info)])
module_args = dict(
path=dict(type='str', required=True, choices=path_choices),
data=dict(type='list', elements='dict', required=True),
handle_absent_entries=dict(type='str', choices=['ignore', 'remove'], default='ignore'),
handle_entries_content=dict(type='str', choices=['ignore', 'remove', 'remove_as_much_as_possible'], default='ignore'),
ensure_order=dict(type='bool', default=False),
+ handle_read_only=dict(type='str', default='error', choices=['ignore', 'validate', 'error']),
+ handle_write_only=dict(type='str', default='create_only', choices=['create_only', 'always_update', 'error']),
)
module_args.update(api_argument_spec())
@@ -1018,7 +1159,17 @@ def main():
api = create_api(module)
path = split_path(module.params['path'])
- path_info = PATHS.get(tuple(path))
+ versioned_path_info = PATHS.get(tuple(path))
+ if versioned_path_info.needs_version:
+ api_version = get_api_version(api)
+ supported, not_supported_msg = versioned_path_info.provide_version(api_version)
+ if not supported:
+ msg = 'Path /{path} is not supported for API version {api_version}'.format(path='/'.join(path), api_version=api_version)
+ if not_supported_msg:
+ msg = '{0}: {1}'.format(msg, not_supported_msg)
+ module.fail_json(msg=msg)
+ path_info = versioned_path_info.get_data()
+
backend = get_backend(path_info)
if path_info is None or backend is None:
module.fail_json(msg='Path /{path} is not yet supported'.format(path='/'.join(path)))
diff --git a/ansible_collections/community/routeros/plugins/modules/command.py b/ansible_collections/community/routeros/plugins/modules/command.py
index 84426025c..52b916ba2 100644
--- a/ansible_collections/community/routeros/plugins/modules/command.py
+++ b/ansible_collections/community/routeros/plugins/modules/command.py
@@ -40,7 +40,7 @@ options:
description:
- List of commands to send to the remote RouterOS device over the
configured provider. The resulting output from the command
- is returned. If the I(wait_for) argument is provided, the
+ is returned. If the O(wait_for) argument is provided, the
module is not returned until the condition is satisfied or
the number of retries has expired.
required: true
@@ -57,11 +57,11 @@ options:
elements: str
match:
description:
- - The I(match) argument is used in conjunction with the
- I(wait_for) argument to specify the match policy. Valid
- values are C(all) or C(any). If the value is set to C(all)
+ - The O(match) argument is used in conjunction with the
+ O(wait_for) argument to specify the match policy. Valid
+ values are V(all) or V(any). If the value is set to V(all)
then all conditionals in the wait_for must be satisfied. If
- the value is set to C(any) then only one of the values must be
+ the value is set to V(any) then only one of the values must be
satisfied.
default: all
choices: ['any', 'all']
@@ -71,7 +71,7 @@ options:
- Specifies the number of retries a command should by tried
before it is considered failed. The command is run on the
target device every retry and evaluated against the
- I(wait_for) conditions.
+ O(wait_for) conditions.
default: 10
type: int
interval:
diff --git a/ansible_collections/community/routeros/plugins/modules/facts.py b/ansible_collections/community/routeros/plugins/modules/facts.py
index 85c0b37c4..50f9a21fc 100644
--- a/ansible_collections/community/routeros/plugins/modules/facts.py
+++ b/ansible_collections/community/routeros/plugins/modules/facts.py
@@ -31,9 +31,9 @@ options:
description:
- When supplied, this argument will restrict the facts collected
to a given subset. Possible values for this argument include
- C(all), C(hardware), C(config), C(interfaces), and C(routing).
+ V(all), V(hardware), V(config), V(interfaces), and V(routing).
- Can specify a list of values to include a larger subset.
- Values can also be used with an initial C(!) to specify that a
+ Values can also be used with an initial V(!) to specify that a
specific subset should not be collected.
required: false
default:
@@ -75,55 +75,55 @@ ansible_facts:
# default
ansible_net_model:
description: The model name returned from the device.
- returned: I(gather_subset) contains C(default)
+ returned: O(gather_subset) contains V(default)
type: str
ansible_net_serialnum:
description: The serial number of the remote device.
- returned: I(gather_subset) contains C(default)
+ returned: O(gather_subset) contains V(default)
type: str
ansible_net_version:
description: The operating system version running on the remote device.
- returned: I(gather_subset) contains C(default)
+ returned: O(gather_subset) contains V(default)
type: str
ansible_net_hostname:
description: The configured hostname of the device.
- returned: I(gather_subset) contains C(default)
+ returned: O(gather_subset) contains V(default)
type: str
ansible_net_arch:
description: The CPU architecture of the device.
- returned: I(gather_subset) contains C(default)
+ returned: O(gather_subset) contains V(default)
type: str
ansible_net_uptime:
description: The uptime of the device.
- returned: I(gather_subset) contains C(default)
+ returned: O(gather_subset) contains V(default)
type: str
ansible_net_cpu_load:
description: Current CPU load.
- returned: I(gather_subset) contains C(default)
+ returned: O(gather_subset) contains V(default)
type: str
# hardware
ansible_net_spacefree_mb:
description: The available disk space on the remote device in MiB.
- returned: I(gather_subset) contains C(hardware)
+ returned: O(gather_subset) contains V(hardware)
type: dict
ansible_net_spacetotal_mb:
description: The total disk space on the remote device in MiB.
- returned: I(gather_subset) contains C(hardware)
+ returned: O(gather_subset) contains V(hardware)
type: dict
ansible_net_memfree_mb:
description: The available free memory on the remote device in MiB.
- returned: I(gather_subset) contains C(hardware)
+ returned: O(gather_subset) contains V(hardware)
type: int
ansible_net_memtotal_mb:
description: The total memory on the remote device in MiB.
- returned: I(gather_subset) contains C(hardware)
+ returned: O(gather_subset) contains V(hardware)
type: int
# config
ansible_net_config:
description: The current active config from the device.
- returned: I(gather_subset) contains C(config)
+ returned: O(gather_subset) contains V(config)
type: str
ansible_net_config_nonverbose:
@@ -132,52 +132,52 @@ ansible_facts:
- This value is idempotent in the sense that if the facts module is run twice and the device's config
was not changed between the runs, the value is identical. This is achieved by running C(/export)
and stripping the timestamp from the comment in the first line.
- returned: I(gather_subset) contains C(config)
+ returned: O(gather_subset) contains V(config)
type: str
version_added: 1.2.0
# interfaces
ansible_net_all_ipv4_addresses:
description: All IPv4 addresses configured on the device.
- returned: I(gather_subset) contains C(interfaces)
+ returned: O(gather_subset) contains V(interfaces)
type: list
ansible_net_all_ipv6_addresses:
description: All IPv6 addresses configured on the device.
- returned: I(gather_subset) contains C(interfaces)
+ returned: O(gather_subset) contains V(interfaces)
type: list
ansible_net_interfaces:
description: A hash of all interfaces running on the system.
- returned: I(gather_subset) contains C(interfaces)
+ returned: O(gather_subset) contains V(interfaces)
type: dict
ansible_net_neighbors:
description: The list of neighbors from the remote device.
- returned: I(gather_subset) contains C(interfaces)
+ returned: O(gather_subset) contains V(interfaces)
type: dict
# routing
ansible_net_bgp_peer:
description: A dictionary with BGP peer information.
- returned: I(gather_subset) contains C(routing)
+ returned: O(gather_subset) contains V(routing)
type: dict
ansible_net_bgp_vpnv4_route:
description: A dictionary with BGP vpnv4 route information.
- returned: I(gather_subset) contains C(routing)
+ returned: O(gather_subset) contains V(routing)
type: dict
ansible_net_bgp_instance:
description: A dictionary with BGP instance information.
- returned: I(gather_subset) contains C(routing)
+ returned: O(gather_subset) contains V(routing)
type: dict
ansible_net_route:
description: A dictionary for routes in all routing tables.
- returned: I(gather_subset) contains C(routing)
+ returned: O(gather_subset) contains V(routing)
type: dict
ansible_net_ospf_instance:
description: A dictionary with OSPF instances.
- returned: I(gather_subset) contains C(routing)
+ returned: O(gather_subset) contains V(routing)
type: dict
ansible_net_ospf_neighbor:
description: A dictionary with OSPF neighbors.
- returned: I(gather_subset) contains C(routing)
+ returned: O(gather_subset) contains V(routing)
type: dict
"""
import re
@@ -311,7 +311,7 @@ class Config(FactsBase):
'/export',
]
- RM_DATE_RE = re.compile(r'^# [a-z0-9/][a-z0-9/]* [0-9:]* by RouterOS')
+ RM_DATE_RE = re.compile(r'^# [a-z0-9/-][a-z0-9/-]* [0-9:]* by RouterOS')
def populate(self):
super(Config, self).populate()