Coder Social home page Coder Social logo

ansible-collections / community.routeros Goto Github PK

View Code? Open in Web Editor NEW
94.0 12.0 43.0 4.82 MB

Ansible modules for managing MikroTik RouterOS instances.

Home Page: https://galaxy.ansible.com/ui/repo/published/community/routeros/

License: GNU General Public License v3.0

Python 100.00%
mikrotik-routeros routeros ansible-collection hacktoberfest

community.routeros's People

Contributors

adeptvin1 avatar akimrx avatar andersson007 avatar cosandr avatar dependabot[bot] avatar derdeagle avatar felixfontein avatar gundalow avatar hansmi avatar heuels avatar jadyndev avatar jplitza avatar liquorice-head avatar mpas97 avatar nikolaydachev avatar phibos avatar phox142 avatar psztoch avatar qaxi avatar renatoalmeidaoliveira avatar samburney avatar sgrimee avatar therfert avatar tim427 avatar tobsa13 avatar txt-file avatar vint2k avatar ytimenkov avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

community.routeros's Issues

cannot install community.routeros module via ansible-galaxy

SUMMARY

Can't install community.routeros module. I was install ansible via ppa.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.routeros

ANSIBLE VERSION
ansible [core 2.12.7]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/username/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/username/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.4 (main, Apr  2 2022, 09:04:19) [GCC 11.2.0]
  jinja version = 3.0.3
  libyaml = True
COLLECTION VERSION
CONFIGURATION
OS / ENVIRONMENT

Ubuntu 22.04

Distributor ID:	Ubuntu
Description:	Ubuntu 22.04 LTS
Release:	22.04
Codename:	jammy
STEPS TO REPRODUCE
ansible-galaxy collection install community.routeros -vvv
EXPECTED RESULTS

Can install that module.

ACTUAL RESULTS
Starting galaxy collection install process
Process install dependency map
ERROR! Unexpected Exception, this is probably a bug: CollectionDependencyProvider.find_matches() got an unexpected keyword argument 'identifier'
the full traceback was:

Traceback (most recent call last):
  File "/usr/bin/ansible-galaxy", line 128, in <module>
    exit_code = cli.run()
  File "/usr/lib/python3/dist-packages/ansible/cli/galaxy.py", line 569, in run
    return context.CLIARGS['func']()
  File "/usr/lib/python3/dist-packages/ansible/cli/galaxy.py", line 86, in method_wrapper
    return wrapped_method(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/ansible/cli/galaxy.py", line 1203, in execute_install
    self._execute_install_collection(
  File "/usr/lib/python3/dist-packages/ansible/cli/galaxy.py", line 1230, in _execute_install_collection
    install_collections(
  File "/usr/lib/python3/dist-packages/ansible/galaxy/collection/__init__.py", line 548, in install_collections
    dependency_map = _resolve_depenency_map(
  File "/usr/lib/python3/dist-packages/ansible/galaxy/collection/__init__.py", line 1364, in _resolve_depenency_map
    return collection_dep_resolver.resolve(
  File "/usr/lib/python3/dist-packages/resolvelib/resolvers.py", line 481, in resolve
    state = resolution.resolve(requirements, max_rounds=max_rounds)
  File "/usr/lib/python3/dist-packages/resolvelib/resolvers.py", line 348, in resolve
    self._add_to_criteria(self.state.criteria, r, parent=None)
  File "/usr/lib/python3/dist-packages/resolvelib/resolvers.py", line 147, in _add_to_criteria
    matches = self._p.find_matches(
TypeError: CollectionDependencyProvider.find_matches() got an unexpected keyword argument 'identifier'

Important information for collection maintainers

SUMMARY

Dear maintainers,

This is important for your collections!

  • In accordance with the Community decision, we have created the news-for-maintainers repository for announcements of changes impacting collection maintainers (see the examples) instead of Issue 45 that will be closed soon.

    • To keep yourself well-informed and, therefore, things in your collection working, please subscribe to the repository by using the Watch button in the upper right corner on the repository's home page.
    • If you do not want to get notifications about related discussions, please subscribe only to Issues.
    • Please read the brief guidelines on how the repository should be used.
    • Please avoid unnecessary discussions in issues, use the Discussions feature. Every comment posted will notify a lot of folks!
  • Also we would like to remind you about the Bullhorn contributor newsletter which has recently started to be released weekly. To learn what it looks like, see the past releases. Please subscribe and talk to the Community via Bullhorn!

  • Join us in #ansible-social (for news reporting & chat), #ansible-community (for discussing collection & maintainer topics), and other channels on Matrix/IRC.

  • Help the Community and the Steering Committee to make right decisions by taking part in discussing and voting on the Community Topics that impact the whole project and the collections in particular. Your opinion there will be much appreciated!

Thank you!

facts subset config is allways "changed"

SUMMARY

Every time 'community.routeros.facts' subset 'config' returns data it's status is 'not changed' but it is false.
Returned data are different on every run of 'community.routeros.facts' even configuration on device is not changed:

  1. there is date at the beggining of the file
  2. with "/export verbose" there are exported unconfigured services too and for example unconfigured '/interface ovpn-server server' contains random generated MAC address (tested on RouterBOARD 750G r3)
ISSUE TYPE
  • Bug Report
COMPONENT NAME

'community.routeros.facts' subset 'config'

ANSIBLE VERSION

CONFIGURATION
# ansible --version
ansible 2.10.6
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.8/dist-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.8.5 (default, Jul 28 2020, 12:59:40) [GCC 9.3.0]
OS / ENVIRONMENT

Ubuntu 20.04
RouterBOARD 750G r3
RouterOS 6.40.3

STEPS TO REPRODUCE

setup your inventory to an Mikrotik device (tested on RouterBOARD 750G r3)

---
- name: Mikrotik config1
  community.routeros.facts:
    gather_subset: config

- set_fact: cfg1="{{ ansible_net_config }}" 
- set_fact: cfg3="{{ ansible_net_config }}" 

- name: Mikrotik config2
  community.routeros.facts:
    gather_subset: config

- set_fact: cfg2="{{ ansible_net_config }}" 

- ansible.builtin.debug: 
    msg: "cfg1 is different from cfg2"
  when: cfg1 != cfg2

- ansible.builtin.debug: 
    msg: "cfg1 is not different from cfg1"
  when: cfg1 == cfg1

- ansible.builtin.debug: 
    msg: "cfg1 is not different from cfg3"
  when: cfg1 == cfg3
EXPECTED RESULTS

cfg1 should be the same cfg2 because device configuration did not changed

ACTUAL RESULTS

cfg1 and cfg2 are different.
it makes very difficult to version those cfg files

Error when starting routeros_facts and routeros_commands modules

SUMMARY

Hello, when starting playbook with the module routeros_facts.py for older Mikrotik devices, I get the error described below. After studying the experience of previous colleagues, I changed the response time to 2 minutes in network_cli, unfortunately this did not have the desired effect. I also tried using the prefix "+cet1024w", but it didn't work. I thought that the problem is in the old version of ROS v6. 41 <, but updating to ROS 6.45.9 did not solve the problem, and that is typical RB3011 works calmly. And on the old 951, but updated Mikrotik problems.

ISSUE TYPE
  • Bug Report
    ifilyanin@mikrotik-awx:~/multivendor_module_ansible$ ansible-playbook show_version_command.yml -i inventory_retn_mikrotik -vvvv -u duty+e -k -c network_cli -e ansible_network_os=routeros --check
    [WARNING]: log file at /var/log/ansible.log is not writeable and we cannot create it, aborting

ansible-playbook 2.9.0
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/ifilyanin/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/ifilyanin/.local/lib/python3.7/site-packages/ansible
executable location = /home/ifilyanin/.local/bin/ansible-playbook
python version = 3.7.3 (default, Jul 25 2020, 13:03:44) [GCC 8.3.0]
Using /etc/ansible/ansible.cfg as config file
SSH password:
setting up inventory plugins
host_list declined parsing /home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik as it did not pass its verify_file() method
script declined parsing /home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik as it did not pass its verify_file() method
auto declined parsing /home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik as it did not pass its verify_file() method
Not replacing invalid character(s) "{'-'}" in group name (CE-904044-2)
[DEPRECATION WARNING]: The TRANSFORM_INVALID_GROUP_CHARS settings is set to
allow bad characters in group names by default, this will change, but still be
user configurable on deprecation. This feature will be removed in version 2.10.
Deprecation warnings can be disabled by setting deprecation_warnings=False in
ansible.cfg.
[WARNING]: Invalid characters were found in group names but not replaced, use
-vvvv to see details

Not replacing invalid character(s) "{'-'}" in group name (CE-904044-2)
toml declined parsing /home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik as it did not pass its verify_file() method
[WARNING]: * Failed to parse
/home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik with yaml
plugin: Syntax Error while loading YAML. did not find expected The error appears to be in
'/home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik': line 2,
column 1, but may be elsewhere in the file depending on the exact syntax
problem. The offending line appears to be: [CE-904044-2] 172.21.250.26 ^ here

File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/inventory/manager.py", line 280, in parse_source
plugin.parse(self._inventory, self._loader, source, cache=cache)
File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/inventory/yaml.py", line 105, in parse
raise AnsibleParserError(e)

[WARNING]: * Failed to parse
/home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik with ini
plugin: /home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik:3:
Expected key=value host variable assignment, got: routeros

File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/inventory/manager.py", line 280, in parse_source
plugin.parse(self._inventory, self._loader, source, cache=cache)
File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/inventory/ini.py", line 138, in parse
raise AnsibleParserError(e)

[WARNING]: Unable to parse
/home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik as an
inventory source

[WARNING]: No inventory was parsed, only implicit localhost is available

[WARNING]: provided hosts list is empty, only localhost is available. Note that
the implicit localhost does not match 'all'

Loading callback plugin default of type stdout, v2.0 from /home/ifilyanin/.local /lib/python3.7/site-packages/ansible/plugins/callback/default.py

PLAYBOOK: show_version_command.yml *********************************************
Positional arguments: show_version_command.yml
verbosity: 4
ask_pass: True
remote_user: duty+e
connection: network_cli
timeout: 10
become_method: sudo
tags: ('all',)
check: True
inventory: ('/home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik' ,)
extra_vars: ('ansible_network_os=routeros',)
forks: 5
1 plays in show_version_command.yml

PLAY [show facts] **************************************************************
META: ran handlers

TASK [show facts] **************************************************************
task path: /home/ifilyanin/multivendor_module_ansible/show_version_command.yml:8
<172.21.250.26> attempting to start connection
<172.21.250.26> using connection plugin network_cli
<172.21.250.26> local domain socket does not exist, starting it
<172.21.250.26> control socket path is /home/ifilyanin/.ansible/pc/a591f9c842
<172.21.250.26> local domain socket listeners started successfully
<172.21.250.26> loaded cliconf plugin for network_os routeros
<172.21.250.26>
<172.21.250.26> local domain socket path is /home/ifilyanin/.ansible/pc/a591f9c8 42
<172.21.250.26> ESTABLISH LOCAL CONNECTION FOR USER: ifilyanin
<172.21.250.26> EXEC /bin/sh -c '( umask 77 && mkdir -p "echo /home/ifilyanin/ .ansible/tmp/ansible-local-201222_rdlrhxs/ansible-tmp-1597735993.0080414-1844593 85328040" && echo ansible-tmp-1597735993.0080414-184459385328040="echo /home /ifilyanin/.ansible/tmp/ansible-local-201222_rdlrhxs/ansible-tmp-1597735993.0080 414-184459385328040" ) && sleep 0'
<172.21.250.26> Attempting python interpreter discovery
<172.21.250.26> EXEC /bin/sh -c 'echo PLATFORM; uname; echo FOUND; command -v '" '"'/usr/bin/python'"'"'; command -v '"'"'python3.7'"'"'; command -v '"'"'python3 .6'"'"'; command -v '"'"'python3.5'"'"'; command -v '"'"'python2.7'"'"'; command -v '"'"'python2.6'"'"'; command -v '"'"'/usr/libexec/platform-python'"'"'; comm and -v '"'"'/usr/bin/python3'"'"'; command -v '"'"'python'"'"'; echo ENDFOUND && sleep 0'
<172.21.250.26> EXEC /bin/sh -c '/usr/bin/python && sleep 0'
<172.21.250.26> Python interpreter discovery fallback (unsupported Linux distrib ution: debian)
Using module file /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/mod ules/network/routeros/routeros_command.py
<172.21.250.26> PUT /home/ifilyanin/.ansible/tmp/ansible-local-201222_rdlrhxs/tm p1kwdc7f1 TO /home/ifilyanin/.ansible/tmp/ansible-local-201222_rdlrhxs/ansible-t mp-1597735993.0080414-184459385328040/AnsiballZ_routeros_command.py
<172.21.250.26> EXEC /bin/sh -c 'chmod u+x /home/ifilyanin/.ansible/tmp/ansible- local-201222_rdlrhxs/ansible-tmp-1597735993.0080414-184459385328040/ /home/ifily anin/.ansible/tmp/ansible-local-201222_rdlrhxs/ansible-tmp-1597735993.0080414-18 4459385328040/AnsiballZ_routeros_command.py && sleep 0'
<172.21.250.26> EXEC /bin/sh -c '/usr/bin/python /home/ifilyanin/.ansible/tmp/an sible-local-201222_rdlrhxs/ansible-tmp-1597735993.0080414-184459385328040/Ansiba llZ_routeros_command.py && sleep 0'
<172.21.250.26> EXEC /bin/sh -c 'rm -f -r /home/ifilyanin/.ansible/tmp/ansible-l ocal-201222_rdlrhxs/ansible-tmp-1597735993.0080414-184459385328040/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
File "/home/ifilyanin/.ansible/tmp/ansible-local-201222_rdlrhxs/ansible-tmp-15 97735993.0080414-184459385328040/AnsiballZ_routeros_command.py", line 102, in
_ansiballz_main()
File "/home/ifilyanin/.ansible/tmp/ansible-local-201222_rdlrhxs/ansible-tmp-15 97735993.0080414-184459385328040/AnsiballZ_routeros_command.py", line 94, in _an siballz_main
invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
File "/home/ifilyanin/.ansible/tmp/ansible-local-201222_rdlrhxs/ansible-tmp-15 97735993.0080414-184459385328040/AnsiballZ_routeros_command.py", line 40, in inv oke_module
runpy.run_module(mod_name='ansible.modules.network.routeros.routeros_command ', init_globals=None, run_name='main', alter_sys=False)
File "/usr/lib/python2.7/runpy.py", line 192, in run_module
fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/tmp/ansible_routeros_command_payload__HFS1L/ansible_routeros_command_pa yload.zip/ansible/modules/network/routeros/routeros_command.py", line 187, in
File "/tmp/ansible_routeros_command_payload__HFS1L/ansible_routeros_command_pa yload.zip/ansible/modules/network/routeros/routeros_command.py", line 157, in ma in
File "/tmp/ansible_routeros_command_payload__HFS1L/ansible_routeros_command_pa yload.zip/ansible/module_utils/network/routeros/routeros.py", line 125, in run_c ommands
File "/tmp/ansible_routeros_command_payload__HFS1L/ansible_routeros_command_pa yload.zip/ansible/module_utils/network/routeros/routeros.py", line 55, in get_co nnection
File "/tmp/ansible_routeros_command_payload__HFS1L/ansible_routeros_command_pa yload.zip/ansible/module_utils/network/routeros/routeros.py", line 69, in get_ca pabilities
File "/tmp/ansible_routeros_command_payload__HFS1L/ansible_routeros_command_pa yload.zip/ansible/module_utils/connection.py", line 185, in rpc
ansible.module_utils.connection.ConnectionError: timeout value 30 seconds reache d while trying to send command: b'/system resource print'

[WARNING]: Platform linux on host 172.21.250.26 is using the discovered Python
interpreter at /usr/bin/python, but future installation of another Python
interpreter could change this. See https://docs.ansible.com/ansible/2.9/referen
ce_appendices/interpreter_discovery.html for more information.

fatal: [172.21.250.26]: FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"module_stderr": "Traceback (most recent call last):\n File "/home/ifilyan in/.ansible/tmp/ansible-local-201222_rdlrhxs/ansible-tmp-1597735993.0080414-1844 59385328040/AnsiballZ_routeros_command.py", line 102, in \n _ansibal lz_main()\n File "/home/ifilyanin/.ansible/tmp/ansible-local-201222_rdlrhxs/an sible-tmp-1597735993.0080414-184459385328040/AnsiballZ_routeros_command.py", li ne 94, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PA RAMS)\n File "/home/ifilyanin/.ansible/tmp/ansible-local-201222_rdlrhxs/ansibl e-tmp-1597735993.0080414-184459385328040/AnsiballZ_routeros_command.py", line 4 0, in invoke_module\n runpy.run_module(mod_name='ansible.modules.network.rout eros.routeros_command', init_globals=None, run_name='main', alter_sys=False) \n File "/usr/lib/python2.7/runpy.py", line 192, in run_module\n fname, lo ader, pkg_name)\n File "/usr/lib/python2.7/runpy.py", line 72, in _run_code\n exec code in run_globals\n File "/tmp/ansible_routeros_command_payload__HF S1L/ansible_routeros_command_payload.zip/ansible/modules/network/routeros/router os_command.py", line 187, in \n File "/tmp/ansible_routeros_command_p ayload__HFS1L/ansible_routeros_command_payload.zip/ansible/modules/network/route ros/routeros_command.py", line 157, in main\n File "/tmp/ansible_routeros_com mand_payload__HFS1L/ansible_routeros_command_payload.zip/ansible/module_utils/ne twork/routeros/routeros.py", line 125, in run_commands\n File "/tmp/ansible_r outeros_command_payload__HFS1L/ansible_routeros_command_payload.zip/ansible/modu le_utils/network/routeros/routeros.py", line 55, in get_connection\n File "/t mp/ansible_routeros_command_payload__HFS1L/ansible_routeros_command_payload.zip/ ansible/module_utils/network/routeros/routeros.py", line 69, in get_capabilitie s\n File "/tmp/ansible_routeros_command_payload__HFS1L/ansible_routeros_comman d_payload.zip/ansible/module_utils/connection.py", line 185, in rpc\nansibl e.module_utils.connection.ConnectionError: timeout value 30 seconds reached whil e trying to send command: b'/system resource print'\n",
"module_stdout": "",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}
...ignoring
META: ran handlers
META: ran handlers

PLAY RECAP *********************************************************************
172.21.250.26 : ok=1 changed=0 unreachable=0 failed=0 s kipped=0 rescued=0 ignored=1

2020-08-16 15:17:16,553 p=ifilyanin u=156254 | ansible-playbook 2.9.0
config file = /etc/ansible/ansible.cfg
configured module search path = ['/home/ifilyanin/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /home/ifilyanin/.local/lib/python3.7/site-packages/ansible
executable location = /home/ifilyanin/.local/bin/ansible-playbook
python version = 3.7.3 (default, Jul 25 2020, 13:03:44) [GCC 8.3.0]
2020-08-16 15:17:16,553 p=ifilyanin u=156254 | Using /etc/ansible/ansible.cfg as config file
2020-08-16 15:17:21,583 p=ifilyanin u=156254 | setting up inventory plugins
2020-08-16 15:17:21,592 p=ifilyanin u=156254 | host_list declined parsing /home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik as it did not pass its verify_file() method
2020-08-16 15:17:21,592 p=ifilyanin u=156254 | script declined parsing /home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik as it did not pass its verify_file() method
2020-08-16 15:17:21,592 p=ifilyanin u=156254 | auto declined parsing /home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik as it did not pass its verify_file() method
2020-08-16 15:17:21,598 p=ifilyanin u=156254 | Not replacing invalid character(s) "{'-'}" in group name (CE-904044-2)
2020-08-16 15:17:21,598 p=ifilyanin u=156254 | [DEPRECATION WARNING]: The TRANSFORM_INVALID_GROUP_CHARS settings is set to allow bad characters in group names by default, this will change, but still be user configurable on
deprecation. This feature will be removed in version 2.10. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
2020-08-16 15:17:21,598 p=ifilyanin u=156254 | [WARNING]: Invalid characters were found in group names but not replaced, use -vvvv to see details

2020-08-16 15:17:21,599 p=ifilyanin u=156254 | Not replacing invalid character(s) "{'-'}" in group name (CE-904044-2)
2020-08-16 15:17:21,600 p=ifilyanin u=156254 | toml declined parsing /home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik as it did not pass its verify_file() method
2020-08-16 15:17:21,601 p=ifilyanin u=156254 | [WARNING]: * Failed to parse /home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik with yaml plugin: Syntax Error while loading YAML. did not find expected
The error appears to be in '/home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik': line 2, column 1, but may be elsewhere in the file depending
on the exact syntax problem. The offending line appears to be: [CE-904044-2] 172.21.250.26 ^ here

2020-08-16 15:17:21,601 p=ifilyanin u=156254 | File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/inventory/manager.py", line 280, in parse_source
plugin.parse(self._inventory, self._loader, source, cache=cache)
File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/inventory/yaml.py", line 105, in parse
raise AnsibleParserError(e)

2020-08-16 15:17:21,601 p=ifilyanin u=156254 | [WARNING]: * Failed to parse /home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik with ini plugin:
/home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik:3: Expected key=value host variable assignment, got: routeros

2020-08-16 15:17:21,601 p=ifilyanin u=156254 | File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/inventory/manager.py", line 280, in parse_source
plugin.parse(self._inventory, self._loader, source, cache=cache)
File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/inventory/ini.py", line 138, in parse
raise AnsibleParserError(e)

2020-08-16 15:17:21,602 p=ifilyanin u=156254 | [WARNING]: Unable to parse /home/ifilyanin/multivendor_module_ansible/inventory_retn_mikrotik as an inventory source

2020-08-16 15:17:21,602 p=ifilyanin u=156254 | [WARNING]: No inventory was parsed, only implicit localhost is available

2020-08-16 15:17:21,602 p=ifilyanin u=156254 | [WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'

2020-08-16 15:17:21,865 p=ifilyanin u=156254 | Loading callback plugin default of type stdout, v2.0 from /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/callback/default.py
2020-08-16 15:17:21,926 p=ifilyanin u=156254 | PLAYBOOK: show_version_command.yml **********************************************************************************************************************************************
2020-08-16 15:17:21,927 p=ifilyanin u=156254 | 1 plays in show_version_command.yml
2020-08-16 15:17:21,931 p=ifilyanin u=156254 | PLAY [show facts] ***************************************************************************************************************************************************************
2020-08-16 15:17:21,943 p=ifilyanin u=156254 | META: ran handlers
2020-08-16 15:17:21,953 p=ifilyanin u=156254 | TASK [show facts] ***************************************************************************************************************************************************************
2020-08-16 15:17:21,972 p=ifilyanin u=156260 | <172.21.250.26> attempting to start connection
2020-08-16 15:17:21,973 p=ifilyanin u=156260 | <172.21.250.26> using connection plugin network_cli
2020-08-16 15:17:22,359 p=ifilyanin u=156260 | <172.21.250.26> local domain socket does not exist, starting it
2020-08-16 15:17:22,360 p=ifilyanin u=156260 | <172.21.250.26> control socket path is /home/ifilyanin/.ansible/pc/9697c92b53
2020-08-16 15:17:22,360 p=ifilyanin u=156260 | <172.21.250.26> 156261 1597580242.27891: trying /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/pycache
2020-08-16 15:17:22,360 p=ifilyanin u=156260 | <172.21.250.26> 156261 1597580242.27920: trying /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection
2020-08-16 15:17:22,360 p=ifilyanin u=156260 | <172.21.250.26> 156261 1597580242.28906: Loaded config def from plugin (connection/ssh)
2020-08-16 15:17:22,360 p=ifilyanin u=156260 | <172.21.250.26> 156261 1597580242.28913: Loading Connection 'ssh' from /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/ssh.py (searched paths: /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection:/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/pycache) (found_in_cache=False, class_only=True)
2020-08-16 15:17:22,360 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.30196: Loaded config def from plugin (connection/network_cli)
2020-08-16 15:17:22,361 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.30214: Loading Connection 'network_cli' from /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/network_cli.py (searched paths: /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection:/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/pycache)
2020-08-16 15:17:22,361 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.30266: trying /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/shell
2020-08-16 15:17:22,361 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.30404: trying /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/doc_fragments
2020-08-16 15:17:22,361 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.30580: Loading ModuleDocFragment 'shell_common' from /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/doc_fragments/shell_common.py
2020-08-16 15:17:22,361 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.30685: Loaded config def from plugin (shell/sh)
2020-08-16 15:17:22,361 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.30691: Loading ShellModule 'sh' from /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/shell/sh.py
2020-08-16 15:17:22,361 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.30697: Loading ShellModule 'sh' from /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/shell/sh.py (found_in_cache=True, class_only=False)
2020-08-16 15:17:22,361 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.30752: Loading Connection 'local' from /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/local.py (searched paths: /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection:/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/pycache)
2020-08-16 15:17:22,361 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.30767: Loading ShellModule 'sh' from /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/shell/sh.py (found_in_cache=True, class_only=False)
2020-08-16 15:17:22,362 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.30771: Loading ShellModule 'sh' from /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/shell/sh.py (found_in_cache=True, class_only=False)
2020-08-16 15:17:22,362 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.30787: Loading Connection 'ssh' from /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/ssh.py (searched paths: /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection:/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/pycache) (found_in_cache=True, class_only=True)
2020-08-16 15:17:22,362 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.31028: trying /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/terminal/pycache
2020-08-16 15:17:22,362 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.31062: trying /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/terminal
2020-08-16 15:17:22,362 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.31219: Loading TerminalModule 'routeros' from /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/terminal/routeros.py (searched paths: /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/terminal:/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/terminal/pycache)
2020-08-16 15:17:22,362 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.31412: trying /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/cliconf/pycache
2020-08-16 15:17:22,362 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.31444: trying /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/cliconf
2020-08-16 15:17:22,362 p=ifilyanin u=156260 | <172.21.250.26> 156265 1597580242.31523: Loading Cliconf 'routeros' from /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/cliconf/routeros.py (searched paths: /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/cliconf:/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/cliconf/pycache)
2020-08-16 15:17:22,362 p=ifilyanin u=156260 | <172.21.250.26> local domain socket listeners started successfully
2020-08-16 15:17:22,363 p=ifilyanin u=156260 | <172.21.250.26> loaded cliconf plugin for network_os routeros
2020-08-16 15:17:22,363 p=ifilyanin u=156260 | network_os is set to routeros
2020-08-16 15:17:22,363 p=ifilyanin u=156260 | <172.21.250.26> 156261 1597580242.27891: trying /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/pycache
156261 1597580242.27920: trying /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection
156261 1597580242.28906: Loaded config def from plugin (connection/ssh)
156261 1597580242.28913: Loading Connection 'ssh' from /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/ssh.py (searched paths: /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection:/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/pycache) (found_in_cache=False, class_only=True)

2020-08-16 15:17:22,363 p=ifilyanin u=156260 | <172.21.250.26> local domain socket path is /home/ifilyanin/.ansible/pc/9697c92b53
2020-08-16 15:17:22,365 p=ifilyanin u=156260 | <172.21.250.26> ESTABLISH LOCAL CONNECTION FOR USER: ifilyanin
2020-08-16 15:17:22,366 p=ifilyanin u=156260 | <172.21.250.26> EXEC /bin/sh -c '( umask 77 && mkdir -p "echo /home/ifilyanin/.ansible/tmp/ansible-local-156254na3tocp4/ansible-tmp-1597580242.3654187-206418296162592" && echo ansible-tmp-1597580242.3654187-206418296162592="echo /home/ifilyanin/.ansible/tmp/ansible-local-156254na3tocp4/ansible-tmp-1597580242.3654187-206418296162592" ) && sleep 0'
2020-08-16 15:17:22,545 p=ifilyanin u=156260 | <172.21.250.26> Attempting python interpreter discovery
2020-08-16 15:17:22,546 p=ifilyanin u=156260 | <172.21.250.26> EXEC /bin/sh -c 'echo PLATFORM; uname; echo FOUND; command -v '"'"'/usr/bin/python'"'"'; command -v '"'"'python3.7'"'"'; command -v '"'"'python3.6'"'"'; command -v '"'"'python3.5'"'"'; command -v '"'"'python2.7'"'"'; command -v '"'"'python2.6'"'"'; command -v '"'"'/usr/libexec/platform-python'"'"'; command -v '"'"'/usr/bin/python3'"'"'; command -v '"'"'python'"'"'; echo ENDFOUND && sleep 0'
2020-08-16 15:17:22,556 p=ifilyanin u=156260 | <172.21.250.26> EXEC /bin/sh -c '/usr/bin/python && sleep 0'
2020-08-16 15:17:22,579 p=ifilyanin u=156260 | <172.21.250.26> Python interpreter discovery fallback (unsupported Linux distribution: debian)
2020-08-16 15:17:22,581 p=ifilyanin u=156260 | Using module file /home/ifilyanin/.local/lib/python3.7/site-packages/ansible/modules/network/routeros/routeros_command.py
2020-08-16 15:17:22,582 p=ifilyanin u=156260 | <172.21.250.26> PUT /home/ifilyanin/.ansible/tmp/ansible-local-156254na3tocp4/tmpdjarrryp TO /home/ifilyanin/.ansible/tmp/ansible-local-156254na3tocp4/ansible-tmp-1597580242.3654187-206418296162592/AnsiballZ_routeros_command.py
2020-08-16 15:17:22,583 p=ifilyanin u=156260 | <172.21.250.26> EXEC /bin/sh -c 'chmod u+x /home/ifilyanin/.ansible/tmp/ansible-local-156254na3tocp4/ansible-tmp-1597580242.3654187-206418296162592/ /home/ifilyanin/.ansible/tmp/ansible-local-156254na3tocp4/ansible-tmp-1597580242.3654187-206418296162592/AnsiballZ_routeros_command.py && sleep 0'
2020-08-16 15:17:22,589 p=ifilyanin u=156260 | <172.21.250.26> EXEC /bin/sh -c '/usr/bin/python /home/ifilyanin/.ansible/tmp/ansible-local-156254na3tocp4/ansible-tmp-1597580242.3654187-206418296162592/AnsiballZ_routeros_command.py && sleep 0'
2020-08-16 15:17:22,709 p=ifilyanin u=156265 | <172.21.250.26> ESTABLISH PARAMIKO SSH CONNECTION FOR USER: duty+e on PORT 22 TO 172.21.250.26
2020-08-16 15:18:03,503 p=ifilyanin u=156265 | Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/paramiko/channel.py", line 699, in recv
out = self.in_buffer.read(nbytes, self.timeout)
File "/usr/lib/python3/dist-packages/paramiko/buffered_pipe.py", line 164, in read
raise PipeTimeout()
paramiko.buffered_pipe.PipeTimeout

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/network_cli.py", line 579, in send
response = self.receive(command, prompt, answer, newline, prompt_retry_check, check_all)
File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/network_cli.py", line 528, in receive
data = self._ssh_shell.recv(256)
File "/usr/lib/python3/dist-packages/paramiko/channel.py", line 701, in recv
raise socket.timeout()
socket.timeout
During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/utils/jsonrpc.py", line 45, in handle_request
result = rpc_method(*args, **kwargs)
File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/cliconf/routeros.py", line 78, in get_capabilities
result = super(Cliconf, self).get_capabilities()
File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/cliconf/init.py", line 283, in get_capabilities
result['device_info'] = self.get_device_info()
File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/cliconf/routeros.py", line 48, in get_device_info
resource = self.get('/system resource print')
File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/cliconf/routeros.py", line 75, in get
return self.send_command(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline, check_all=check_all)
File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/cliconf/init.py", line 127, in send_command
resp = self._connection.send(**kwargs)
File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/init.py", line 35, in wrapped
return func(self, *args, **kwargs)
File "/home/ifilyanin/.local/lib/python3.7/site-packages/ansible/plugins/connection/network_cli.py", line 584, in send
% (self._ssh_shell.gettimeout(), command.strip()))
ansible.errors.AnsibleConnectionFailure: timeout value 30 seconds reached while trying to send command: b'/system resource print'

2020-08-16 15:18:03,517 p=ifilyanin u=156260 | <172.21.250.26> EXEC /bin/sh -c 'rm -f -r /home/ifilyanin/.ansible/tmp/ansible-local-156254na3tocp4/ansible-tmp-1597580242.3654187-206418296162592/ > /dev/null 2>&1 && sleep 0'
2020-08-16 15:18:03,527 p=ifilyanin u=156254 | The full traceback is:
Traceback (most recent call last):
File "/home/ifilyanin/.ansible/tmp/ansible-local-156254na3tocp4/ansible-tmp-1597580242.3654187-206418296162592/AnsiballZ_routeros_command.py", line 102, in
_ansiballz_main()
File "/home/ifilyanin/.ansible/tmp/ansible-local-156254na3tocp4/ansible-tmp-1597580242.3654187-206418296162592/AnsiballZ_routeros_command.py", line 94, in _ansiballz_main
invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
File "/home/ifilyanin/.ansible/tmp/ansible-local-156254na3tocp4/ansible-tmp-1597580242.3654187-206418296162592/AnsiballZ_routeros_command.py", line 40, in invoke_module
runpy.run_module(mod_name='ansible.modules.network.routeros.routeros_command', init_globals=None, run_name='main', alter_sys=False)
File "/usr/lib/python2.7/runpy.py", line 192, in run_module
fname, loader, pkg_name)
File "/usr/lib/python2.7/runpy.py", line 72, in _run_code
exec code in run_globals
File "/tmp/ansible_routeros_command_payload_35_ouf/ansible_routeros_command_payload.zip/ansible/modules/network/routeros/routeros_command.py", line 187, in
File "/tmp/ansible_routeros_command_payload_35_ouf/ansible_routeros_command_payload.zip/ansible/modules/network/routeros/routeros_command.py", line 157, in main
File "/tmp/ansible_routeros_command_payload_35_ouf/ansible_routeros_command_payload.zip/ansible/module_utils/network/routeros/routeros.py", line 125, in run_commands
File "/tmp/ansible_routeros_command_payload_35_ouf/ansible_routeros_command_payload.zip/ansible/module_utils/network/routeros/routeros.py", line 55, in get_connection
File "/tmp/ansible_routeros_command_payload_35_ouf/ansible_routeros_command_payload.zip/ansible/module_utils/network/routeros/routeros.py", line 69, in get_capabilities
File "/tmp/ansible_routeros_command_payload_35_ouf/ansible_routeros_command_payload.zip/ansible/module_utils/connection.py", line 185, in rpc
ansible.module_utils.connection.ConnectionError: timeout value 30 seconds reached while trying to send command: b'/system resource print'

2020-08-16 15:18:03,528 p=ifilyanin u=156254 | [WARNING]: Platform linux on host 172.21.250.26 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could
change this. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information.

2020-08-16 15:18:03,528 p=ifilyanin u=156254 | fatal: [172.21.250.26]: FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"module_stderr": "Traceback (most recent call last):\n File "/home/ifilyanin/.ansible/tmp/ansible-local-156254na3tocp4/ansible-tmp-1597580242.3654187-206418296162592/AnsiballZ_routeros_command.py", line 102, in \n _ansiballz_main()\n File "/home/ifilyanin/.ansible/tmp/ansible-local-156254na3tocp4/ansible-tmp-1597580242.3654187-206418296162592/AnsiballZ_routeros_command.py", line 94, in _ansiballz_main\n invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n File "/home/ifilyanin/.ansible/tmp/ansible-local-156254na3tocp4/ansible-tmp-1597580242.3654187-206418296162592/AnsiballZ_routeros_command.py", line 40, in invoke_module\n runpy.run_module(mod_name='ansible.modules.network.routeros.routeros_command', init_globals=None, run_name='main', alter_sys=False)\n File "/usr/lib/python2.7/runpy.py", line 192, in run_module\n fname, loader, pkg_name)\n File "/usr/lib/python2.7/runpy.py", line 72, in _run_code\n exec code in run_globals\n File "/tmp/ansible_routeros_command_payload_35_ouf/ansible_routeros_command_payload.zip/ansible/modules/network/routeros/routeros_command.py", line 187, in \n File "/tmp/ansible_routeros_command_payload_35_ouf/ansible_routeros_command_payload.zip/ansible/modules/network/routeros/routeros_command.py", line 157, in main\n File "/tmp/ansible_routeros_command_payload_35_ouf/ansible_routeros_command_payload.zip/ansible/module_utils/network/routeros/routeros.py", line 125, in run_commands\n File "/tmp/ansible_routeros_command_payload_35_ouf/ansible_routeros_command_payload.zip/ansible/module_utils/network/routeros/routeros.py", line 55, in get_connection\n File "/tmp/ansible_routeros_command_payload_35_ouf/ansible_routeros_command_payload.zip/ansible/module_utils/network/routeros/routeros.py", line 69, in get_capabilities\n File "/tmp/ansible_routeros_command_payload_35_ouf/ansible_routeros_command_payload.zip/ansible/module_utils/connection.py", line 185, in rpc\nansible.module_utils.connection.ConnectionError: timeout value 30 seconds reached while trying to send command: b'/system resource print'\n",
"module_stdout": "",
"msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
"rc": 1
}
2020-08-16 15:18:03,528 p=ifilyanin u=156254 | ...ignoring
2020-08-16 15:18:03,530 p=ifilyanin u=156254 | META: ran handlers
2020-08-16 15:18:03,531 p=ifilyanin u=156254 | META: ran handlers
2020-08-16 15:18:03,534 p=ifilyanin u=156254 | PLAY RECAP **********************************************************************************************************************************************************************
2020-08-16 15:18:03,534 p=ifilyanin u=156254 | 172.21.250.26 : ok=1 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=1
2020-08-16 15:18:03,634 p=ifilyanin u=156265 | shutdown complete

COMPONENT NAME

routeros_facts.py, routeros_command.py

ANSIBLE VERSION
ansible --version
[WARNING]: log file at /var/log/ansible.log is not writeable and we cannot create it, aborting

ansible 2.9.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/ifilyanin/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/ifilyanin/.local/lib/python3.7/site-packages/ansible
  executable location = /home/ifilyanin/.local/bin/ansible
  python version = 3.7.3 (default, Jul 25 2020, 13:03:44) [GCC 8.3.0]


CONFIGURATION
 ansible-config dump --only-changed
[WARNING]: log file at /var/log/ansible.log is not writeable and we cannot create it, aborting

DEFAULT_LOG_PATH(/etc/ansible/ansible.cfg) = /var/log/ansible.log

OS / ENVIRONMENT

Debian 10

STEPS TO REPRODUCE
EXPECTED RESULTS
ACTUAL RESULTS
- name: show facts
  hosts: "{{ hosts }}"
  gather_facts: false
  ignore_errors: true
  tasks:

    - name: show facts
      routeros_facts:
        gather_subset: "{{ gather_facts }}"


- name: show facts
  hosts: CE-904044-2
  gather_facts: false
  ignore_errors: true
  tasks:

    - name: show facts
      routeros_command:
        commands: /export

can't change value of nat using api_find_and_modify

SUMMARY

when try to use api_find_and_modify can't get what i want by find based on input then change the value and i get the result ok (success) when remove require_matches_min: 1 but there is no change of values: so try to change it to get what i want but no luck

failed: [any -> localhost] (item=[443, 'hello.com']) => {
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "allow_no_matches": false,
            "ca_path": "keys/trust.test.ca.crt",
            "encoding": "ASCII",
            "find": {
                "action": "masquerade",
                "chain": "srcnat",
                "disabled": "yes",
                "dst-address-list": "hello.com",
                "dst-port": "443",
                "protocol": "tcp",
                "src-address": "192.168.14.16"
            },
            "force_no_cert": false,
            "hostname": "gpsm.test",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "path": "ip firewall nat",
            "port": null,
            "require_matches_max": null,
            "require_matches_min": 1,
            "timeout": 10,
            "tls": false,
            "username": "admin",
            "validate_cert_hostname": false,
            "validate_certs": true,
            "values": {
                "disabled": "no"
            }
        }
    },
    "item": [
        443,
        "hello.com"
    ],
    "msg": "Found no entries, but allow_no_matches=false"
}
failed: [any -> localhost] (item=[80, 'hello.com']) => {
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "allow_no_matches": false,
            "ca_path": "keys/trust.test.ca.crt",
            "encoding": "ASCII",
            "find": {
                "action": "masquerade",
                "chain": "srcnat",
                "disabled": "yes",
                "dst-address-list": "hello.com",
                "dst-port": "80",
                "protocol": "tcp",
                "src-address": "192.168.14.16"
            },
            "force_no_cert": false,
            "hostname": "gpsm.test",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "path": "ip firewall nat",
            "port": null,
            "require_matches_max": null,
            "require_matches_min": 1,
            "timeout": 10,
            "tls": false,
            "username": "admin",
            "validate_cert_hostname": false,
            "validate_certs": true,
            "values": {
                "disabled": "no"
            }
        }
    },
    "item": [
        80,
        "hello.com"
    ],
    "msg": "Found no entries, but allow_no_matches=false"
}
failed: [any -> localhost] (item=[80, 'google.com']) => {
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "allow_no_matches": false,
            "ca_path": "keys/trust.test.ca.crt",
            "encoding": "ASCII",
            "find": {
                "action": "masquerade",
                "chain": "srcnat",
                "disabled": "yes",
                "dst-address-list": "google.com",
                "dst-port": "80",
                "protocol": "tcp",
                "src-address": "192.168.14.16"
            },
            "force_no_cert": false,
            "hostname": "gpsm.test",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "path": "ip firewall nat",
            "port": null,
            "require_matches_max": null,
            "require_matches_min": 1,
            "timeout": 10,
            "tls": false,
            "username": "admin",
            "validate_cert_hostname": false,
            "validate_certs": true,
            "values": {
                "disabled": "no"
            }
        }
    },
    "item": [
        80,
        "google.com"
    ],
    "msg": "Found no entries, but allow_no_matches=false"
}
failed: [any -> localhost] (item=[443, 'google.com']) => {
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "allow_no_matches": false,
            "ca_path": "keys/trust.test.ca.crt",
            "encoding": "ASCII",
            "find": {
                "action": "masquerade",
                "chain": "srcnat",
                "disabled": "yes",
                "dst-address-list": "google.com",
                "dst-port": "443",
                "protocol": "tcp",
                "src-address": "192.168.14.16"
            },
            "force_no_cert": false,
            "hostname": "gpsm.test",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "path": "ip firewall nat",
            "port": null,
            "require_matches_max": null,
            "require_matches_min": 1,
            "timeout": 10,
            "tls": false,
            "username": "admin",
            "validate_cert_hostname": false,
            "validate_certs": true,
            "values": {
                "disabled": "no"
            }
        }
    },
    "item": [
        443,
        "google.com"
    ],
    "msg": "Found no entries, but allow_no_matches=false"
}

Sure

ISSUE TYPE
  • Your Report
    not sure if it's bug or need more info
COMPONENT NAME
montip: 192.168.14.16
montport: [443,80] #443/80
montproto: tcp #tcp/udp
user: root
websites: ['hello.com','google.com']
- name: Adjust NAT
community.routeros.api_find_and_modify:
  hostname: "{{ hostname }}"
  password: "{{ password }}"
  username: "{{ username }}"
  ca_path: "{{ ca_path }}"
  path: ip firewall nat
  find: >-
   src-address={{ montip }}
   protocol={{ montproto }}
   dst-address-list={{ item.1 }}
   dst-port={{ item.0 }}
   chain={{ natchain }}
   action={{ nataction }}
   out-interface-list={{ interfacelist }}
   disabled={{ natstatus }}
  values: 
    disabled: "no"
  require_matches_min: 1
  # allow_no_matches=true
  # require_matches_max: 1
delegate_to: localhost
register:   QueryNatOut
with_nested:  
  - "{{ montport }}"
  - "{{ websites }}"
ANSIBLE VERSION
ansible [core 2.13.3]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.9/site-packages/ansible
  ansible collection location = /home/user/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.9.16 (main, Dec 21 2022, 10:57:18) [GCC 8.5.0 20210514 (Red Hat 8.5.0-17)]
  jinja version = 3.1.2
  libyaml = True

Thanks

Every run of a playbook shows bunch of tasks with state changed, but vars are same. is it designed without idempotency?

I's not bug report, it's question about idempotency, of module community.routeros.command

i have a playbook:


  • name: Full configuration of mikrotik routers
    hosts: _routers
    gather_facts: false
    tasks:

    • name: Fill full config to the router
      community.routeros.command:
      commands: "{{ item }}"
      with_items: "{{config_lines}}"

    vars are static, but every run shows me that something was changed ( without real change).
    i hope to see green ok status when running playbook with same unchanged variables.

    Can anyone clarify me my doubts please?

[3.0.0] command should not claim to support check mode

SUMMARY

Right now the command module claims that it supports check mode. This is wrong, as it does not (it has no clue whether the commands it executes do changes or not). We should change this in 3.0.0.

(We shouldn't change it earlier since there might be a lot of roles and playbooks that depend on it, and for them it will be a breaking change.)

ISSUE TYPE
  • Bug Report
COMPONENT NAME

command

[API] The comment breaks the work of the module

Of course, it was very funny to look for the cause of the error for so much time, but after looking at the source code, everything became clear.

Guys, we need to correct the division of the string into parameters, because the comment does not always consist of one word.

The function that returns the error

A function that incorrectly separates arguments and breaks down into comment="some multiple string"

How to reproduce it?
Try to add a simple rule of the form:

  community.routeros.api:
    hostname: "{{ mikrotik_host }}"
    username: "{{ mikrotik_user }}"
    password: "{{ mikrotik_password }}"
    path: ip firewall filter
    add: action=accept chain=forward comment='accept in ipsec policy' ipsec-policy=in,ipsec

The actual result will be an error when adding the rule, but by the way, this module does not understand its own errors at all and always returns OK, which is also funny and requires correction.

With the debug, I was able to see the true result of the execution and the essence of the "error":

    "msg": [
        "missing '=' after 'in'"

A few details:

ok: [localhost] => (item={'comment': 'accept in ipsec policy', 'id': 6, 'action': 'accept', 'chain': 'forward', 'options': 'ipsec-policy=in,ipsec'}) => {
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "add": "action=accept chain=forward comment='accept in ipsec policy' ipsec-policy=in,ipsec",  <<< here
            "cmd": null,
            "hostname": "10.0.0.1",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "path": "ip firewall filter",
            "port": null,
            "query": null,
            "remove": null,
            "ssl": false,
            "update": null,
            "username": "ansible"
        }
    },
    "item": {
        "action": "accept",
        "chain": "forward",
        "comment": "accept in ipsec policy",
        "ipsec-policy: "in,ipsec"
    },
    "msg": [
        "missing '=' after 'in'"  <<< here

Duplicate data in stdout and facts starting with RouterOS 7.2

SUMMARY

Starting with Router OS 7.2 stdout of community.routeros.command contains the output twice. And when running community.routeros.facts against a device with RouterOS 7.2 or newer (tested up to RouterOS 7.6) hostvars[inventory_hostname]['ansible_net_config'] contains the config twice.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.routeros.facts
community.routeros.command

ANSIBLE VERSION
ansible [core 2.13.6]
  config file = /home/markus/gits/ansible-speedcom-backbone/ansible.cfg
  configured module search path = ['/home/markus/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/markus/gits/ansible-speedcom-backbone/.venv/lib/python3.10/site-packages/ansible
  ansible collection location = /home/markus/gits/ansible-speedcom-backbone/.ansible/collections
  executable location = /home/markus/gits/ansible-speedcom-backbone/.venv/bin/ansible
  python version = 3.10.6 (main, Nov  2 2022, 18:53:38) [GCC 11.3.0]
  jinja version = 3.1.2
  libyaml = True

COLLECTION VERSION
Collection         Version
------------------ -------
community.routeros 2.3.1 
OS / ENVIRONMENT

RouterOS>=7.2

STEPS TO REPRODUCE
    - name: Collect only the config and default facts
      community.routeros.facts:
        gather_subset:
          - "config"

    - name: Save Config Backup
      ansible.builtin.copy:
        content: "{{ hostvars[inventory_hostname]['ansible_net_config'] }}"
        dest: "{{ backup_dir }}/{{ inventory_hostname }}_config.{{ lookup('pipe', 'date +%Y%m%d') }}.txt"
      delegate_to: localhost

    - name: Run command
      community.routeros.command:
        commands: /system/routerboard/print
      register: config

    - name: Save Output to File
      ansible.builtin.copy:
        content: "{{ config.stdout_lines }}"
        dest: "{{ backup_dir }}/{{ inventory_hostname }}_routerboard_print.{{ lookup('pipe', 'date +%Y%m%d') }}.txt"
      delegate_to: localhost
EXPECTED RESULTS

stdout and hostvars[inventory_hostname]['ansible_net_config'] should not contain duplicate data.

ACTUAL RESULTS

stdout and hostvars[inventory_hostname]['ansible_net_config'] contains duplicate data.

Mikrotik RouterOS Platform Unable to Respond to Command Line Prompts

SUMMARY

Initially opened this on the master ansible page under issue #75305, but was told to post here instead. I am trying to make configuration changes on RouterOS that require you to respond to a yes or no prompt, but there does not seem to be a way to do this. I found the below link and tried it, however I am getting an error when using it with RouterOS (probably doesnt exist in the module).

https://docs.ansible.com/ansible/latest/network/user_guide/network_working_with_command_output.html

Is this just a feature that does not exist and would need to be developed, or am I doing something wrong?

ISSUE TYPE
  • Bug Report
COMPONENT NAME

routeros module

ANSIBLE VERSION

  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/netblazr/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/netblazr/.local/lib/python3.8/site-packages/ansible
  ansible collection location = /home/netblazr/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/netblazr/.local/bin/ansible
  python version = 3.8.10 (default, Jun  2 2021, 10:49:15) [GCC 9.4.0]
  jinja version = 2.10.1
  libyaml = True

COLLECTION VERSION

/.ansible/collections/ansible_collections
Collection         Version
------------------ -------
community.routeros 1.2.0


CONFIGURATION


DEFAULT_LOG_PATH(/etc/ansible/ansible.cfg) = /etc/ansible/ansible.log
DEFAULT_REMOTE_PORT(/etc/ansible/ansible.cfg) = 7022
DEFAULT_REMOTE_USER(/etc/ansible/ansible.cfg) = admin
DEFAULT_TIMEOUT(/etc/ansible/ansible.cfg) = 1000
HOST_KEY_CHECKING(/etc/ansible/ansible.cfg) = False

OS / ENVIRONMENT

Ubuntu 20.04

STEPS TO REPRODUCE
Command that I run is here: ansible-playbook mipse_upgrade.yml -k -i test_host

Host file is below:
[all:vars]
ansible_user=####
ansible_port=####
ansible_network_os=routeros

SW1 ansible_host=10.28.134.3
SW2 ansible_host=10.28.134.4
SW3 ansible_host=10.28.139.2
SW4 ansible_host=10.28.139.3
SW5 ansible_host=10.28.143.2
SW6 ansible_host=10.28.143.3

Playbook is below:

    hosts: all
    connection: network_cli
    gather_facts: false
    vars:
    upgrade: 6.47.10

    tasks:

        name: Get OS Version
        routeros_command:
        commands: /system routerboard print
        register: output

        name: Get Current Firmware Line
        set_fact:
        current: "{{ item | replace('current-firmware: ', '') | trim }}"
        when: "'current-firmware:' in item"
        loop: "{{ output.stdout_lines[0] }}"

        name: Download new firmware if needed
        routeros_command:
        commands: /tool fetch address=10.10.72.2 src-path=/srv/ftp/routeros-mipsbe-6.47.10.npk user=#### password=#### dst-path=routeros-mipsbe-6.47.10.npk port=21 mode=ftp
        when: current is version_compare(upgrade, '<')

        name: Upgrade Firmware
        routeros_command:
        commands:
        - /system routerboard upgrade
        prompt:
        - "Do you really want to upgrade firmware? [y/n]"
        answer:
        - 'y'
        when: current is version_compare(upgrade, '<')

        name: Reboot the router
        routeros_command:
        commands: ":execute {/system reboot;delay 1;quit}"
        when: current is version_compare(upgrade, '<')

EXPECTED RESULTS

Expected ansible to respond to the prompt Do you really want to upgrade firmware? [y/n] with a "y" causing the router to upgrade. But this seems to be unsupported by RouterOS.

ACTUAL RESULTS

SSH password:

PLAY [all] ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************

TASK [Get OS Version] *****************************************************************************************************************************************************************************************************************************************************************************************************************************************************
[DEPRECATION WARNING]: Distribution Ubuntu 20.04 on host SW3 should use /usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See https://docs.ansible.com/ansible/2.11/reference_appendices/interpreter_discovery.html for
more information. This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [SW3]
[DEPRECATION WARNING]: Distribution Ubuntu 20.04 on host SW1 should use /usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See https://docs.ansible.com/ansible/2.11/reference_appendices/interpreter_discovery.html for
more information. This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [SW1]
[DEPRECATION WARNING]: Distribution Ubuntu 20.04 on host SW2 should use /usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See https://docs.ansible.com/ansible/2.11/reference_appendices/interpreter_discovery.html for
more information. This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [SW2]
[DEPRECATION WARNING]: Distribution Ubuntu 20.04 on host SW5 should use /usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See https://docs.ansible.com/ansible/2.11/reference_appendices/interpreter_discovery.html for
more information. This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [SW5]
[DEPRECATION WARNING]: Distribution Ubuntu 20.04 on host SW4 should use /usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See https://docs.ansible.com/ansible/2.11/reference_appendices/interpreter_discovery.html for
more information. This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [SW4]
[DEPRECATION WARNING]: Distribution Ubuntu 20.04 on host SW6 should use /usr/bin/python3, but is using /usr/bin/python for backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python for this host. See https://docs.ansible.com/ansible/2.11/reference_appendices/interpreter_discovery.html for
more information. This feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
ok: [SW6]

TASK [Get Current Firmware Line] ******************************************************************************************************************************************************************************************************************************************************************************************************************************************
skipping: [SW1] => (item=routerboard: yes)
skipping: [SW1] => (item=             model: CRS125-24G-1S)
skipping: [SW1] => (item=     serial-number: 7381067E1946)
skipping: [SW1] => (item=     firmware-type: ar9344)
skipping: [SW1] => (item=  factory-firmware: 3.33)
skipping: [SW2] => (item=routerboard: yes)
skipping: [SW2] => (item=             model: CRS125-24G-1S)
skipping: [SW2] => (item=     serial-number: 738106DEC18F)
skipping: [SW2] => (item=     firmware-type: ar9344)
skipping: [SW2] => (item=  factory-firmware: 3.33)
skipping: [SW3] => (item=routerboard: yes)
skipping: [SW3] => (item=             model: CRS125-24G-1S)
skipping: [SW3] => (item=     serial-number: 738106FA5F2A)
skipping: [SW4] => (item=routerboard: yes)
skipping: [SW4] => (item=             model: CRS125-24G-1S)
skipping: [SW4] => (item=     serial-number: 738106BE8983)
skipping: [SW4] => (item=     firmware-type: ar9344)
skipping: [SW4] => (item=  factory-firmware: 3.33)
skipping: [SW3] => (item=     firmware-type: ar9344)
skipping: [SW5] => (item=routerboard: yes)
skipping: [SW3] => (item=  factory-firmware: 3.33)
skipping: [SW5] => (item=             model: CRS125-24G-1S)
skipping: [SW5] => (item=     serial-number: 738106160FA2)
skipping: [SW5] => (item=     firmware-type: ar9344)
skipping: [SW5] => (item=  factory-firmware: 3.33)
ok: [SW3] => (item=  current-firmware: 6.45.9)
skipping: [SW3] => (item=  upgrade-firmware: 6.47.10)
ok: [SW4] => (item=  current-firmware: 6.45.9)
skipping: [SW4] => (item=  upgrade-firmware: 6.47.10)
skipping: [SW6] => (item=routerboard: yes)
skipping: [SW6] => (item=             model: CRS125-24G-1S)
skipping: [SW6] => (item=     serial-number: 738106E28184)
skipping: [SW6] => (item=     firmware-type: ar9344)
skipping: [SW6] => (item=  factory-firmware: 3.33)
ok: [SW1] => (item=  current-firmware: 6.47.10)
skipping: [SW1] => (item=  upgrade-firmware: 6.47.10)
ok: [SW2] => (item=  current-firmware: 6.45.9)
skipping: [SW2] => (item=  upgrade-firmware: 6.47.10)
ok: [SW5] => (item=  current-firmware: 6.45.9)
skipping: [SW5] => (item=  upgrade-firmware: 6.47.10)
ok: [SW6] => (item=  current-firmware: 6.45.9)
skipping: [SW6] => (item=  upgrade-firmware: 6.47.10)

TASK [Download new firmware if needed] ************************************************************************************************************************************************************************************************************************************************************************************************************************************
skipping: [SW1]
ok: [SW3]
ok: [SW6]
ok: [SW4]
ok: [SW2]
ok: [SW5]

TASK [Upgrade Firmware] ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************
skipping: [SW1]
fatal: [SW3]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (routeros_command) module: answer, prompt. Supported parameters include: retries, commands, interval, wait_for, match."}
fatal: [SW2]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (routeros_command) module: answer, prompt. Supported parameters include: retries, commands, interval, wait_for, match."}
fatal: [SW4]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (routeros_command) module: answer, prompt. Supported parameters include: retries, commands, interval, wait_for, match."}
fatal: [SW5]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (routeros_command) module: answer, prompt. Supported parameters include: retries, commands, interval, wait_for, match."}
fatal: [SW6]: FAILED! => {"changed": false, "msg": "Unsupported parameters for (routeros_command) module: answer, prompt. Supported parameters include: retries, commands, interval, wait_for, match."}

TASK [Reboot the router] **************************************************************************************************************************************************************************************************************************************************************************************************************************************************
skipping: [SW1]

PLAY RECAP ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
SW1                        : ok=2    changed=0    unreachable=0    failed=0    skipped=3    rescued=0    ignored=0
SW2                        : ok=3    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
SW3                        : ok=3    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
SW4                        : ok=3    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
SW5                        : ok=3    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0
SW6                        : ok=3    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

Fatal during task execution

SUMMARY

I have a list of MikroTik cAP ac in my inventory. On some devices, task crashes when doing a simple task, while others do it successfully.
fatal: [router]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "msg": "timeout value 30 seconds reached while trying to send command: b'/system resource print'"}

ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.routeros.command

ANSIBLE VERSION
ansible [core 2.11.3]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.5/dist-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.5.3 (default, Apr  5 2021, 09:00:41) [GCC 6.3.0 20170516]
  jinja version = 2.11.3
  libyaml = False
COLLECTION VERSION
# /usr/local/lib/python3.5/dist-packages/ansible_collections
Collection         Version
------------------ -------
community.routeros 1.2.0

# /root/.ansible/collections/ansible_collections
Collection         Version
------------------ -------
community.routeros 1.2.0
CONFIGURATION
DEFAULT_HOST_LIST(/etc/ansible/ansible.cfg) = ['/etc/ansible/hosts']
DEFAULT_PRIVATE_KEY_FILE(/etc/ansible/ansible.cfg) = /root/.ssh/id_rsa
OS / ENVIRONMENT

cAP ac
firmware: 6.48.4
board-name: cAP ac
model: RBcAPGi-5acD2nD
revision: r2
serial-number: B9320B9EF0D4
firmware-type: ipq4000L
factory-firmware: 6.44
OS
Distributor ID: Debian
Description: Debian GNU/Linux 9.13 (stretch)
Release: 9.13
Codename: stretch

STEPS TO REPRODUCE

[community]
host ansible_host=10.10.5.105
[community:vars]
ansible_connection=ansible.netcommon.network_cli
ansible_network_os=community.routeros.routeros
ansible_user=user
ansible_ssh_private_key_file=/root/.ssh/id_rsa
ansible_connection=network_cli
ansible_ssh_extra_args='-o StrictHostKeyChecking=no'

- name: RouterOS test with network_cli connection
  hosts: community
  gather_facts: false
  connection: ansible.netcommon.network_cli
  vars:
    ansible_python_interpreter: "{{ ansible_playbook_python }}"
  tasks:

    - name: Get Firmware
      community.routeros.command:
        commands: - /system routerboard print
      register: output
EXPECTED RESULTS

ok: [host]

ACTUAL RESULTS

fatal: [host]: FAILED! => {"changed": false, "msg": "timeout value 30 seconds reached while trying to send command: b'/system resource print'"}
or
fatal: [host]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "msg": "timeout value 30 seconds reached while trying to send command: b'/system resource print'"}

/usr/local/lib/python3.5/dist-packages/ansible/parsing/vault/__init__.py:44: CryptographyDeprecationWarning: Python 3.5 support will be dropped in the next release of cryptography. Please upgrade your Python.
  from cryptography.exceptions import InvalidSignature
ansible-playbook [core 2.11.3]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.5/dist-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible-playbook
  python version = 3.5.3 (default, Apr  5 2021, 09:00:41) [GCC 6.3.0 20170516]
  jinja version = 2.11.3
  libyaml = False
Using /etc/ansible/ansible.cfg as config file
host_list declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
script declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
auto declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Parsed /etc/ansible/hosts inventory source with ini plugin
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: cap-office-backup ***************************************************************************************************************************************************************************************
1 plays in cap-office-backup

PLAY [RouterOS test with network_cli connection] ******************************************************************************************************************************************************************
META: ran handlers

TASK [Get Firmware] ***********************************************************************************************************************************************************************************************
task path: /etc/ansible/cap-office-backup:9
redirecting (type: connection) ansible.builtin.network_cli to ansible.netcommon.network_cli
<10.10.5.105> ESTABLISH LOCAL CONNECTION FOR USER: root
<10.10.5.105> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-local-31895pgb851rm `"&& mkdir "` echo /root/.ansible/tmp/ansible-local-31895pgb851rm/ansible-tmp-1632405069.1125197-31938-187202320516234 `" && echo ansible-tmp-1632405069.1125197-31938-187202320516234="` echo /root/.ansible/tmp/ansible-local-31895pgb851rm/ansible-tmp-1632405069.1125197-31938-187202320516234 `" ) && sleep 0'
Using module file /root/.ansible/collections/ansible_collections/community/routeros/plugins/modules/command.py
<10.10.5.105> PUT /root/.ansible/tmp/ansible-local-31895pgb851rm/tmpm79bs6ky TO /root/.ansible/tmp/ansible-local-31895pgb851rm/ansible-tmp-1632405069.1125197-31938-187202320516234/AnsiballZ_command.py
<10.10.5.105> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-local-31895pgb851rm/ansible-tmp-1632405069.1125197-31938-187202320516234/ /root/.ansible/tmp/ansible-local-31895pgb851rm/ansible-tmp-1632405069.1125197-31938-187202320516234/AnsiballZ_command.py && sleep 0'
<10.10.5.105> EXEC /bin/sh -c '/usr/bin/python3 /root/.ansible/tmp/ansible-local-31895pgb851rm/ansible-tmp-1632405069.1125197-31938-187202320516234/AnsiballZ_command.py && sleep 0'
<10.10.5.105> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-local-31895pgb851rm/ansible-tmp-1632405069.1125197-31938-187202320516234/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
  File "/tmp/ansible_community.routeros.command_payload_yowzf4on/ansible_community.routeros.command_payload.zip/ansible_collections/community/routeros/plugins/module_utils/routeros.py", line 74, in get_capabilities
    capabilities = Connection(module._socket_path).get_capabilities()
  File "/tmp/ansible_community.routeros.command_payload_yowzf4on/ansible_community.routeros.command_payload.zip/ansible/module_utils/connection.py", line 195, in __rpc__
    raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code)
fatal: [host ]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "commands": [
                - "/system routerboard print"
            ],
            "interval": 1,
            "match": "all",
            "retries": 10,
            "wait_for": null
        }
    },
    "msg": "timeout value 30 seconds reached while trying to send command: b'/system resource print'"
}

PLAY RECAP ********************************************************************************************************************************************************************************************************
host : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

Error 'identity' must be '.id' module community.routeros.api

SUMMARY

Hello.

I am trying to get neighbor data through community.routeros.api.
When I add the "identity" field to the list, I get an error "'identity' must be '.id'". Is it supposed to be like this or is it a bug?

ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.routeros.api

ANSIBLE VERSION
ansible [core 2.12.2]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.9/site-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.9.7 (default, Nov 24 2021, 21:15:59) [GCC 10.3.1 20211027]
  jinja version = 3.0.3
  libyaml = False
COLLECTION VERSION
# /usr/lib/python3.9/site-packages/ansible_collections
Collection         Version
------------------ -------
community.routeros 2.0.0 
CONFIGURATION
DEFAULT_ASK_PASS(/etc/ansible/ansible.cfg) = False
DEFAULT_GATHERING(/etc/ansible/ansible.cfg) = smart
DEFAULT_HOST_LIST(/etc/ansible/ansible.cfg) = ['/root/ansible/hosts.yaml']
HOST_KEY_CHECKING(/etc/ansible/ansible.cfg) = False
OS / ENVIRONMENT
routerboard: yes
board-name: SXT 2
model: RBSXTG-2HnD
revision: r3
serial-number: E2230F5EDF77
firmware-type: ar9344L
factory-firmware: 6.47.10
current-firmware: 6.47.10
upgrade-firmware: 6.46.
STEPS TO REPRODUCE
    - name: Get "ip neighbor query" {{ inventory_hostname }}
      community.routeros.api:
        hostname: "{{ ansible_host }}"
        port: "{{ api_port }}"
        password: "{{ ansible_password }}"
        username: "{{ ansible_user }}"
        path: "ip neighbor"
        query: ".id address mac-address identity"
      register: neighbor_list
EXPECTED RESULTS

I need to get the IP addresses and names of devices connected to the AP via WDS. To do this, I request data from the list of /ip neighbors: ip address, mac-address, record .id and identity. Further I process by mac-address.

ACTUAL RESULTS

As a result I get an error.

fatal: [tmp5-1]: FAILED! => {"changed": false, "msg": ["'identity' must be '.id'"]}

issue with community.routeros.command and community.routeros.facts when there is a dash in the username

SUMMARY

If the username contains a dash "-" (something like "ssh-admin"), the connection timeout error will appear.

ISSUE TYPE
  • Bug Report
COMPONENT NAME
ANSIBLE VERSION
2.9.16 and 2.10.2
CONFIGURATION
DEFAULT_ASK_PASS(/home/phil/ansible/ansible.cfg) = False
DEFAULT_HOST_LIST(/home/phil/ansible/ansible.cfg) = ['/home/phil/ansible/myhosts']
DEPRECATION_WARNINGS(/home/phil/ansible/ansible.cfg) = False
OS / ENVIRONMENT

Debian buster

STEPS TO REPRODUCE

Make the username with a dash inside it (eg ssh-admin) for login on routeros device. And then try to start playbook with him.

- name: RouterOS test with network_cli connection
  hosts: mikrotik_server
  gather_facts: false
  tasks:

   - community.routeros.command:
      commands:
        - /system resource print
    register: system_resource_print
  - debug:
      var: system_resource_print.stdout_lines

 - community.routeros.facts:
  - debug:
      msg: "First IP address: {{ ansible_net_all_ipv4_addresses[0] }}"
EXPECTED RESULTS

PLAY [RouterOS test with network_cli connection] ************************************************************************************************************

TASK [community.routeros.command] ***************************************************************************************************************************
ok: [172.16.10.172]

TASK [debug] ************************************************************************************************************************************************
ok: [172.16.10.172] => {
"system_resource_print.stdout_lines": [
[
"uptime: 1w3d23h36m54s",
" version: 6.46.8 (long-term)",
" build-time: Oct/29/2020 08:29:55",
" free-memory: 189.3MiB",
" total-memory: 224.0MiB",
" cpu: Intel(R)",
" cpu-count: 4",
" cpu-frequency: 2400MHz",
" cpu-load: 0%",
" free-hdd-space: 31.3MiB",
" total-hdd-space: 63.5MiB",
" write-sect-since-reboot: 3600",
" write-sect-total: 3601",
" architecture-name: x86_64",
" board-name: CHR",
" platform: MikroTik"
]
]
}

TASK [community.routeros.facts] *****************************************************************************************************************************
ok: [172.16.10.172]

TASK [debug] ************************************************************************************************************************************************
ok: [172.16.10.172] => {
"msg": "First IP address: 172.16.10.172"
}

PLAY RECAP **************************************************************************************************************************************************
172.16.10.172 : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0

ACTUAL RESULTS

The full traceback is:
File "/tmp/ansible_community.routeros.command_payload_jqwdps2f/ansible_community.routeros.command_payload.zip/ansible_collections/community/routeros/plugins/module_utils/routeros.py", line 74, in get_capabilities
capabilities = Connection(module._socket_path).get_capabilities()
File "/tmp/ansible_community.routeros.command_payload_jqwdps2f/ansible_community.routeros.command_payload.zip/ansible/module_utils/connection.py", line 195, in rpc
raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code)
fatal: [172.16.10.172]: FAILED! => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": false,
"invocation": {
"module_args": {
"commands": [
"/system resource print"
],
"interval": 1,
"match": "all",
"retries": 10,
"wait_for": null
}
},
"msg": "timeout value 30 seconds reached while trying to send command: b'/system resource print'"
}


api_modify unsupported keys

Hello there,
I've started to work with this collection to configure routeros hardware, first of all thanks for this great piece of software it's a real pleasure working with it !

SUMMARY

I've encountered some keys unsupported by api_modify :

- name: ip firewall filter
  community.routeros.api_modify:
    path: ip firewall filter
    data: 
      "{{ firewall_filters }}"

loop item :
        {
            "action": "fasttrack-connection",
            "chain": "forward",
            "connection-state": "established,related",
            "hw-offload": true,
        },

result:
TASK [mikrotik : ip firewall filter] 
FAILED! => {"changed": false, "msg": "Unknown key \"hw-offload\" at index 1."}

Same here :

- name: interface ethernet
  community.routeros.api_modify:
    path: interface ethernet
    data: 
      "{{ interfaces_ethernet }}"

loop item: 
        {
            "default-name": "ether5",
            "name": "ether5-test",
            "poe-out": "auto-on"
        },

result:
TASK [mikrotik : interface ethernet] 
FAILED! => {"changed": false, "msg": "Unknown key \"poe-out\" for default-name=\"ether5\"."}

I don't use it but I noticed poe-priority key is also missing for "interface ethernet" path

I've added these keys in my local plugins/module_utils/_api_data.py file and these tasks are running happily

ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.routeros.api_modify

ANSIBLE VERSION
ansible [core 2.12.9]
  python version = 3.10.7 (main, Sep  7 2022, 00:00:00) [GCC 12.2.1 20220819 (Red Hat 12.2.1-1)]
  jinja version = 3.0.3
  libyaml = True
COLLECTION VERSION
Collection         Version
------------------ -------
community.routeros 2.3.0
OS / ENVIRONMENT

Mikrotik ROS 7.5 (stable)

Routeros tasks switch to paramiko transport ignoring any settings

SUMMARY

It is pretty unclear to me, why paramiko is even used here, so I file this as a bug report. Ansible uses normal ssh binary, except when I try to run routeros tasks. Then it requires the paramiko lib for some reason, which does not use my ~/.ssh/config and has all kinds of its own issues. I grepped through this repo if paramiko appears anywhere but cannot find it.
I am now thoroughly puzzled.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

ansible-playbook, community.routeros.command

ANSIBLE VERSION
ansible --version
ansible 2.10.8
  config file = None
  configured module search path = ['/home/at/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = <....> venv/lib/python3.8/site-packages/ansible
  executable location = <...> venv/bin/ansible
  python version = 3.8.5 (default, Jan 27 2021, 15:41:15) [GCC 9.3.0]
CONFIGURATION
<empt>
OS / ENVIRONMENT

Linux XXXX 5.4.0-66-lowlatency #74-Ubuntu SMP PREEMPT Wed Jan 27 23:41:42 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

STEPS TO REPRODUCE
  • in fresh python venv:
  • pip install ansible
  • create minimal example inventory with one router and one "normal" linux host
[routers]
router ansible_host=192.168.88.1

[routers:vars]
ansible_connection=ansible.netcommon.network_cli
connection=network_cli
ansible_network_os=community.routeros.routeros
ansible_user=admin
gather_facts=no
ansible_gather_facts=no
ansible_python_interpreter=auto_silent

[servers]
someserver    ansible_host=someserver

playbook:

---
- name: RouterOS test with network_cli connection
  hosts: routers
  gather_facts: false
  tasks:

  # Run a command and print its output
  - community.routeros.command:
      commands:
        - /system resource print
    register: system_resource_print
  - debug:
      var: system_resource_print.stdout_lines

  # Retrieve facts
  - community.routeros.facts:
  - debug:
      msg: "First IP address: {{ ansible_net_all_ipv4_addresses }}"
      
- name: TestSomethingElse
  hosts: servers
  tasks:
    - shell: uptime
      register: some_output
    - debug: var=some_output.stdout_lines
EXPECTED RESULTS

Run without errors

ACTUAL RESULTS
  • the routeros task:
<snip>
 ___________________________________
< TASK [community.routeros.command] >
 -----------------------------------
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

fatal: [router]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python2.7"}, "changed": false, "msg": "paramiko is not installed: No module named 'paramiko'"}
  • the "normal" linux host task runs without issues

After pip install paramiko

  • runs without issues

After pip uninstall paramiko

  • error reappears

After trying running ansible-playbook with forced ssh transport e.g. : ANSIBLE_TRANSPORT=ssh ansible-playbook -i hosts simplexample.yml

  • error still there

Problem with basic example from readme: Tries to find python interpreter on RouterOS

Please raise issues via the new interface
If I copy&paste the current inventory (ip and creds updated) and playbook example from the readme I get the following error message:

[WARNING]: Platform linux on host router is using the discovered Python interpreter at /usr/bin/python2.7, but future installation of another Python interpreter could change the meaning of that path. See
https://docs.ansible.com/ansible/2.10/reference_appendices/interpreter_discovery.html for more information.
fatal: [router]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python2.7"}, "changed": false, "msg": "paramiko is not installed: No module named 'paramiko'"}

The versions I am using:

  • python 3.8.5
  • ansible 2.10.7 in venv
  • ansible-playbook 2.10.7 in venv

Router:

admin@MikroTik] /system> routerboard print 
       routerboard: yes
  model: 951G-2HnD
  firmware-type: ar9344
  factory-firmware: 3.33
  current-firmware: 6.43.2
  upgrade-firmware: 6.44

community.routeros.facts fails for some devices

SUMMARY

community.routeros.facts module fails with cryptic Python error message on some managed targets. I don't know how these targets are different from other targets; a help is needed to help me to investigate this problem. The "reduced" facts collection (only hardware) doesn't seem to fail.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.routeros.facts module

ANSIBLE VERSION
ansible [core 2.12.4]
  config file = /home/merlin/ansible/rterminal-ansible-default/trunk/routeros/ansible.cfg
  configured module search path = ['/home/merlin/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/merlin/ansible/lib/python3.9/site-packages/ansible
  ansible collection location = /home/merlin/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/merlin/ansible/bin/ansible
  python version = 3.9.9 (main, Jan 29 2022, 08:46:33) [GCC 11.2.0]
  jinja version = 3.1.1
  libyaml = True
COLLECTION VERSION
Collection         Version
------------------ -------
community.routeros 2.0.0  

I also tried the latest version from Github, got exactly same error message (up to apparently random strings).

CONFIGURATION
DEFAULT_HOST_LIST(/home/merlin/ansible/rterminal-ansible-default/trunk/routeros/ansible.cfg) = ['/home/merlin/ansible/rterminal-ansible-default/trunk/routeros/hosts']
OS / ENVIRONMENT

Controller node: Linux muon 5.15.23-gentoo-x86_64 #1 SMP PREEMPT Tue Feb 15 09:57:12 MSK 2022 x86_64 Intel(R) Core(TM) i5-3470 CPU @ 3.20GHz GenuineIntel GNU/Linux
Ansible is running in virtualenv, it was installed right as recommended in the official docs.

Managed target: 2011UiAS-2HnD, RouterOS version 6.47.4. It shows less than 20% of CPU load and 91.4MiB of free memory.

Another target where it appeared: 962UiGS-5HacT2HnT, 6.49.2, which has low CPU load and much free memory available too.

And another one, RB4011iGS+, 6.43.4.

STEPS TO REPRODUCE
ansible gw -m community.routeros.facts
EXPECTED RESULTS

finish without problems

ACTUAL RESULTS
ansible [core 2.12.4]
  config file = /home/merlin/ansible/rterminal-ansible-default/trunk/routeros/ansible.cfg
  configured module search path = ['/home/merlin/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/merlin/ansible/lib/python3.9/site-packages/ansible
  ansible collection location = /home/merlin/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/merlin/ansible/bin/ansible
  python version = 3.9.9 (main, Jan 29 2022, 08:46:33) [GCC 11.2.0]
  jinja version = 3.1.1
  libyaml = True
Using /home/merlin/ansible/rterminal-ansible-default/trunk/routeros/ansible.cfg as config file
setting up inventory plugins
host_list declined parsing /home/merlin/ansible/rterminal-ansible-default/trunk/routeros/hosts as it did not pass its verify_file() method
script declined parsing /home/merlin/ansible/rterminal-ansible-default/trunk/routeros/hosts as it did not pass its verify_file() method
auto declined parsing /home/merlin/ansible/rterminal-ansible-default/trunk/routeros/hosts as it did not pass its verify_file() method
Parsed /home/merlin/ansible/rterminal-ansible-default/trunk/routeros/hosts inventory source with ini plugin
Loading callback plugin minimal of type stdout, v2.0 from /home/merlin/ansible/lib/python3.9/site-packages/ansible/plugins/callback/minimal.py
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.
META: ran handlers
Loading collection community.routeros from /home/merlin/ansible/lib/python3.9/site-packages/ansible_collections/community/routeros
Loading collection ansible.netcommon from /home/merlin/ansible/lib/python3.9/site-packages/ansible_collections/ansible/netcommon
<gw> attempting to start connection
<gw> using connection plugin ansible.netcommon.network_cli
Found ansible-connection at path /home/merlin/ansible/bin/ansible-connection
<gw> local domain socket does not exist, starting it
<gw> control socket path is /home/merlin/.ansible/pc/06a0df8ba2
<gw> Loading collection ansible.netcommon from /home/merlin/ansible/lib/python3.9/site-packages/ansible_collections/ansible/netcommon
<gw> Loading collection community.routeros from /home/merlin/ansible/lib/python3.9/site-packages/ansible_collections/community/routeros
<gw> local domain socket listeners started successfully
<gw> loaded cliconf plugin ansible_collections.community.routeros.plugins.cliconf.routeros from path /home/merlin/ansible/lib/python3.9/site-packages/ansible_collections/community/routeros/plugins/cliconf/routeros.py for network_os community.routeros.routeros
<gw> ssh type is set to libssh
<gw> 
<gw> local domain socket path is /home/merlin/.ansible/pc/06a0df8ba2
<gw> ESTABLISH LOCAL CONNECTION FOR USER: merlin
<gw> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0 `"&& mkdir "` echo /home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0/ansible-tmp-1651149712.703595-10387-20298977077536 `" && echo ansible-tmp-1651149712.703595-10387-20298977077536="` echo /home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0/ansible-tmp-1651149712.703595-10387-20298977077536 `" ) && sleep 0'
Using module file /home/merlin/ansible/lib/python3.9/site-packages/ansible_collections/community/routeros/plugins/modules/facts.py
<gw> PUT /home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0/tmp0coc6sms TO /home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0/ansible-tmp-1651149712.703595-10387-20298977077536/AnsiballZ_facts.py
<gw> EXEC /bin/sh -c 'chmod u+x /home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0/ansible-tmp-1651149712.703595-10387-20298977077536/ /home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0/ansible-tmp-1651149712.703595-10387-20298977077536/AnsiballZ_facts.py && sleep 0'
<gw> EXEC /bin/sh -c '/home/merlin/ansible/bin/python /home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0/ansible-tmp-1651149712.703595-10387-20298977077536/AnsiballZ_facts.py && sleep 0'
<gw> EXEC /bin/sh -c 'rm -f -r /home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0/ansible-tmp-1651149712.703595-10387-20298977077536/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0/ansible-tmp-1651149712.703595-10387-20298977077536/AnsiballZ_facts.py", line 107, in <module>
    _ansiballz_main()
  File "/home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0/ansible-tmp-1651149712.703595-10387-20298977077536/AnsiballZ_facts.py", line 99, in _ansiballz_main
    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
  File "/home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0/ansible-tmp-1651149712.703595-10387-20298977077536/AnsiballZ_facts.py", line 47, in invoke_module
    runpy.run_module(mod_name='ansible_collections.community.routeros.plugins.modules.facts', init_globals=dict(_module_fqn='ansible_collections.community.routeros.plugins.modules.facts', _modlib_path=modlib_path),
  File "/usr/lib/python3.9/runpy.py", line 210, in run_module
    return _run_module_code(code, init_globals, run_name, mod_spec)
  File "/usr/lib/python3.9/runpy.py", line 97, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/tmp/ansible_community.routeros.facts_payload_ew3k5xxf/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py", line 652, in <module>
  File "/tmp/ansible_community.routeros.facts_payload_ew3k5xxf/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py", line 640, in main
  File "/tmp/ansible_community.routeros.facts_payload_ew3k5xxf/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py", line 347, in populate
  File "/tmp/ansible_community.routeros.facts_payload_ew3k5xxf/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py", line 365, in populate_addresses
KeyError: 'e7-kvant'
gw | FAILED! => {
    "changed": false,
    "module_stderr": "Traceback (most recent call last):\n  File \"/home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0/ansible-tmp-1651149712.703595-10387-20298977077536/AnsiballZ_facts.py\", line 107, in <module>\n    _ansiballz_main()\n  File \"/home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0/ansible-tmp-1651149712.703595-10387-20298977077536/AnsiballZ_facts.py\", line 99, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/home/merlin/.ansible/tmp/ansible-local-10384lhnt7xc0/ansible-tmp-1651149712.703595-10387-20298977077536/AnsiballZ_facts.py\", line 47, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.community.routeros.plugins.modules.facts', init_globals=dict(_module_fqn='ansible_collections.community.routeros.plugins.modules.facts', _modlib_path=modlib_path),\n  File \"/usr/lib/python3.9/runpy.py\", line 210, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/usr/lib/python3.9/runpy.py\", line 97, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/usr/lib/python3.9/runpy.py\", line 87, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_community.routeros.facts_payload_ew3k5xxf/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py\", line 652, in <module>\n  File \"/tmp/ansible_community.routeros.facts_payload_ew3k5xxf/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py\", line 640, in main\n  File \"/tmp/ansible_community.routeros.facts_payload_ew3k5xxf/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py\", line 347, in populate\n  File \"/tmp/ansible_community.routeros.facts_payload_ew3k5xxf/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py\", line 365, in populate_addresses\nKeyError: 'e7-kvant'\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}

e7-kvant is the name of one of the "public" interfaces, which has three public IP addresses configured.

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: KeyError: 'address'
gw-wka-1.al5 | FAILED! => {
    "changed": false,
    "module_stderr": "Traceback (most recent call last):\n  File \"/home/merlin/.ansible/tmp/ansible-local-10430el3ik_nf/ansible-tmp-1651150294.4569864-10557-160384140379644/AnsiballZ_facts.py\", line 107, in <module>\n    _ansiballz_main()\n  File \"/home/merlin/.ansible/tmp/ansible-local-10430el3ik_nf/ansible-tmp-1651150294.4569864-10557-160384140379644/AnsiballZ_facts.py\", line 99, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/home/merlin/.ansible/tmp/ansible-local-10430el3ik_nf/ansible-tmp-1651150294.4569864-10557-160384140379644/AnsiballZ_facts.py\", line 47, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.community.routeros.plugins.modules.facts', init_globals=dict(_module_fqn='ansible_collections.community.routeros.plugins.modules.facts', _modlib_path=modlib_path),\n  File \"/usr/lib/python3.9/runpy.py\", line 210, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/usr/lib/python3.9/runpy.py\", line 97, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/usr/lib/python3.9/runpy.py\", line 87, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_community.routeros.facts_payload_twxjy40a/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py\", line 652, in <module>\n  File \"/tmp/ansible_community.routeros.facts_payload_twxjy40a/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py\", line 640, in main\n  File \"/tmp/ansible_community.routeros.facts_payload_twxjy40a/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py\", line 347, in populate\n  File \"/tmp/ansible_community.routeros.facts_payload_twxjy40a/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py\", line 367, in populate_addresses\nKeyError: 'address'\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}

This is another kind of message, this time from hAP AC.

During the assembly of this report, I convinced myself this is a heisenbug. It happens sometimes, however with probability more than 50%. I can't see any apparent correlations. I see the error with interface name most often, but I've seen the other message about address at least once. The connection between control node and managed target is almost "direct" (through the managed switch), and I am sure there is no problems with it. Other failed nodes were accessed over the Internet.

api_modify does not support regexp in "ip dns static"

SUMMARY

If my DNS entries have regexp, the api_modify module breaks (fails with KeyError while parsing data from the router).

The api module successfully adds it for example:

- name: Add with api
  delegate_to: localhost
  community.routeros.api:
    path: ip dns static
    add: 'address=10.1.2.3 regexp=".*\\.ansible\\.test\$"'

api_modify complains about missing "name".

If I comment out satisfy_keys I can at least add the normal A record with a name, although I see regexp is missing from fields. RouterOS requires either name or regexp to be present, I'm not familiar enough with the code to tell if that's possible to check for unfortunately.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.routeros.api_modify

ANSIBLE VERSION
ansible [core 2.14.1]
  config file = /home/andrei/src/homelab/ansible/ansible.cfg
  configured module search path = ['/home/andrei/src/homelab/ansible/library']
  ansible python module location = /usr/lib/python3.10/site-packages/ansible
  ansible collection location = /home/andrei/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.8 (main, Nov  1 2022, 14:18:21) [GCC 12.2.0] (/usr/bin/python)
  jinja version = 3.1.2
  libyaml = True
COLLECTION VERSION
# /home/andrei/.ansible/collections/ansible_collections
Collection         Version
------------------ -------
community.routeros 2.5.0
OS / ENVIRONMENT

RouterOS 7.6

STEPS TO REPRODUCE

For this to fail, a record without name must exist on the router.

- name: MikroTik playbook
  hosts: mikrotik
  gather_facts: false
  module_defaults:
    group/community.routeros.api:
      hostname: "{{ ansible_host }}"
      username: "{{ api_username }}"
      password: "{{ api_password }}"
      tls: true
      validate_certs: true
      ca_path: "{{ inventory_dir }}/files/{{ inventory_hostname }}/ca.crt"

  tasks:
    - name: Add with api
      delegate_to: localhost
      community.routeros.api:
        path: ip dns static
        add: "address=10.1.2.3 name=test.ansible ttl=1h"

    - name: Add with api_modify
      delegate_to: localhost
      community.routeros.api_modify:
        path: ip dns static
        data:
          - address: "10.1.2.3"
            name: "test.ansible"
            ttl: 1h
EXPECTED RESULTS

DNS entry to be added/modified.

ACTUAL RESULTS
TASK [Add with api_modify] ***************************************************************************************************************************************************
task path: /home/andrei/src/homelab/ansible/playbooks/mikrotik.yml:26
<localhost> ESTABLISH LOCAL CONNECTION FOR USER: andrei
<localhost> EXEC /bin/sh -c 'echo ~andrei && sleep 0'
<localhost> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/andrei/.ansible/tmp `"&& mkdir "` echo /home/andrei/.ansible/tmp/ansible-tmp-1671659966.5005448-644021-192568282386458 `" && echo ansible-tmp-1671659966.5005448-644021-192568282386458="` echo /home/andrei/.ansible/tmp/ansible-tmp-1671659966.5005448-644021-192568282386458 `" ) && sleep 0'
Using module file /home/andrei/.ansible/collections/ansible_collections/community/routeros/plugins/modules/api_modify.py
<localhost> PUT /home/andrei/.ansible/tmp/ansible-local-643933cjncgwro/tmpjdb_rrab TO /home/andrei/.ansible/tmp/ansible-tmp-1671659966.5005448-644021-192568282386458/AnsiballZ_api_modify.py
<localhost> EXEC /bin/sh -c 'chmod u+x /home/andrei/.ansible/tmp/ansible-tmp-1671659966.5005448-644021-192568282386458/ /home/andrei/.ansible/tmp/ansible-tmp-1671659966.5005448-644021-192568282386458/AnsiballZ_api_modify.py && sleep 0'
<localhost> EXEC /bin/sh -c '/usr/bin/python /home/andrei/.ansible/tmp/ansible-tmp-1671659966.5005448-644021-192568282386458/AnsiballZ_api_modify.py && sleep 0'
<localhost> EXEC /bin/sh -c 'rm -f -r /home/andrei/.ansible/tmp/ansible-tmp-1671659966.5005448-644021-192568282386458/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/home/andrei/.ansible/tmp/ansible-tmp-1671659966.5005448-644021-192568282386458/AnsiballZ_api_modify.py", line 107, in <module>
    _ansiballz_main()
  File "/home/andrei/.ansible/tmp/ansible-tmp-1671659966.5005448-644021-192568282386458/AnsiballZ_api_modify.py", line 99, in _ansiballz_main
    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
  File "/home/andrei/.ansible/tmp/ansible-tmp-1671659966.5005448-644021-192568282386458/AnsiballZ_api_modify.py", line 47, in invoke_module
    runpy.run_module(mod_name='ansible_collections.community.routeros.plugins.modules.api_modify', init_globals=dict(_module_fqn='ansible_collections.community.routeros.plugins.modules.api_modify', _modlib_path=modlib_path),
  File "/usr/lib/python3.10/runpy.py", line 224, in run_module
    return _run_module_code(code, init_globals, run_name, mod_spec)
  File "/usr/lib/python3.10/runpy.py", line 96, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/tmp/ansible_community.routeros.api_modify_payload_eoa88wdc/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py", line 989, in <module>
  File "/tmp/ansible_community.routeros.api_modify_payload_eoa88wdc/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py", line 985, in main
  File "/tmp/ansible_community.routeros.api_modify_payload_eoa88wdc/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py", line 554, in sync_list
  File "/tmp/ansible_community.routeros.api_modify_payload_eoa88wdc/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py", line 554, in <genexpr>
KeyError: 'name'
fatal: [mt-router -> localhost]: FAILED! => {
    "changed": false,
    "module_stderr": "Traceback (most recent call last):\n  File \"/home/andrei/.ansible/tmp/ansible-tmp-1671659966.5005448-644021-192568282386458/AnsiballZ_api_modify.py\", line 107, in <module>\n    _ansiballz_main()\n  File \"/home/andrei/.ansible/tmp/ansible-tmp-1671659966.5005448-644021-192568282386458/AnsiballZ_api_modify.py\", line 99, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/home/andrei/.ansible/tmp/ansible-tmp-1671659966.5005448-644021-192568282386458/AnsiballZ_api_modify.py\", line 47, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.community.routeros.plugins.modules.api_modify', init_globals=dict(_module_fqn='ansible_collections.community.routeros.plugins.modules.api_modify', _modlib_path=modlib_path),\n  File \"/usr/lib/python3.10/runpy.py\", line 224, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/usr/lib/python3.10/runpy.py\", line 96, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/usr/lib/python3.10/runpy.py\", line 86, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_community.routeros.api_modify_payload_eoa88wdc/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py\", line 989, in <module>\n  File \"/tmp/ansible_community.routeros.api_modify_payload_eoa88wdc/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py\", line 985, in main\n  File \"/tmp/ansible_community.routeros.api_modify_payload_eoa88wdc/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py\", line 554, in sync_list\n  File \"/tmp/ansible_community.routeros.api_modify_payload_eoa88wdc/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py\", line 554, in <genexpr>\nKeyError: 'name'\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}

community.routeros.facts not working for MikroTik RouterOS 7.9

SUMMARY

Hello, when trying to collect facts from the device, the playbook ends with an error. For me now the problem is observed for the version of MikroTik RouterOS 7.9

ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.routeros.facts

ANSIBLE VERSION
ansible [core 2.13.6]
config file = /home/user/mkt/ansible.cfg
configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
ansible python module location = /usr/local/lib/python3.9/dist-packages/ansible
ansible collection location = /home/user/.ansible/collections:/usr/share/ansible/collections
executable location = /usr/local/bin/ansible
python version = 3.9.2 (default, Feb 28 2021, 17:03:44) [GCC 10.2.1 20210110]
jinja version = 3.1.2
libyaml = True
COLLECTION VERSION
# /home/user/.ansible/collections/ansible_collections
Collection         Version
------------------ -------
community.routeros 2.4.0  

# /usr/local/lib/python3.9/dist-packages/ansible_collections
Collection         Version
------------------ -------
community.routeros 2.4.0

CONFIGURATION
DEFAULT_FORKS(/home/user/mkt/ansible.cfg) = 50
DEFAULT_HOST_LIST(/home/user/mkt/ansible.cfg) = ['/home/user/mkt/dynamic-inventory.yml']
DEFAULT_TIMEOUT(/home/user/mkt/ansible.cfg) = 10
DEFAULT_VAULT_PASSWORD_FILE(/home/user/mkt/ansible.cfg) = /home/user/mkt/.ansible_vault_pass
DEPRECATION_WARNINGS(/home/user/mkt/ansible.cfg) = False
HOST_KEY_CHECKING(/home/user/mkt/ansible.cfg) = False
PERSISTENT_COMMAND_TIMEOUT(/home/user/mkt/ansible.cfg) = 60
PERSISTENT_CONNECT_TIMEOUT(/home/user/mkt/ansible.cfg) = 60
RETRY_FILES_ENABLED(/home/user/mkt/ansible.cfg) = True
RETRY_FILES_SAVE_PATH(/home/user/mkt/ansible.cfg) = /home/user/mkt/retry-files

OS / ENVIRONMENT

MikroTik RouterOS 7.9

STEPS TO REPRODUCE
- name: Collect all facts from the device
  community.routeros.facts:
    gather_subset: all
  register: all_facts

EXPECTED RESULTS
TASK [function/mkt/func-mkt-get-prerequisites : Collect all facts from the device] *******************************
ok: [mikrotik]
ACTUAL RESULTS
TASK [function/mkt/func-mkt-get-prerequisites : Collect all facts from the device] ***************************************************************************************************************************
task path: /home/user/mkt/roles/function/mkt/func-mkt-get-prerequisites/tasks/main.yml:12
redirecting (type: connection) ansible.builtin.network_cli to ansible.netcommon.network_cli
Loading collection ansible.netcommon from /home/user/.ansible/collections/ansible_collections/ansible/netcommon
redirecting (type: terminal) ansible.builtin.routeros to community.routeros.routeros
redirecting (type: cliconf) ansible.builtin.routeros to community.routeros.routeros
<mikrotik> attempting to start connection
<mikrotik> using connection plugin ansible.netcommon.network_cli
Found ansible-connection at path /usr/local/bin/ansible-connection
<mikrotik> local domain socket does not exist, starting it
<mikrotik> control socket path is /home/user/.ansible/pc/18be3475e8
<mikrotik> redirecting (type: connection) ansible.builtin.network_cli to ansible.netcommon.network_cli
<mikrotik> Loading collection ansible.netcommon from /home/user/.ansible/collections/ansible_collections/ansible/netcommon
<mikrotik> redirecting (type: terminal) ansible.builtin.routeros to community.routeros.routeros
<mikrotik> Loading collection community.routeros from /home/user/.ansible/collections/ansible_collections/community/routeros
<mikrotik> redirecting (type: cliconf) ansible.builtin.routeros to community.routeros.routeros
<mikrotik> local domain socket listeners started successfully
<mikrotik> loaded cliconf plugin ansible_collections.community.routeros.plugins.cliconf.routeros from path /home/user/.ansible/collections/ansible_collections/community/routeros/plugins/cliconf/routeros.py for network_os routeros
<mikrotik> ssh type is set to auto
<mikrotik> autodetecting ssh_type
<mikrotik> ssh type is now set to libssh
<mikrotik> 
<mikrotik> local domain socket path is /home/user/.ansible/pc/18be3475e8
<mikrotik> ESTABLISH LOCAL CONNECTION FOR USER: user
<mikrotik> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/user/.ansible/tmp/ansible-local-1401986htxghalb `"&& mkdir "` echo /home/user/.ansible/tmp/ansible-local-1401986htxghalb/ansible-tmp-1684477578.826196-1404386-130310613470958 `" && echo ansible-tmp-1684477578.826196-1404386-130310613470958="` echo /home/user/.ansible/tmp/ansible-local-1401986htxghalb/ansible-tmp-1684477578.826196-1404386-130310613470958 `" ) && sleep 0'
Using module file /home/user/.ansible/collections/ansible_collections/community/routeros/plugins/modules/facts.py
<mikrotik> PUT /home/user/.ansible/tmp/ansible-local-1401986htxghalb/tmpxw482l8c TO /home/user/.ansible/tmp/ansible-local-1401986htxghalb/ansible-tmp-1684477578.826196-1404386-130310613470958/AnsiballZ_facts.py
<mikrotik> EXEC /bin/sh -c 'chmod u+x /home/user/.ansible/tmp/ansible-local-1401986htxghalb/ansible-tmp-1684477578.826196-1404386-130310613470958/ /home/user/.ansible/tmp/ansible-local-1401986htxghalb/ansible-tmp-1684477578.826196-1404386-130310613470958/AnsiballZ_facts.py && sleep 0'
<mikrotik> EXEC /bin/sh -c '/usr/bin/python3 /home/user/.ansible/tmp/ansible-local-1401986htxghalb/ansible-tmp-1684477578.826196-1404386-130310613470958/AnsiballZ_facts.py && sleep 0'
<mikrotik> EXEC /bin/sh -c 'rm -f -r /home/user/.ansible/tmp/ansible-local-1401986htxghalb/ansible-tmp-1684477578.826196-1404386-130310613470958/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/home/user/.ansible/tmp/ansible-local-1401986htxghalb/ansible-tmp-1684477578.826196-1404386-130310613470958/AnsiballZ_facts.py", line 107, in <module>
    _ansiballz_main()
  File "/home/user/.ansible/tmp/ansible-local-1401986htxghalb/ansible-tmp-1684477578.826196-1404386-130310613470958/AnsiballZ_facts.py", line 99, in _ansiballz_main
    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
  File "/home/user/.ansible/tmp/ansible-local-1401986htxghalb/ansible-tmp-1684477578.826196-1404386-130310613470958/AnsiballZ_facts.py", line 47, in invoke_module
    runpy.run_module(mod_name='ansible_collections.community.routeros.plugins.modules.facts', init_globals=dict(_module_fqn='ansible_collections.community.routeros.plugins.modules.facts', _modlib_path=modlib_path),
  File "/usr/lib/python3.9/runpy.py", line 210, in run_module
    return _run_module_code(code, init_globals, run_name, mod_spec)
  File "/usr/lib/python3.9/runpy.py", line 97, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/usr/lib/python3.9/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/tmp/ansible_community.routeros.facts_payload_p2p2z2gu/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py", line 663, in <module>
  File "/tmp/ansible_community.routeros.facts_payload_p2p2z2gu/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py", line 651, in main
  File "/tmp/ansible_community.routeros.facts_payload_p2p2z2gu/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py", line 455, in populate
  File "/tmp/ansible_community.routeros.facts_payload_p2p2z2gu/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py", line 532, in parse_route
  File "/tmp/ansible_community.routeros.facts_payload_p2p2z2gu/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py", line 474, in preprocess
IndexError: list index out of range
fatal: [mikrotik]: FAILED! => {
    "changed": false,
    "module_stderr": "Traceback (most recent call last):\n  File \"/home/user/.ansible/tmp/ansible-local-1401986htxghalb/ansible-tmp-1684477578.826196-1404386-130310613470958/AnsiballZ_facts.py\", line 107, in <module>\n    _ansiballz_main()\n  File \"/home/user/.ansible/tmp/ansible-local-1401986htxghalb/ansible-tmp-1684477578.826196-1404386-130310613470958/AnsiballZ_facts.py\", line 99, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/home/user/.ansible/tmp/ansible-local-1401986htxghalb/ansible-tmp-1684477578.826196-1404386-130310613470958/AnsiballZ_facts.py\", line 47, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.community.routeros.plugins.modules.facts', init_globals=dict(_module_fqn='ansible_collections.community.routeros.plugins.modules.facts', _modlib_path=modlib_path),\n  File \"/usr/lib/python3.9/runpy.py\", line 210, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/usr/lib/python3.9/runpy.py\", line 97, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/usr/lib/python3.9/runpy.py\", line 87, in _run_code\n    exec(code, run_globals)\n  File \"/tmp/ansible_community.routeros.facts_payload_p2p2z2gu/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py\", line 663, in <module>\n  File \"/tmp/ansible_community.routeros.facts_payload_p2p2z2gu/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py\", line 651, in main\n  File \"/tmp/ansible_community.routeros.facts_payload_p2p2z2gu/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py\", line 455, in populate\n  File \"/tmp/ansible_community.routeros.facts_payload_p2p2z2gu/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py\", line 532, in parse_route\n  File \"/tmp/ansible_community.routeros.facts_payload_p2p2z2gu/ansible_community.routeros.facts_payload.zip/ansible_collections/community/routeros/plugins/modules/facts.py\", line 474, in preprocess\nIndexError: list index out of range\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}

Support new paths

SUMMARY

Good day! I use your module to automate the configuration of my Mikrotik. There was a need to configure the following paths in the configuration:
/system logging; /system logging action

ISSUE TYPE
  • Feature Idea
COMPONENT NAME

community.routeros.api_modify module – Modify data at paths with API

ADDITIONAL INFORMATION

Here is an example of the command I need to execute on my Mikrotik:
/system logging action add email-start-tls=yes email-to={{ smtp_mail_to_addr }} name={{ smtp_logging_action_name }} target=email
/system logging add action={{ smtp_logging_action_name }} topics=critical
/system logging add action={{ smtp_logging_action_name }} topics=error
/system logging add action={{ smtp_logging_action_name }} topics=warning

I'm sorry if there are errors in the text!

Ansible Contributor Summit 09.21 is open

SUMMARY

I'm happy to announce that the registration (free) for the Ansible Contributor Summit is open.

Which day should you attend?

  • If you are wondering what it means to "contribute" to Ansible, or if you have been using Ansible for a while and are thinking of ways to get more involved with the project and community, then Day 1 (September 28, Tuesday) is for you! We will have hands-on labs and demos + a hackathon.
  • If you have already been contributing or participating in our previous Contributor Summits, you are still welcome to attend Day 1, however we think that Day 2 (October 1, Friday) will be more interesting for you.

Refer to the registration page for details.

See you at the summit!

changed: false always

SUMMARY

Runs with community.routeros.command never showed changed even though things are changing.

ISSUE TYPE
  • Bug Report
COMPONENT NAME
ANSIBLE VERSION
ansible 2.9.26
  config file = /var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg
  configured module search path = ['/var/home/anthonyjrabbito/dev/infra/ansible/library', '/var/home/anthonyjrabbito/dev/infra/ansible/kubespray/library', '/var/home/anthonyjrabbito/dev/infra/ansible/k8s-cluster-installation/ansible/library']
  ansible python module location = /usr/lib/python3.10/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.10.0rc2 (default, Sep  8 2021, 00:00:00) [GCC 11.2.1 20210728 (Red Hat 11.2.1-1)]
COLLECTION VERSION
2.0.0-a1
CONFIGURATION
ANSIBLE_PIPELINING(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = True
ANSIBLE_SSH_ARGS(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = -o ControlMaster=auto -o ControlPersist=30m -o ConnectionAttempts=100 -o UserKnownHostsFil>
CACHE_PLUGIN(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = jsonfile
CACHE_PLUGIN_CONNECTION(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = /tmp
CACHE_PLUGIN_TIMEOUT(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = 7200
DEFAULT_CALLBACK_WHITELIST(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = ['profile_tasks']
DEFAULT_GATHERING(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = smart
DEFAULT_HOST_LIST(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = ['/var/home/anthonyjrabbito/dev/infra/ansible/inventory/inventory.ini']
DEFAULT_MODULE_PATH(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = ['/var/home/anthonyjrabbito/dev/infra/ansible/library', '/var/home/anthonyjrabbito/dev/>
DEFAULT_ROLES_PATH(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = ['/var/home/anthonyjrabbito/dev/infra/ansible/roles', '/var/home/anthonyjrabbito/dev/inf>
DEFAULT_STDOUT_CALLBACK(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = default
DEFAULT_STRATEGY_PLUGIN_PATH(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = ['/var/home/anthonyjrabbito/dev/infra/ansible/plugins/mitogen/ansible_mitogen/>
DEPRECATION_WARNINGS(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = False
DISPLAY_SKIPPED_HOSTS(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = False
HOST_KEY_CHECKING(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = False
INVENTORY_IGNORE_EXTS(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = ['~', '.orig', '.bak', '.ini', '.cfg', '.retry', '.pyc', '.pyo', '.creds', '.gpg']
INVENTORY_IGNORE_PATTERNS(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = ['artifacts', 'credentials']
PERSISTENT_COMMAND_TIMEOUT(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = 600
TRANSFORM_INVALID_GROUP_CHARS(/var/home/anthonyjrabbito/dev/infra/ansible/ansible.cfg) = ignore
OS / ENVIRONMENT
STEPS TO REPRODUCE
- name: system | configure hostname
  community.routeros.command:
    commands:
        - /system identity set name="{{ system.hostname }}"
EXPECTED RESULTS

Ansible will report a change.

ACTUAL RESULTS
ok: [sw-core-1.scr1.rabbito.tech] => (item={'port': 'sfp-sfpplus4', 'pvid': 10}) => {                                                                                  
    "ansible_loop_var": "item",                                                                                                                                        
    "changed": false,                                                                                                                                                  
    "invocation": {                                                                                                                                                    
        "module_args": {                                                                                                                                               
            "commands": [                                                                                                                                              
                "/interface bridge port add bridge=bridge interface=sfp-sfpplus4 pvid=10",                                                                             
                "/interface bridge vlan add bridge=bridge untagged=sfp-sfpplus4 vlan-ids=10",                                                                          
                "/interface ethernet set sfp-sfpplus4 comment=\"configured by Ansible\""                                                                               
            ],                                                                                                                                                         
            "interval": 1,                                                                                                                                             
            "match": "all",                                                                                                                                            
            "retries": 10,                                                                                                                                             
            "wait_for": null                                                                                                                                           
        }                                                                                                                                                              
    },                                                                                                                                                                 
    "item": {                                                                                                                                                          
        "port": "sfp-sfpplus4",                                                                                                                                        
        "pvid": 10                                                                                                                                                     
    },                                                                                                                                                                 
    "stdout": [                                                                                                                                                        
        "",                                                                                                                                                            
        "",       
        ""
    ],         
    "stdout_lines": [
        [  
            ""
        ],
        [            
            ""
        ],    
        [ 
            ""
        ]     
    ]     
}   

RouterOS - issue with routeros_facts when interface has a space in name

SUMMARY

When an interface has a space in its name, the routeros_facts module will fail.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

routeros

ANSIBLE VERSION
ansible 2.9.9
  config file = None
  configured module search path = ['/home/daniel/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.6/dist-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.6.9 (default, Apr 18 2020, 01:56:04) [GCC 8.4.0]
CONFIGURATION
no changes
OS / ENVIRONMENT

Windows 10, Ubuntu WSL 1

STEPS TO REPRODUCE
  1. change an interface name to: "spaces in name"
  2. run the example playbook
- name: Mikrotik Playbook
  hosts: all
  gather_facts: no
  tasks:
  - name: Get Facts
    routeros_facts:
      gather_subset: all
EXPECTED RESULTS

No crash should occur

ACTUAL RESULTS

Ansible will crash - it extracts not the whole name when spaces are present in it

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: KeyError: u'spaces'

To fix this I have changed the extraction regexp in routeros_facts.py file:
function parse_name:
match = re.search(r'name=\"([\w\d\-\s]+)\"', data, re.M)
function parse_interface:
match = re.search(r'\sinterface=([\w\d\-\s]+[\w\d\-])\s', data, re.M)

Ansible Contributor Summit. Tuesday, April 12, 2022.

Ansible Contributor Summit

We are happy to announce that the registration for the Ansible Contributor Summit is open!

Why
  • This is a great opportunity for interested people to meet, discuss related topics, share their stories and opinions, get the latest important updates and just to hang out together.

  • There will be different announcements & presentations by Community, Core, Cloud, Network, and other teams.

  • Current contributors will be happy to share their stories and experience with newcomers.

  • There will be links to interactive self-passed instruqt scenarios shared during the event that help newcomers learn different aspects of development.

Where/when

Online on Matrix and Youtube. Tuesday, April 12, 2022, 12:00 - 20:00 UTC.

How to join
  • Add the event to your calendar. Use the ical URL (for example, in Google Calendar "Add other calendars" > "Import from URL") instead of importing the .ics file so that any updates to the event will be reflected in your calendar.

  • Check out the Summit page:

    • Add you name to attendees.
    • Suggest summit topics that would be interesting to you to hear about.
    • Vote on and propose changes to topics suggested by others.
    • If you want to be a presenter, please contact the Ansible Community team via [email protected].

We are looking forward to seeing you!:)

Fail task on !trap from API

SUMMARY

It is currently impossible to catch a failed API command, because the TrapError from librouteros is specifically excluded from failing the module. (And also because the errors method incorrectly compares to "False" (string) instead of False (boolean))

IMO this is the sole advantage of the API over the CLI: That it communicates what is an error in a meaningful way.

ISSUE TYPE
  • Feature Idea
COMPONENT NAME

community.routeros.api

ADDITIONAL INFORMATION

community.routeros.api_find_and_modify is not idempotent

SUMMARY

Hello! I am using the community.routeros.api_find_and_modify module to configure the snmp community. When the role is first started, the default community will change to the required one, at the end the host state is "changed". When restarting and the configured community, the task state is "changed", although old_data and new_data are the same.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.routeros.api_find_и_modify

ANSIBLE VERSION
ansible [core 2.13.6]
ansible [core 2.13.6]
  config file = /home/user/mkt/ansible.cfg
  configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.9/dist-packages/ansible
  ansible collection location = /home/user/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.9.2 (default, Feb 28 2021, 17:03:44) [GCC 10.2.1 20210110]
  jinja version = 3.1.2
  libyaml = True
COLLECTION VERSION
# /usr/local/lib/python3.9/dist-packages/ansible_collections
Collection         Version
------------------ -------
community.routeros 2.4.0  

# /home/user/.ansible/collections/ansible_collections
Collection         Version
------------------ -------
community.routeros 2.4.0
OS / ENVIRONMENT

MikroTik RouterOS 6.46.5

STEPS TO REPRODUCE
- name: Configure SNMP Community and other
  community.routeros.api_find_and_modify:
    path: snmp community
    find:
      default: yes
    values:
      addresses: "{{ ZP_Server }},{{ local_zb_proxy_ip }}"
      name: "{{ SNMP_COMMUNITY }}"
      security: none
      disabled: no
  register: snmp_community

- name: debug snmp_community
  debug:
    msg: "{{ snmp_community }}"
EXPECTED RESULTS

When the role is restarted, it is expected that the task state will be "changed=0"

ACTUAL RESULTS

Identical old_data and new_data, with the state "changed=1" at the end after the role is restarted

"new_data": [
    {
        ".id": "*0",
        "addresses": "0.0.0.0,1.1.1.1",
        "authentication-password": "",
        "authentication-protocol": "MD5",
        "default": true,
        "disabled": false,
        "encryption-password": "",
        "encryption-protocol": "DES",
        "name": "name",
        "read-access": true,
        "security": "none",
        "write-access": false
    }
],
"old_data": [
    {
        ".id": "*0",
        "addresses": "0.0.0.0,1.1.1.1",
        "authentication-password": "",
        "authentication-protocol": "MD5",
        "default": true,
        "disabled": false,
        "encryption-password": "",
        "encryption-protocol": "DES",
        "name": "name",
        "read-access": true,
        "security": "none",
        "write-access": false

Support for automatic dependency assembly (librouteros), when building a docker container execution environment for AWX

SUMMARY
ISSUE TYPE
  • Feature Idea
COMPONENT NAME
ADDITIONAL INFORMATION

Support for automatic dependency assembly (librouteros), when building a docker container execution environment for AWX. Look https://github.com/ansible/awx-ee/tree/0.6.0 and https://ansible-builder.readthedocs.io/en/latest/collection_metadata.html
To do this, add a file to the root of the project requirements.txt with the contents of librouteros. That will be enough.

Router Identity => 19 char's doesn't work correctly with routeros_command

SUMMARY

When the router has a name greater than or equal to 19 char's the return from routeros_command

ISSUE TYPE
  • Bug Report
COMPONENT NAME

routeros_command
command

ANSIBLE VERSION
@dev ansible-test]$ ansible --version
ansible 2.9.21
  config file = /home/markmcn/ansible-test/ansible.cfg
  configured module search path = ['/home/markmcn/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.6/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.6.8 (default, Aug 18 2020, 08:33:21) [GCC 8.3.1 20191121 (Red Hat 8.3.1-5)]

CONFIGURATION
dev ansible-test]$ ansible-config dump --only-changed
DEFAULT_HOST_LIST(/home/markmcn/ansible-test/ansible.cfg) = ['/home/markmcn/ansible-test/hosts']
HOST_KEY_CHECKING(/home/markmcn/ansible-test/ansible.cfg) = False


OS / ENVIRONMENT

Running on RHEL 8 installed using DNF
Targeting Mikrotik RouterOS 6.48.2

STEPS TO REPRODUCE

set the router identity/hostname to a name of 19 char's or longer and run the play book with -v switch to see the return.
if you repeat the playbook against the same device but change the identity/hostname to a shorter name you'll get the expected result as can be seen in the output with -v

---
- hosts: 'noc_x'
  become: 'no'
  order: inventory
  serial: 1
  #  gather_facts: false

  tasks:

  - name: Check current firmware version
    routeros_command:
      commands:
        - :put [/system routerboard get current-firmware ]
    register: current_fw
EXPECTED RESULTS

Expecting the current firmware version to be returned as is shown in the output below

ansible-playbook -v ./debug.yml 
Using /home/markmcn/ansible-test/ansible.cfg as config file

PLAY [noc_x] *******************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************************************************************
ok: [dev-rt.i.domain.xx]

TASK [Check current firmware version] ******************************************************************************************************************************************************************************************************
ok: [dev-rt.i.domain.xx] => {"changed": false, "stdout": ["6.48.2"], "stdout_lines": [["6.48.2"]]}

PLAY RECAP *********************************************************************************************************************************************************************************************************************************
dev-rt.i.domain.xx       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   
ACTUAL RESULTS

After collecting the expected result above I logged into the test device and changed the hostname/identity to ThisIsAReallyLongName and repeated the test. Notice how the stdout of the return now contains mangled copies of the ROS command issued. If you shorten the hostname under the 19 char limit the result goes back to being as expected.

 ansible-playbook -v ./debug.yml 
Using /home/markmcn/ansible-test/ansible.cfg as config file

PLAY [noc_x] *******************************************************************************************************************************************************************************************************************************

TASK [Gathering Facts] *********************************************************************************************************************************************************************************************************************
ok: [dev-rt.i.domain.xx]

TASK [Check current firmware version] ******************************************************************************************************************************************************************************************************
ok: [dev-rt.i.domain.xx] => {"changed": false, "stdout": [":put [/system routerboard get current-firmware \n<ystem routerboard get current-firmware ]                                      \n<ystem routerboard get current-firmware ]\n<ystem routerboard get current-firmware ]\n\n6.48.2"], "stdout_lines": [[":put [/system routerboard get current-firmware ", "<ystem routerboard get current-firmware ]                                      ", "<ystem routerboard get current-firmware ]", "<ystem routerboard get current-firmware ]", "", "6.48.2"]]}

PLAY RECAP *********************************************************************************************************************************************************************************************************************************
dev-rt.i.domain.xx       : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Different manage RouterOS v6 and v7 via API

SUMMARY

Hello!
For a long time we have been developing roles and playbooks for RouterOS v6, both for ssh and for the api.

Now we have to support devices with RouterOS v7. Unfortunately, the code we have already written does not work with this version of RouterOS, although it would be logical that device management via the api should not change from version to version.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

ansible-collections/community.routeros.api_modify

ANSIBLE VERSION
ansible [core 2.13.6]
  config file = /home/user/mkt/ansible.cfg
  configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.9/dist-packages/ansible
  ansible collection location = /home/user/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.9.2
  jinja version = 3.1.2
  libyaml = True
COLLECTION VERSION
Collection         Version
------------------ -------
community.routeros 2.4.0
STEPS TO REPRODUCE

For RouterOS 6.49.7, this role works correctly, but for RouterOS 7.6 it ends with an error. It is logical to assume that the interaction with the device via the api should not change from version to version.

- name: For set module_defaults
  block:


    - name: Configure ntp
      community.routeros.api_modify:
        path: system ntp client
        data:
          - enabled: yes
            server-dns-names: time.google.com,0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org,3.pool.ntp.org
            primary-ntp: "{{ ntp_server_list[0] }}"
            secondary-ntp: "{{ ntp_server_list[1] }}"

    - name: Configure timezone
      community.routeros.api_modify:
        path: system clock
        data:
          - time-zone-autodetect: no
            time-zone-name: manual

    - name: Configure timezone manual
      community.routeros.api_modify:
        path: system clock manual
        data:
          - time-zone: +0{{ timezone_shift }}:00

  
  module_defaults:
    group/community.routeros.api:
      hostname: '{{ inventory_hostname }}'
      password: '{{ service_user_ans_pass }}'
      username: '{{ service_user_ans_login }}'
      tls: true
      force_no_cert: false
      validate_certs: false
      validate_cert_hostname: false
ACTUAL RESULTS
TASK [MKT/mkt-config-ntp : Configure ntp] ***********************************************************************************************************
fatal: [mikrotik1]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "ca_path": null,
            "data": [
                {
                    "enabled": true,
                    "primary-ntp": "0.0.0.0",
                    "secondary-ntp": "1.1.1.1",
                    "server-dns-names": "time.google.com,0.pool.ntp.org,1.pool.ntp.org,2.pool.ntp.org,3.pool.ntp.org"
                }
            ],
            "encoding": "ASCII",
            "ensure_order": false,
            "force_no_cert": false,
            "handle_absent_entries": "ignore",
            "handle_entries_content": "ignore",
            "hostname": "mikrotik1",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "path": "system ntp client",
            "port": null,
            "timeout": 10,
            "tls": true,
            "username": "user",
            "validate_cert_hostname": false,
            "validate_certs": false
        }
    },
    "msg": "Error while modifying: unknown parameter server-dns-names"
}

Release plan

Small collections like this one don't need a complex plan like the one for community.general and community.network. So how about the following?

Release minor and patch releases whenever we want (like after adding new features or fixing bugs). Since this collection is small, there's no need to fix things in advance. Just add features, and after a feature either wait a bit longer for more features/bugs, or make a release.

I suggest releasing form main branch, as described here: https://github.com/ansible/community/wiki/ReleasingCollections#releasing-without-release-branches-for-smaller-collections

Once we release a 2.0.0 (with some breaking change relative to 1.x.y), we can have a stable-1 branch so we can backport bugfixes (or even features) if needed, and release more 1.x.y versions.

(This is essentially what other collections I work on are doing, like community.crypto and community.sops.)

About the next release(s): I would suggest we quickly release a 1.0.0 version, so we can get it included in Ansible 2.10. We should do some testing with the current 0.1.0 release, maybe add bugfixes (or even features), if necessary release a 0.2.0 first, but not wait too long until 1.0.0.

What do you think?

CC @renatoalmeidaoliveira @NikolayDachev @adeptvin1 @heuels

(BTW, I put @heuels and @NikolayDachev as the authors of this collection since they created the plugins and modules in it. I hope that's ok for everyone!)

routeros.run_command: If the command is long, the output will be corrupted.

SUMMARY

If you specify a command that exceeds 60 characters, a part of the specified command is output.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.network.routeros_command

ANSIBLE VERSION

CONFIGURATION
# ansible --version
ansible 2.10.2
# ansible-galaxy collection list
Collection         Version
------------------ -------
ansible.netcommon  1.4.1  
check_point.mgmt   2.0.0  
community.network  1.2.0  
community.routeros 0.1.1  
fortinet.fortios   1.0.15 
vyos.vyos          1.1.0  
OS / ENVIRONMENT

cat /etc/system-release

CentOS Linux release 7.8.2003 (Core)

STEPS TO REPRODUCE
abnormal pattern:
    - name: test
      community.network.routeros_command:
        commands:
          # - '/system ntp clients set enabled=yes primary-ntp=0.0.0.0 secondary-ntp=0.0.0.0 server-dns-names=ntp.nict.jp'
          - '/interface       bridge         print detail  without-paging'

normal pattern:
    - name: test
      community.network.routeros_command:
        commands:
          # - '/system ntp clients set enabled=yes primary-ntp=0.0.0.0 secondary-ntp=0.0.0.0 server-dns-names=ntp.nict.jp'
          - '/interface       bridge         print detail without-paging'
EXPECTED RESULTS
ACTUAL RESULTS

**** abnormal pattern *********************************************************
ok: [HAPAC202] => {
"changed": false,
"invocation": {
"module_args": {
"commands": [
"/interface bridge print detail without-paging"
],
"interval": 1,
"match": "all",
"retries": 10,
"wait_for": null
}
},
"stdout": [
"/interface bridge print detail without-pagin\n<ge print detail without-paging \n<ge print detail without-paging\n<ge print detail without-paging\n\nFlags: X - disabled, R - running \n 0 R ;;; defconf\n name="bridgeLocal" mtu=auto actual-mtu=1500 l2mtu=1598 arp=enabled \n arp-timeout=auto mac-address=48:8F:5A:66:75:5A protocol-mode=rstp \n fast-forward=yes igmp-snooping=no auto-mac=no \n admin-mac=48:8F:5A:66:75:5A ageing-time=5m priority=0x8000 \n max-message-age=20s forward-delay=15s transmit-hold-count=6 \n vlan-filtering=no dhcp-snooping=no"
],
"stdout_lines": [
[
"/interface bridge print detail without-pagin",
"<ge print detail without-paging ",
"<ge print detail without-paging",
"<ge print detail without-paging",
"",
"Flags: X - disabled, R - running ",
" 0 R ;;; defconf",
" name="bridgeLocal" mtu=auto actual-mtu=1500 l2mtu=1598 arp=enabled ",
" arp-timeout=auto mac-address=48:8F:5A:66:75:5A protocol-mode=rstp ",
" fast-forward=yes igmp-snooping=no auto-mac=no ",
" admin-mac=48:8F:5A:66:75:5A ageing-time=5m priority=0x8000 ",
" max-message-age=20s forward-delay=15s transmit-hold-count=6 ",
" vlan-filtering=no dhcp-snooping=no"
]
]
}

**** normal pattern *********************************************************
ok: [HAPAC202] => {
"changed": false,
"invocation": {
"module_args": {
"commands": [
"/interface bridge print detail without-paging"
],
"interval": 1,
"match": "all",
"retries": 10,
"wait_for": null
}
},
"stdout": [
"Flags: X - disabled, R - running \n 0 R ;;; defconf\n name="bridgeLocal" mtu=auto actual-mtu=1500 l2mtu=1598 arp=enabled \n arp-timeout=auto mac-address=48:8F:5A:66:75:5A protocol-mode=rstp \n fast-forward=yes igmp-snooping=no auto-mac=no \n admin-mac=48:8F:5A:66:75:5A ageing-time=5m priority=0x8000 \n max-message-age=20s forward-delay=15s transmit-hold-count=6 \n vlan-filtering=no dhcp-snooping=no"
],
"stdout_lines": [
[
"Flags: X - disabled, R - running ",
" 0 R ;;; defconf",
" name="bridgeLocal" mtu=auto actual-mtu=1500 l2mtu=1598 arp=enabled ",
" arp-timeout=auto mac-address=48:8F:5A:66:75:5A protocol-mode=rstp ",
" fast-forward=yes igmp-snooping=no auto-mac=no ",
" admin-mac=48:8F:5A:66:75:5A ageing-time=5m priority=0x8000 ",
" max-message-age=20s forward-delay=15s transmit-hold-count=6 ",
" vlan-filtering=no dhcp-snooping=no"
]
]
}

[root@jobsv01 mikrotik]# ansible-playbook -i inventory/hosts test.yml -vvvv
ansible-playbook 2.10.2
  config file = /root/mikrotik/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
  executable location = /usr/local/bin/ansible-playbook
  python version = 3.6.8 (default, Apr  2 2020, 13:34:55) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
Using /root/mikrotik/ansible.cfg as config file
setting up inventory plugins
host_list declined parsing /root/mikrotik/inventory/hosts as it did not pass its verify_file() method
script declined parsing /root/mikrotik/inventory/hosts as it did not pass its verify_file() method
auto declined parsing /root/mikrotik/inventory/hosts as it did not pass its verify_file() method
Parsed /root/mikrotik/inventory/hosts inventory source with ini plugin
Loading collection community.network from /root/.ansible/collections/ansible_collections/community/network
Loading callback plugin default of type stdout, v2.0 from /usr/local/lib/python3.6/site-packages/ansible/plugins/callback/default.py

PLAYBOOK: test.yml ****************************************************************************************************************************************************
Positional arguments: test.yml
verbosity: 4
connection: smart
timeout: 10
become_method: sudo
tags: ('all',)
inventory: ('/root/mikrotik/inventory/hosts',)
forks: 5
1 plays in test.yml

PLAY [routeros] *******************************************************************************************************************************************************
META: ran handlers

TASK [test] ***********************************************************************************************************************************************************
task path: /root/mikrotik/test.yml:55
Loading collection ansible.netcommon from /root/.ansible/collections/ansible_collections/ansible/netcommon
<192.168.12.9> attempting to start connection
<192.168.12.9> using connection plugin ansible.netcommon.network_cli
Found ansible-connection at path /usr/local/bin/ansible-connection
<192.168.12.9> local domain socket does not exist, starting it
<192.168.12.9> control socket path is /root/.ansible/pc/e65fb158c0
<192.168.12.9> Loading collection ansible.netcommon from /root/.ansible/collections/ansible_collections/ansible/netcommon
<192.168.12.9> Loading collection community.network from /root/.ansible/collections/ansible_collections/community/network
<192.168.12.9> local domain socket listeners started successfully
<192.168.12.9> loaded cliconf plugin ansible_collections.community.network.plugins.cliconf.routeros from path /root/.ansible/collections/ansible_collections/community/network/plugins/cliconf/routeros.py for network_os community.network.routeros
<192.168.12.9> 
<192.168.12.9> local domain socket path is /root/.ansible/pc/e65fb158c0
<192.168.12.9> ESTABLISH LOCAL CONNECTION FOR USER: root
<192.168.12.9> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-local-3742u5boe25r `"&& mkdir "` echo /root/.ansible/tmp/ansible-local-3742u5boe25r/ansible-tmp-1604225621.7764585-3748-263012588570871 `" && echo ansible-tmp-1604225621.7764585-3748-263012588570871="` echo /root/.ansible/tmp/ansible-local-3742u5boe25r/ansible-tmp-1604225621.7764585-3748-263012588570871 `" ) && sleep 0'
Using module file /root/.ansible/collections/ansible_collections/community/network/plugins/modules/routeros_command.py
<192.168.12.9> PUT /root/.ansible/tmp/ansible-local-3742u5boe25r/tmp35aqsx0j TO /root/.ansible/tmp/ansible-local-3742u5boe25r/ansible-tmp-1604225621.7764585-3748-263012588570871/AnsiballZ_routeros_command.py
<192.168.12.9> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-local-3742u5boe25r/ansible-tmp-1604225621.7764585-3748-263012588570871/ /root/.ansible/tmp/ansible-local-3742u5boe25r/ansible-tmp-1604225621.7764585-3748-263012588570871/AnsiballZ_routeros_command.py && sleep 0'
<192.168.12.9> EXEC /bin/sh -c '/usr/bin/python3 /root/.ansible/tmp/ansible-local-3742u5boe25r/ansible-tmp-1604225621.7764585-3748-263012588570871/AnsiballZ_routeros_command.py && sleep 0'
<192.168.12.9> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-local-3742u5boe25r/ansible-tmp-1604225621.7764585-3748-263012588570871/ > /dev/null 2>&1 && sleep 0'
ok: [HAPAC202] => {
    "changed": false,
    "invocation": {
        "module_args": {
            "commands": [
                "/interface       bridge         print detail   without-paging"
            ],
            "interval": 1,
            "match": "all",
            "retries": 10,
            "wait_for": null
        }
    },
    "stdout": [
        "/interface       bridge         print detail   without-pagin\n<ge         print detail   without-paging                                      \n<ge         print detail   without-paging\n<ge         print detail   without-paging\n\nFlags: X - disabled, R - running \n 0 R ;;; defconf\n     name=\"bridgeLocal\" mtu=auto actual-mtu=1500 l2mtu=1598 arp=enabled \n     arp-timeout=auto mac-address=48:8F:5A:66:75:5A protocol-mode=rstp \n     fast-forward=yes igmp-snooping=no auto-mac=no \n     admin-mac=48:8F:5A:66:75:5A ageing-time=5m priority=0x8000 \n     max-message-age=20s forward-delay=15s transmit-hold-count=6 \n     vlan-filtering=no dhcp-snooping=no"
    ],
    "stdout_lines": [
        [
            "/interface       bridge         print detail   without-pagin",
            "<ge         print detail   without-paging                                      ",
            "<ge         print detail   without-paging",
            "<ge         print detail   without-paging",
            "",
            "Flags: X - disabled, R - running ",
            " 0 R ;;; defconf",
            "     name=\"bridgeLocal\" mtu=auto actual-mtu=1500 l2mtu=1598 arp=enabled ",
            "     arp-timeout=auto mac-address=48:8F:5A:66:75:5A protocol-mode=rstp ",
            "     fast-forward=yes igmp-snooping=no auto-mac=no ",
            "     admin-mac=48:8F:5A:66:75:5A ageing-time=5m priority=0x8000 ",
            "     max-message-age=20s forward-delay=15s transmit-hold-count=6 ",
            "     vlan-filtering=no dhcp-snooping=no"
        ]
    ]
}
META: ran handlers
META: ran handlers

PLAY RECAP ************************************************************************************************************************************************************
HAPAC202                   : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

[api_facts] Add "gather_subset: config"

SUMMARY

Hello! It's me, again :)
I wanted to make an analogue of the Mikrotik command (/export), not a specific path, but the entire configuration.
I tried to implement this using the community.routeros.api, but it did not lead to success.

- name: Collect all config from the device
  community.routeros.api:
    path: /
    cmd: export
  register: result

- name: debug result
  debug:
    msg: "{{ result }}"
TASK [1DEV/mkt : Collect all config from the device]****************************************************************
ok: [Mikrotik]

TASK [1DEV/mkt : debug result]**************************************************************************************
ok: [Mikrotik] => {
    "msg": {
        "changed": false,
        "failed": false,
        "msg": []
    }
}

Next, I tried to use community.routeros.api_facts, but the gather_subset parameter does not have the "config" value, as it was implemented in the similar ssh module community.routeros.facts.

ISSUE TYPE
  • Feature Idea
COMPONENT NAME

community.routeros.api_facts module – Collect facts from remote devices running MikroTik RouterOS using the API

ADDITIONAL INFORMATION

I would like to get /export with Mikrotik the following task

- name: Collect all config from the device
  community.routeros.api_facts:
    gather_subset: config
  register: result

And get approximately the following result, as implemented in community.routeros.facts

"msg": {
        "ansible_net_config": "# jan/19/2023 10:04:08 by RouterOS 6.46.5\n# software id = \n ****************",
        "ansible_net_config_nonverbose": "# RouterOS 6.46.5\n# software id = \n ****************"
}

can't change value of nat using api_find_and_modify

SUMMARY

when try to use api_find_and_modify can't get what i want by find based on input then change the value and i get the result ok (success) when remove require_matches_min: 1 but there is no change of values: so try to change it to get what i want but no luck

failed: [any -> localhost] (item=[443, 'hello.com']) => {
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "allow_no_matches": false,
            "ca_path": "keys/trust.test.ca.crt",
            "encoding": "ASCII",
            "find": {
                "action": "masquerade",
                "chain": "srcnat",
                "disabled": "yes",
                "dst-address-list": "hello.com",
                "dst-port": "443",
                "protocol": "tcp",
                "src-address": "192.168.14.16"
            },
            "force_no_cert": false,
            "hostname": "gpsm.test",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "path": "ip firewall nat",
            "port": null,
            "require_matches_max": null,
            "require_matches_min": 1,
            "timeout": 10,
            "tls": false,
            "username": "admin",
            "validate_cert_hostname": false,
            "validate_certs": true,
            "values": {
                "disabled": "no"
            }
        }
    },
    "item": [
        443,
        "hello.com"
    ],
    "msg": "Found no entries, but allow_no_matches=false"
}
failed: [any -> localhost] (item=[80, 'hello.com']) => {
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "allow_no_matches": false,
            "ca_path": "keys/trust.test.ca.crt",
            "encoding": "ASCII",
            "find": {
                "action": "masquerade",
                "chain": "srcnat",
                "disabled": "yes",
                "dst-address-list": "hello.com",
                "dst-port": "80",
                "protocol": "tcp",
                "src-address": "192.168.14.16"
            },
            "force_no_cert": false,
            "hostname": "gpsm.test",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "path": "ip firewall nat",
            "port": null,
            "require_matches_max": null,
            "require_matches_min": 1,
            "timeout": 10,
            "tls": false,
            "username": "admin",
            "validate_cert_hostname": false,
            "validate_certs": true,
            "values": {
                "disabled": "no"
            }
        }
    },
    "item": [
        80,
        "hello.com"
    ],
    "msg": "Found no entries, but allow_no_matches=false"
}
failed: [any -> localhost] (item=[80, 'google.com']) => {
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "allow_no_matches": false,
            "ca_path": "keys/trust.test.ca.crt",
            "encoding": "ASCII",
            "find": {
                "action": "masquerade",
                "chain": "srcnat",
                "disabled": "yes",
                "dst-address-list": "google.com",
                "dst-port": "80",
                "protocol": "tcp",
                "src-address": "192.168.14.16"
            },
            "force_no_cert": false,
            "hostname": "gpsm.test",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "path": "ip firewall nat",
            "port": null,
            "require_matches_max": null,
            "require_matches_min": 1,
            "timeout": 10,
            "tls": false,
            "username": "admin",
            "validate_cert_hostname": false,
            "validate_certs": true,
            "values": {
                "disabled": "no"
            }
        }
    },
    "item": [
        80,
        "google.com"
    ],
    "msg": "Found no entries, but allow_no_matches=false"
}
failed: [any -> localhost] (item=[443, 'google.com']) => {
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "allow_no_matches": false,
            "ca_path": "keys/trust.test.ca.crt",
            "encoding": "ASCII",
            "find": {
                "action": "masquerade",
                "chain": "srcnat",
                "disabled": "yes",
                "dst-address-list": "google.com",
                "dst-port": "443",
                "protocol": "tcp",
                "src-address": "192.168.14.16"
            },
            "force_no_cert": false,
            "hostname": "gpsm.test",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "path": "ip firewall nat",
            "port": null,
            "require_matches_max": null,
            "require_matches_min": 1,
            "timeout": 10,
            "tls": false,
            "username": "admin",
            "validate_cert_hostname": false,
            "validate_certs": true,
            "values": {
                "disabled": "no"
            }
        }
    },
    "item": [
        443,
        "google.com"
    ],
    "msg": "Found no entries, but allow_no_matches=false"
}

Sure

ISSUE TYPE
  • Your Report
    not sure if it's bug or need more info
COMPONENT NAME
montip: 192.168.14.16
montport: [443,80] #443/80
montproto: tcp #tcp/udp
user: root
websites: ['hello.com','google.com']
- name: Adjust NAT
community.routeros.api_find_and_modify:
  hostname: "{{ hostname }}"
  password: "{{ password }}"
  username: "{{ username }}"
  ca_path: "{{ ca_path }}"
  path: ip firewall nat
  find: >-
   src-address={{ montip }}
   protocol={{ montproto }}
   dst-address-list={{ item.1 }}
   dst-port={{ item.0 }}
   chain={{ natchain }}
   action={{ nataction }}
   out-interface-list={{ interfacelist }}
   disabled={{ natstatus }}
  values: 
    disabled: "no"
  require_matches_min: 1
  # allow_no_matches=true
  # require_matches_max: 1
delegate_to: localhost
register:   QueryNatOut
with_nested:  
  - "{{ montport }}"
  - "{{ websites }}"
ANSIBLE VERSION
ansible [core 2.13.3]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/user/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.9/site-packages/ansible
  ansible collection location = /home/user/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.9.16 (main, Dec 21 2022, 10:57:18) [GCC 8.5.0 20210514 (Red Hat 8.5.0-17)]
  jinja version = 3.1.2
  libyaml = True

Thanks

Extra lines in stdout (ROS 6.49 to 7.1.5)

SUMMARY

When I send a command to the router I get a response from the router with extra lines.
image

ISSUE TYPE
  • Bug Report
COMPONENT NAME

routeros

ANSIBLE VERSION
ansible 2.9.6
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/wsl/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.8.10 (default, Sep 28 2021, 16:10:42) [GCC 9.3.0]
COLLECTION VERSION

CONFIGURATION
[defaults]
stdout_callback = yaml
host_key_checking = False
retry_files_enabled = False
inventory = hosts.yaml
[persistent_connection]
connect_timeout = 30
command_timeout = 30
STEPS TO REPRODUCE
- name: check user is exist
  hosts: mikrotik
  gather_facts: false
  tasks:
    - name: check user is exist
      community.routeros.command:
        commands: 
          - if ([/user find name=admin] !="") do={:put "exist"}
      register: exist

    - debug:
        var: exist
EXPECTED RESULTS

I want to get only output from line 3

ACTUAL RESULTS

I got 3 lines. First-line eq first letter of command, middle-lines = empty line(empty lines can be more than one), last line eq correct output.


Confusion regarding supported keys

Hello everyone,

thank you for your time spent with creating this great piece of sotware. Recently I decided to use ansible to manage all mikrotik configrations. The main goal is to have infrastructure as code and be able to apply any changes to mikrotik devices using ansible.

I have tried very basic examples, unfortunately these do not seem to work for me.

I took basic example "Setup DHCP server networks", added key "domain", which from my point of view should work, and it produces following error.

Not sure whether this is a bug but I think this should be working. Am I wrong, please?

- name: "Mikrotik Import"
  hosts: mikrotiks
  gather_facts: no
  tasks:
    - name: Setup DHCP server networks
      community.routeros.api_modify:
        hostname: "{{ ansible_host }}"
        password: "{{ ansible_ssh_pass }}"
        username: "{{ ansible_user }}"
        path: ip dhcp-server network
        handle_absent_entries: remove
        handle_entries_content: remove_as_much_as_possible
        ensure_order: true
        data:
          - address: 192.168.88.0/24
            comment: admin network
            dns-server: 192.168.88.1
            gateway: 192.168.88.1
            # this creates the problem
            domain: lab.loc
SUMMARY
ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.routeros.api_modify

ANSIBLE VERSION
/usr/local/Cellar/ansible/5.7.1/libexec/lib/python3.10/site-packages/paramiko/transport.py:236: CryptographyDeprecationWarning: Blowfish has been deprecated
  "class": algorithms.Blowfish,
ansible [core 2.12.5]
  configured module search path = ['/Users/xxx/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/Cellar/ansible/5.7.1/libexec/lib/python3.10/site-packages/ansible
  ansible collection location = /Users/xxx/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/local/bin/ansible
  python version = 3.10.4 (main, Apr 26 2022, 19:42:59) [Clang 13.1.6 (clang-1316.0.21.2)]
  jinja version = 3.1.2
  libyaml = True
COLLECTION VERSION
# /usr/local/Cellar/ansible/5.7.1/libexec/lib/python3.10/site-packages/ansible_collections
Collection         Version
------------------ -------
community.routeros 2.0.0  

# /Users/xxx/.ansible/collections/ansible_collections
Collection         Version
------------------ -------
community.routeros 2.2.0  
CONFIGURATION
(empty)
OS / ENVIRONMENT

Targeting Mikrotik ROS 7.3.1 (stable)

STEPS TO REPRODUCE

Simply running the given playbook produces the error.

EXPECTED RESULTS

Command to be succesful, creating a DHCP server network with domain assigned.

ACTUAL RESULTS
fatal: [gw]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "ca_path": null,
            "data": [
                {
                    "address": "192.168.88.0/24",
                    "comment": "******** network",
                    "dns-server": "192.168.88.1",
                    "domain": "lab.loc",
                    "gateway": "192.168.88.1"
                }
            ],
            "encoding": "ASCII",
            "ensure_order": true,
            "handle_absent_entries": "remove",
            "handle_entries_content": "remove_as_much_as_possible",
            "hostname": "10.56.155.254",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "path": "ip dhcp-server network",
            "port": null,
            "tls": false,
            "username": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "validate_cert_hostname": false,
            "validate_certs": true
        }
    },
    "msg": "Unknown key \"domain\" for address=\"192.168.88.0/24\"."
}

RouterOS Commands Don't Seem to Be Working

SUMMARY

I have tried running a known good old playbook and a newer playbook that do similar things, the tasks say they completed but the commands are not run on the Mikrotik devices. The playbooks are simple, all they do is download a file with ftp and then run the scrip with import. I am able to run the same commands manually on the devices, so it doesn't appear to be an issue there. I also tried putting the individual commands instead of downloading the script but that made difference. The error appears to be ansible splitting up the commands into multiple lines which causes Mikrotik to not know how to proceed but I could be wrong. I have updated everything on the server using apt and rebooted the server with no change.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

MIkrotik RouterOS

ANSIBLE VERSION
ansible [core 2.11.1]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/netblazr/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/netblazr/.local/lib/python3.8/site-packages/ansible
  ansible collection location = /home/netblazr/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/netblazr/.local/bin/ansible
  python version = 3.8.10 (default, Sep 28 2021, 16:10:42) [GCC 9.3.0]
  jinja version = 2.10.1
  libyaml = True

COLLECTION VERSION
# /home/user/.ansible/collections/ansible_collections
Collection         Version
------------------ -------
community.routeros 1.2.0

# /usr/lib/python3/dist-packages/ansible_collections
Collection         Version
------------------ -------
community.routeros 1.2.0

CONFIGURATION
DEFAULT_REMOTE_PORT(/etc/ansible/ansible.cfg) = 7022
DEFAULT_TIMEOUT(/etc/ansible/ansible.cfg) = 1000
HOST_KEY_CHECKING(/etc/ansible/ansible.cfg) = False
PERSISTENT_COMMAND_TIMEOUT(/etc/ansible/ansible.cfg) = 60
PERSISTENT_CONNECT_TIMEOUT(/etc/ansible/ansible.cfg) = 60

OS / ENVIRONMENT

Running on Ubuntu 20

STEPS TO REPRODUCE
Here is the playbook. Usernames/passwords have been edited for security.

---
- hosts: all
  connection: network_cli
  gather_facts: false

  tasks:
   - name: Enable DHCP Snooping
     routeros_command:
       commands:
         /tool fetch address=10.10.72.2 src-path=/srv/ftp/enable-dhcp-snooping-crs326.rsc user=xxx password=xxx dst-path=enable-dhcp-snooping-crs326.rsc port=21 mode=ftp
         /import enable-dhcp-snooping-crs326.rsc

I just tested it on one host but here is the host file:

[all:vars]
ansible_user=xxx
ansible_ssh_pass=xxx
ansible_port=7022
ansible_network_os=routeros

[snooptest]

SW1 ansible_host=10.241.0.59

EXPECTED RESULTS

No output from the playbook but the devices should be changed. The contents of the Mikrotik script are below, all it's doing is enabling dhcp snooping and then setting a few ports to trusted.

/int bridge set dhcp-snooping=yes numbers=0
/int bridge port set trusted=yes numbers=0
/int bridge port set trusted=yes numbers=24
/int bridge port set trusted=yes numbers=25

ACTUAL RESULTS

The mikrotik devices show that ansible logs in like usual, but then the file is never downloaded or ran. Note that if I do the fetch and import commands manually it works fine. Replaced user/pass as usual.

user@Linux-Ansible:/etc/ansible$ sudo ansible-playbook enable_dhcp_snoop_crs326.yml -l snooptest -vvvv
ansible-playbook [core 2.11.6]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /root/.ansible/collections:/usr/share/ansible/collections
  executable location = /usr/bin/ansible-playbook
  python version = 3.8.10 (default, Sep 28 2021, 16:10:42) [GCC 9.3.0]
  jinja version = 2.10.1
  libyaml = True
Using /etc/ansible/ansible.cfg as config file
setting up inventory plugins
host_list declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
script declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
auto declined parsing /etc/ansible/hosts as it did not pass its verify_file() method
Parsed /etc/ansible/hosts inventory source with ini plugin
redirecting (type: modules) ansible.builtin.routeros_command to community.routeros.command
Loading collection community.routeros from /usr/lib/python3/dist-packages/ansible_collections/community/routeros
Loading callback plugin default of type stdout, v2.0 from /usr/lib/python3/dist-packages/ansible/plugins/callback/default.py
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: enable_dhcp_snoop_crs326.yml ************************************************************************************************************************************************************************************************************************************************************************************************************************************
Positional arguments: enable_dhcp_snoop_crs326.yml
verbosity: 4
connection: smart
timeout: 1000
become_method: sudo
tags: ('all',)
inventory: ('/etc/ansible/hosts',)
subset: snooptest
forks: 5
1 plays in enable_dhcp_snoop_crs326.yml

PLAY [all] ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
META: ran handlers

TASK [Enable DHCP Snooping] ***********************************************************************************************************************************************************************************************************************************************************************************************************************************************
task path: /etc/ansible/enable_dhcp_snoop_crs326.yml:7
redirecting (type: connection) ansible.builtin.network_cli to ansible.netcommon.network_cli
Loading collection ansible.netcommon from /usr/lib/python3/dist-packages/ansible_collections/ansible/netcommon
redirecting (type: terminal) ansible.builtin.routeros to community.routeros.routeros
redirecting (type: cliconf) ansible.builtin.routeros to community.routeros.routeros
<10.241.0.59> attempting to start connection
<10.241.0.59> using connection plugin ansible.netcommon.network_cli
Found ansible-connection at path /usr/bin/ansible-connection
<10.241.0.59> local domain socket does not exist, starting it
<10.241.0.59> control socket path is /root/.ansible/pc/fdd8f497bd
<10.241.0.59> redirecting (type: connection) ansible.builtin.network_cli to ansible.netcommon.network_cli
<10.241.0.59> Loading collection ansible.netcommon from /usr/lib/python3/dist-packages/ansible_collections/ansible/netcommon
<10.241.0.59> redirecting (type: terminal) ansible.builtin.routeros to community.routeros.routeros
<10.241.0.59> Loading collection community.routeros from /usr/lib/python3/dist-packages/ansible_collections/community/routeros
<10.241.0.59> redirecting (type: cliconf) ansible.builtin.routeros to community.routeros.routeros
<10.241.0.59> local domain socket listeners started successfully
<10.241.0.59> loaded cliconf plugin ansible_collections.community.routeros.plugins.cliconf.routeros from path /usr/lib/python3/dist-packages/ansible_collections/community/routeros/plugins/cliconf/routeros.py for network_os routeros
<10.241.0.59> ssh type is set to paramiko
<10.241.0.59>
<10.241.0.59> local domain socket path is /root/.ansible/pc/fdd8f497bd
<10.241.0.59> ESTABLISH LOCAL CONNECTION FOR USER: root
<10.241.0.59> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-local-4310zx41brjw `"&& mkdir "` echo /root/.ansible/tmp/ansible-local-4310zx41brjw/ansible-tmp-1638225568.5912402-4315-255970753186567 `" && echo ansible-tmp-1638225568.5912402-4315-255970753186567="` echo /root/.ansible/tmp/ansible-local-4310zx41brjw/ansible-tmp-1638225568.5912402-4315-255970753186567 `" ) && sleep 0'
redirecting (type: modules) ansible.builtin.routeros_command to community.routeros.command
Using module file /usr/lib/python3/dist-packages/ansible_collections/community/routeros/plugins/modules/command.py
<10.241.0.59> PUT /root/.ansible/tmp/ansible-local-4310zx41brjw/tmp5hvwxkg5 TO /root/.ansible/tmp/ansible-local-4310zx41brjw/ansible-tmp-1638225568.5912402-4315-255970753186567/AnsiballZ_command.py
<10.241.0.59> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-local-4310zx41brjw/ansible-tmp-1638225568.5912402-4315-255970753186567/ /root/.ansible/tmp/ansible-local-4310zx41brjw/ansible-tmp-1638225568.5912402-4315-255970753186567/AnsiballZ_command.py && sleep 0'
<10.241.0.59> EXEC /bin/sh -c '/usr/bin/python3 /root/.ansible/tmp/ansible-local-4310zx41brjw/ansible-tmp-1638225568.5912402-4315-255970753186567/AnsiballZ_command.py && sleep 0'
<10.241.0.59> EXEC /bin/sh -c 'rm -f -r /root/.ansible/tmp/ansible-local-4310zx41brjw/ansible-tmp-1638225568.5912402-4315-255970753186567/ > /dev/null 2>&1 && sleep 0'
ok: [SW1] => {
    "changed": false,
    "invocation": {
        "module_args": {
            "commands": [
                "/tool fetch address=10.10.72.2 src-path=/srv/ftp/enable-dhcp-snooping-crs326.rsc user=user password=xxxxx dst-path=enable-dhcp-snooping-crs326.rsc port=21 mode=ftp /import enable-dhcp-snooping-crs326.rsc"
            ],
            "interval": 1,
            "match": "all",
            "retries": 10,
            "wait_for": null
        }
    },
    "stdout": [
        "/tool fetch address=10.10.72.2 src-path=/srv/ftp/en\n<address=10.10.72.2 src-path=/srv/ftp/ena                                      \n<address=10.10.72.2 src-path=/srv/ftp/enable-dhcp-snooping-crs326.rsc user=netb\n<address=10.10.72.2 src-path=/srv/ftp/enable-dhcp-snooping-crs326.rsc user=net>\n<able-dhcp-snooping-crs326.rsc user=netbl                                      \n<able-dhcp-snooping-crs326.rsc user=user password=xxxxx dst-path=e\n<able-dhcp-snooping-crs326.rsc user=user password=xxxxx dst-path=>\n<lazr password=xxxxx dst-path=en                                      \n<lazr password=xxxxx dst-path=enable-dhcp-snooping-crs326.rsc port=21 \n<lazr password=xxxxx dst-path=enable-dhcp-snooping-crs326.rsc port=21>\n<nable-dhcp-snooping-crs326.rsc port=21 m                                      \n<nable-dhcp-snooping-crs326.rsc port=21 mode=ftp /import enable-dhcp-snooping-c\n<nable-dhcp-snooping-crs326.rsc port=21 mode=ftp /import enable-dhcp-snooping->\n<mode=ftp /import enable-dhcp-snooping-cr                                      \n<mode=ftp /import enable-dhcp-snooping-crs326.rsc\n<mode=ftp /import enable-dhcp-snooping-crs326.rsc\n\nexpected end of command (line 1 column 186)"
    ],
    "stdout_lines": [
        [
            "/tool fetch address=10.10.72.2 src-path=/srv/ftp/en",
            "<address=10.10.72.2 src-path=/srv/ftp/ena                                      ",
            "<address=10.10.72.2 src-path=/srv/ftp/enable-dhcp-snooping-crs326.rsc user=netb",
            "<address=10.10.72.2 src-path=/srv/ftp/enable-dhcp-snooping-crs326.rsc user=net>",
            "<able-dhcp-snooping-crs326.rsc user=netbl                                      ",
            "<able-dhcp-snooping-crs326.rsc user=user password=xxxxx dst-path=e",
            "<able-dhcp-snooping-crs326.rsc user=user password=xxxxx dst-path=>",
            "<lazr password=xxxxx dst-path=en                                      ",
            "<lazr password=xxxxx dst-path=enable-dhcp-snooping-crs326.rsc port=21 ",
            "<lazr password=xxxxx dst-path=enable-dhcp-snooping-crs326.rsc port=21>",
            "<nable-dhcp-snooping-crs326.rsc port=21 m                                      ",
            "<nable-dhcp-snooping-crs326.rsc port=21 mode=ftp /import enable-dhcp-snooping-c",
            "<nable-dhcp-snooping-crs326.rsc port=21 mode=ftp /import enable-dhcp-snooping->",
            "<mode=ftp /import enable-dhcp-snooping-cr                                      ",
            "<mode=ftp /import enable-dhcp-snooping-crs326.rsc",
            "<mode=ftp /import enable-dhcp-snooping-crs326.rsc",
            "",
            "expected end of command (line 1 column 186)"
        ]
    ]
}
META: ran handlers
META: ran handlers

PLAY RECAP ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
SW1                        : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

[API] incorrect task execution status

SUMMARY

routeros_api always returns the OK status, even if an error actually occurred.

Related issue

Try to add a simple rule of the form:

  community.routeros.api:
    hostname: "{{ mikrotik_host }}"
    username: "{{ mikrotik_user }}"
    password: "{{ mikrotik_password }}"
    path: ip firewall filter
    add: action=accept chain=forward comment='accept in ipsec policy' ipsec-policy=in,ipsec

Result is OK, but details contains error:

ok: [localhost] => (item={'comment': 'accept in ipsec policy', 'id': 6, 'action': 'accept', 'chain': 'forward', 'options': 'ipsec-policy=in,ipsec'}) => {
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "add": "action=accept chain=forward comment='accept in ipsec policy' ipsec-policy=in,ipsec",  <<< here
            "cmd": null,
            "hostname": "10.0.0.1",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "path": "ip firewall filter",
            "port": null,
            "query": null,
            "remove": null,
            "ssl": false,
            "update": null,
            "username": "ansible"
        }
    },
    "item": {
        "action": "accept",
        "chain": "forward",
        "comment": "accept in ipsec policy",
        "ipsec-policy: "in,ipsec"
    },
    "msg": [
        "missing '=' after 'in'"  <<< here

Attention! This works not only with comments, but also if an invalid argument is specified or something similar. The result always looks like a success, but an error actually occurred, example:

rly, ok? >>> ok: [localhost] => (item={'comment': 'desktop', 'address': '10.0.0.11', 'mac': 'XX:XX:XX:XX:XX:XX'}) => {
    "ansible_loop_var": "item",
    "changed": false,
    "invocation": {
        "module_args": {
            "add": "address=10.0.0.11 mac=XX:XX:XX:XX:XX:XX comment=desktop disabled=no",
            "cmd": null,
            "hostname": "10.0.0.1",
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "path": "ip dhcp-server lease",
            "port": null,
            "query": null,
            "remove": null,
            "ssl": false,
            "update": null,
            "username": "ansible"
        }
    },
    "item": {
        "address": "10.0.0.11",
        "comment": "desktop",
        "mac": "XX:XX:XX:XX:XX:XX"
    },
    "msg": [
        "unknown parameter"  <<< mac is incorrect arg, correct: mac-address, but task result is OK
    ]
}
ISSUE TYPE
  • Bug Report
COMPONENT NAME

routeros_api

ANSIBLE VERSION

2.9.*
2.10.*

COLLECTION VERSION

latest

STEPS TO REPRODUCE

see issue #44

New task module for configuring

SUMMARY

Add a new task module that makes it easier to idempotently modify RouterOS config.

ISSUE TYPE
  • Feature Idea
COMPONENT NAME
ADDITIONAL INFORMATION

Currently, it's a huge PITA to idemtpotently modify RouterOS config. My roles have RouterOS script snippets like this all over the place, to be executed via CLI:

:if ([/ip firewall filter find chain=forward action=fasttrack-connection] = "") do={/ip firewall filter add chain=forward action=fasttrack-connection connection-state=established,related ipsec-policy=out,none} else={/ip firewall filter set [find chain=forward action=fasttrack-connection] ipsec-policy=out,none}

This looks for a firewall rule in the forward chain with action "fasttrack-connection". If it finds such a rule, it sets "ipsec-policy=out,none" on it. If it doesn't find such a rule, it adds one.

Obviously it's quite impossible to catch all edge cases (especially ordering etc.), because RouterOS config is damn complex. But I'd imagine something like this:

- community.routeros.config:
    path: /ip firewall filter
    attributes:
      chain: forward
      action: fasttrack-connection
      connection-state: established,related
      ipsec-policy: out,none
    match:
      - chain
      - action

One could also think about adding more parameters, like "place-before" (ideally accepting something like [find ...]), which would obviously only be used for adding, not for updating.

Also, this would make check mode and proper change detection possible.

Or is there a more elegant way to do this?

/tool romon set id conflict with api .id

SUMMARY

RouterOS api use '.id' for configuration item identify, however routeros configuration also contain 'id' as configuration parameter.
For example /tool romon set id=

Currently RouterOS API module have a specific check if 'id' is exactly '.id' in order to be sure will do the correct api call however this do a conflict with routeros configuration parameters.

"msg": [
    "**'id' must be '.id**'"
]
ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.routeros.api

ANSIBLE VERSION
ansible 2.10.3
  config file = /opt/gitea/ansible/ansible.cfg
  configured module search path = ['/opt/gitea/ansible/library']
  ansible python module location = /usr/local/lib/python3.7/dist-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.7.3 (default, Jul 25 2020, 13:03:44) [GCC 8.3.0]
STEPS TO REPRODUCE
---
- name: configure tool romon
  community.routeros.api:
    hostname: "{{ ros_hostname }}"
    ssl: "{{ ros_ssl }}"
    password: "{{ ros_password }}"
    username: "{{ ros_username }}"
    path: "{{ ros_tool_romon_path }}"
    cmd:
      set
      enabled={{ ros_tool_romon_enabled }}
      secrets={{ ros_tool_romon_secrets }}
      id={{ ros_tool_romon_id }}
  register: toolromon
  delegate_to: localhost

- name: result configure tool romon
  debug:
    msg: "{{ toolromon }}"
EXPECTED RESULTS

no msg should be return
"msg": []

ACTUAL RESULTS
    "changed": false,
    "invocation": {
        "module_args": {
            "add": null,
            "cmd": "set enabled=yes secrets= id=00:00:00:00:00:00",
            "hostname": "ros1",
            "password": "",
            "path": "tool romon",
            "port": null,
            "query": null,
            "remove": null,
            "ssl": true,
            "update": null,
            "username": "admin"
        }
    },
    "msg": [
        "'id' must be '.id'"
    ]
}

Error when run ansible playbook fatal: [router]: FAILED! => {"changed": false, "msg": "'int' object has no attribute 'encode'"}

SUMMARY

Hello, when trying to run playbook from tutorial on two Mikrotik devices with different ROS (6 and 7), the playbook ends with an error.
Run it on two diffrent mashines: Ubuntu 22.04.2 (SRV1) and Ubuntu server 20.04.6 (SRV2)

ISSUE TYPE
  • Bug Report
COMPONENT NAME

ansible.netcommon.network_cli
community.routeros.routeros

ANSIBLE VERSION
SRV1:
ansible [core 2.14.4]
  config file = /home/tolliik/devops/ansible/playbooks/ansible.cfg
  configured module search path = ['/home/tolliik/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/tolliik/.local/lib/python3.10/site-packages/ansible
  ansible collection location = /home/tolliik/.ansible/collections
  executable location = /home/tolliik/.local/bin/ansible
  python version = 3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0] (/usr/bin/python3)
  jinja version = 3.1.2
  libyaml = True

SRV2:
ansible [core 2.13.8]
  config file = /home/tolliik/playbooks/ansible.cfg
  configured module search path = ['/home/tolliik/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/tolliik/.local/lib/python3.8/site-packages/ansible
  ansible collection location = /home/tolliik/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/tolliik/.local/bin/ansible
  python version = 3.8.10 (default, Mar 13 2023, 10:26:41) [GCC 9.4.0]
  jinja version = 3.1.2
  libyaml = True

COLLECTION VERSION

Outpoot of ansible-galaxy collection list ansible.netcommon (I got the same error when the version was only one)

SRV1:
# /home/tolliik/.local/lib/python3.10/site-packages/ansible_collections
Collection        Version
----------------- -------
ansible.netcommon 4.1.0  

# /home/tolliik/.ansible/collections/ansible_collections
Collection        Version
----------------- -------
ansible.netcommon 5.1.1  

SRV2:
# /usr/lib/python3/dist-packages/ansible_collections
Collection        Version
----------------- -------
ansible.netcommon 2.6.1  

# /home/tolliik/.local/lib/python3.8/site-packages/ansible_collections
Collection        Version
----------------- -------
ansible.netcommon 3.1.3  

# /usr/local/lib/python3.8/dist-packages/ansible_collections
Collection        Version
----------------- -------
ansible.netcommon 3.1.3  

# /home/tolliik/.ansible/collections/ansible_collections
Collection        Version
----------------- -------
ansible.netcommon 5.1.1


CONFIGURATION
SRV1:
COLLECTIONS_PATHS(/home/tolliik/devops/ansible/playbooks/ansible.cfg) = ['/home/tolliik/.ansible/collections']
CONFIG_FILE() = /home/tolliik/devops/ansible/playbooks/ansible.cfg
DEFAULT_DEBUG(env: ANSIBLE_DEBUG) = True
DEFAULT_LOG_PATH(env: ANSIBLE_LOG_PATH) = /home/tolliik/ansible.log
PARAMIKO_HOST_KEY_AUTO_ADD(/home/tolliik/devops/ansible/playbooks/ansible.cfg) = True
SRV2:
PARAMIKO_HOST_KEY_AUTO_ADD(/home/tolliik/playbooks/ansible.cfg) = True

OS / ENVIRONMENT

Mikrotik ROS 6.49.8 and Mikrotik ROS 7.9

STEPS TO REPRODUCE

hosts file:
[routers]
router ansible_host=192.168.1.34

[routers:vars]
ansible_connection=ansible.netcommon.network_cli
ansible_network_os=community.routeros.routeros
ansible_user=*********
ansible_ssh_pass=********

---
- name: RouterOS test with network_cli connection
  hosts: routers
  gather_facts: false
  tasks:

  - name: Gather system resources
    community.routeros.command:
      commands:
        - /system resource print
    register: system_resource_print

  - name: Show system resources
    debug:
      var: system_resource_print.stdout_lines

  - name: Gather facts
    community.routeros.facts:

  - name: Show a fact
    debug:
      msg: "First IP address: {{ ansible_net_all_ipv4_addresses[0] }}"
EXPECTED RESULTS
PLAY [RouterOS test with network_cli connection] *****************************************************************

TASK [Gather system resources] ***********************************************************************************
ok: [router]

TASK [Show system resources] *************************************************************************************
ok: [router] => {
    "system_resource_print.stdout_lines": [
        [
            "uptime: 3d10h28m51s",
            "                  version: 6.48.3 (stable)",
            "               build-time: May/25/2021 06:09:45",
            "              free-memory: 31.2MiB",
            "             total-memory: 64.0MiB",
            "                      cpu: MIPS 24Kc V7.4",
            "                cpu-count: 1",
            "            cpu-frequency: 400MHz",
            "                 cpu-load: 1%",
            "           free-hdd-space: 54.2MiB",
            "          total-hdd-space: 128.0MiB",
            "  write-sect-since-reboot: 927",
            "         write-sect-total: 51572981",
            "               bad-blocks: 1%",
            "        architecture-name: mipsbe",
            "               board-name: RB750GL",
            "                 platform: MikroTik"
        ]
    ]
}

TASK [Gather facts] **********************************************************************************************
ok: [router]

TASK [Show a fact] ***********************************************************************************************
ok: [router] => {
    "msg": "First IP address: 192.168.2.1"
}

PLAY RECAP *******************************************************************************************************
router                     : ok=4    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
ACTUAL RESULTS

For example from SRV2

ansible-playbook [core 2.13.8]
  config file = /home/tolliik/playbooks/ansible.cfg
  configured module search path = ['/home/tolliik/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/tolliik/.local/lib/python3.8/site-packages/ansible
  ansible collection location = /home/tolliik/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/tolliik/.local/bin/ansible-playbook
  python version = 3.8.10 (default, Mar 13 2023, 10:26:41) [GCC 9.4.0]
  jinja version = 3.1.2
  libyaml = True
Using /home/tolliik/playbooks/ansible.cfg as config file
setting up inventory plugins
host_list declined parsing /home/tolliik/playbooks/hosts as it did not pass its verify_file() method
script declined parsing /home/tolliik/playbooks/hosts as it did not pass its verify_file() method
auto declined parsing /home/tolliik/playbooks/hosts as it did not pass its verify_file() method
Parsed /home/tolliik/playbooks/hosts inventory source with ini plugin
Loading collection community.routeros from /home/tolliik/.ansible/collections/ansible_collections/community/routeros
Loading callback plugin default of type stdout, v2.0 from /home/tolliik/.local/lib/python3.8/site-packages/ansible/plugins/callback/default.py
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: mikrotik.yml ************************************************************************************************************************************************
Positional arguments: mikrotik.yml
verbosity: 4
connection: smart
timeout: 10
become_method: sudo
tags: ('all',)
inventory: ('/home/tolliik/playbooks/hosts',)
forks: 5
1 plays in mikrotik.yml

PLAY [RouterOS test with network_cli connection] **********************************************************************************************************************
META: ran handlers

TASK [Gather system resources] ****************************************************************************************************************************************
task path: /home/tolliik/playbooks/mikrotik.yml:7
Loading collection ansible.netcommon from /home/tolliik/.ansible/collections/ansible_collections/ansible/netcommon
Loading collection ansible.utils from /home/tolliik/.ansible/collections/ansible_collections/ansible/utils
<192.168.1.34> attempting to start connection
<192.168.1.34> using connection plugin ansible.netcommon.network_cli
Found ansible-connection at path /home/tolliik/.local/bin/ansible-connection
<192.168.1.34> local domain socket does not exist, starting it
<192.168.1.34> control socket path is /home/tolliik/.ansible/pc/e93e03f2f2
<192.168.1.34> Loading collection ansible.netcommon from /home/tolliik/.ansible/collections/ansible_collections/ansible/netcommon
<192.168.1.34> Loading collection ansible.utils from /home/tolliik/.ansible/collections/ansible_collections/ansible/utils
<192.168.1.34> Loading collection community.routeros from /home/tolliik/.ansible/collections/ansible_collections/community/routeros
<192.168.1.34> local domain socket listeners started successfully
<192.168.1.34> loaded cliconf plugin ansible_collections.community.routeros.plugins.cliconf.routeros from path /home/tolliik/.ansible/collections/ansible_collections/community/routeros/plugins/cliconf/routeros.py for network_os community.routeros.routeros
<192.168.1.34> ssh type is set to auto
<192.168.1.34> autodetecting ssh_type
<192.168.1.34> ssh type is now set to libssh
<192.168.1.34> 
<192.168.1.34> local domain socket path is /home/tolliik/.ansible/pc/e93e03f2f2
<192.168.1.34> ESTABLISH LOCAL CONNECTION FOR USER: tolliik
<192.168.1.34> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/tolliik/.ansible/tmp/ansible-local-57510kjlf8v61 `"&& mkdir "` echo /home/tolliik/.ansible/tmp/ansible-local-57510kjlf8v61/ansible-tmp-1685096668.4424844-57515-191673264017952 `" && echo ansible-tmp-1685096668.4424844-57515-191673264017952="` echo /home/tolliik/.ansible/tmp/ansible-local-57510kjlf8v61/ansible-tmp-1685096668.4424844-57515-191673264017952 `" ) && sleep 0'
Using module file /home/tolliik/.ansible/collections/ansible_collections/community/routeros/plugins/modules/command.py
<192.168.1.34> PUT /home/tolliik/.ansible/tmp/ansible-local-57510kjlf8v61/tmp8r6nxezx TO /home/tolliik/.ansible/tmp/ansible-local-57510kjlf8v61/ansible-tmp-1685096668.4424844-57515-191673264017952/AnsiballZ_command.py
<192.168.1.34> EXEC /bin/sh -c 'chmod u+x /home/tolliik/.ansible/tmp/ansible-local-57510kjlf8v61/ansible-tmp-1685096668.4424844-57515-191673264017952/ /home/tolliik/.ansible/tmp/ansible-local-57510kjlf8v61/ansible-tmp-1685096668.4424844-57515-191673264017952/AnsiballZ_command.py && sleep 0'
<192.168.1.34> EXEC /bin/sh -c '/usr/bin/python3 /home/tolliik/.ansible/tmp/ansible-local-57510kjlf8v61/ansible-tmp-1685096668.4424844-57515-191673264017952/AnsiballZ_command.py && sleep 0'
<192.168.1.34> EXEC /bin/sh -c 'rm -f -r /home/tolliik/.ansible/tmp/ansible-local-57510kjlf8v61/ansible-tmp-1685096668.4424844-57515-191673264017952/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
  File "/tmp/ansible_community.routeros.command_payload_aheplf2u/ansible_community.routeros.command_payload.zip/ansible_collections/community/routeros/plugins/module_utils/routeros.py", line 51, in get_capabilities
    capabilities = Connection(module._socket_path).get_capabilities()
  File "/tmp/ansible_community.routeros.command_payload_aheplf2u/ansible_community.routeros.command_payload.zip/ansible/module_utils/connection.py", line 200, in __rpc__
    raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code)
fatal: [router]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "commands": [
                "/system resource print"
            ],
            "interval": 1,
            "match": "all",
            "retries": 10,
            "wait_for": null
        }
    },
    "msg": "'int' object has no attribute 'encode'"
}

PLAY RECAP ************************************************************************************************************************************************************
router                     : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0 

"msg": "Unexpected failure during module execution: too many values to unpack (expected 2)"

SUMMARY

I can not use routeros module with my current config, I'm getting an unexpected failure.
I can connect via SSH from my Ubuntu to RouterOS.

ISSUE TYPE
  • Bug Report
COMPONENT NAME
ANSIBLE VERSION
ansible [core 2.14.6]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/ivan/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/ivan/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/ivan/.local/bin/ansible
  python version = 3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0] (/usr/bin/python3)
  jinja version = 3.0.3
  libyaml = True

COLLECTION VERSION
Collection         Version
------------------ -------
community.routeros 2.8.0 
CONFIGURATION
[defaults]
inventory=/etc/ansible/hosts
deprecation_warnings=False

[inventory]
enable_plugins = yaml, ini

OS / ENVIRONMENT

Ubuntu 22.04.2 LTS
RouterOS 7.10rc1 and also on 6.48.7

STEPS TO REPRODUCE

ansible-playbook -vvvv routeros-playbook.yml --inventory /etc/ansible/hosts --extra-vars "ansible_user=admin ansible_network_os=routeros ansible_become=yes ansible_become_method=enable"

---

- hosts: mikrotiks
  connection: network_cli
  gather_facts: false

  tasks:

    - name: Display resource statistics (routeros)
      routeros_command:
        commands: 
          - /system resource print
      register: routeros_resources

EXPECTED RESULTS
ACTUAL RESULTS
ansible-playbook [core 2.14.6]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/ivan/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3/dist-packages/ansible
  ansible collection location = /home/ivan/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/ivan/.local/bin/ansible-playbook
  python version = 3.10.6 (main, Mar 10 2023, 10:55:28) [GCC 11.3.0] (/usr/bin/python3)
  jinja version = 3.0.3
  libyaml = True
Using /etc/ansible/ansible.cfg as config file
setting up inventory plugins
[WARNING]:  * Failed to parse /etc/ansible/hosts with yaml plugin: We were unable to read either as JSON nor YAML, these are the errors we got from each: JSON: Expecting value: line 1 column 2 (char 1)  Syntax
Error while loading YAML.   did not find expected <document start>  The error appears to be in '/etc/ansible/hosts': line 2, column 1, but may be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:  [mikrotiks] server1 ansible_host=127.0.0.1 ^ here
  File "/usr/lib/python3/dist-packages/ansible/inventory/manager.py", line 293, in parse_source
    plugin.parse(self._inventory, self._loader, source, cache=cache)
  File "/usr/lib/python3/dist-packages/ansible/plugins/inventory/yaml.py", line 107, in parse
    raise AnsibleParserError(e)
[WARNING]:  * Failed to parse /etc/ansible/hosts with ini plugin: /etc/ansible/hosts:4: Section [mikrotiks:var] has unknown type: var
  File "/usr/lib/python3/dist-packages/ansible/inventory/manager.py", line 293, in parse_source
    plugin.parse(self._inventory, self._loader, source, cache=cache)
  File "/usr/lib/python3/dist-packages/ansible/plugins/inventory/ini.py", line 137, in parse
    raise AnsibleParserError(e)
[WARNING]: Unable to parse /etc/ansible/hosts as an inventory source
[WARNING]: No inventory was parsed, only implicit localhost is available
[WARNING]: provided hosts list is empty, only localhost is available. Note that the implicit localhost does not match 'all'
redirecting (type: modules) ansible.builtin.routeros_command to community.routeros.command
Loading collection community.routeros from /home/ivan/.ansible/collections/ansible_collections/community/routeros
Loading callback plugin default of type stdout, v2.0 from /usr/lib/python3/dist-packages/ansible/plugins/callback/default.py
Skipping callback 'default', as we already have a stdout callback.
Skipping callback 'minimal', as we already have a stdout callback.
Skipping callback 'oneline', as we already have a stdout callback.

PLAYBOOK: routeros-playbook.yml ***********************************************************************************************************************************************************************************
Positional arguments: routeros-playbook.yml
verbosity: 4
connection: smart
timeout: 10
become_method: sudo
tags: ('all',)
inventory: ('/etc/ansible/hosts',)
extra_vars: ('ansible_user=admin ansible_network_os=routeros',)
forks: 5
1 plays in routeros-playbook.yml

PLAY [mikrotiks] **************************************************************************************************************************************************************************************************

TASK [Display resource statistics (routeros)] *********************************************************************************************************************************************************************
task path: /home/ivan/routeros-playbook.yml:9
redirecting (type: connection) ansible.builtin.network_cli to ansible.netcommon.network_cli
Loading collection ansible.netcommon from /home/ivan/.ansible/collections/ansible_collections/ansible/netcommon
Loading collection ansible.utils from /home/ivan/.ansible/collections/ansible_collections/ansible/utils
redirecting (type: terminal) ansible.builtin.routeros to community.routeros.routeros
redirecting (type: cliconf) ansible.builtin.routeros to community.routeros.routeros
<127.0.0.1> attempting to start connection
<127.0.0.1> using connection plugin ansible.netcommon.network_cli
Found ansible-connection at path /home/ivan/.local/bin/ansible-connection
The full traceback is:
Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/ansible/executor/task_executor.py", line 158, in run
    res = self._execute()
  File "/usr/lib/python3/dist-packages/ansible/executor/task_executor.py", line 580, in _execute
    socket_path = start_connection(self._play_context, options, self._task._uuid)
  File "/usr/lib/python3/dist-packages/ansible/executor/task_executor.py", line 1221, in start_connection
    for level, message in result['messages']:
ValueError: too many values to unpack (expected 2)
fatal: [server1]: FAILED! => {
    "msg": "Unexpected failure during module execution: too many values to unpack (expected 2)",
    "stdout": ""
}

PLAY RECAP ********************************************************************************************************************************************************************************************************
server1                    : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0   
  


Multiple routers, one playbook.

Hi everyone,

I would like to hear if someone can assist with an example of executing commands with the community.routeros.api module to multiple routers with 1 inventry file. I looked through the examples but it seems that you have to specify the ip of the router in each play.

Hope this is enough info.

Regards
Ryan

Prompt matching issue

SUMMARY

Issues with parenthesis in host name. Can't match any promt, so every command fails with timeout triggered.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

routeros

ANSIBLE VERSION
ansible 2.9.15
  config file = /home/sfinx/ansible/mikrotik/base_config/ansible.cfg
  configured module search path = [u'/home/sfinx/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/dist-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.16 (default, Oct 10 2019, 22:02:15) [GCC 8.3.0]
CONFIGURATION
no changes
OS / ENVIRONMENT
STEPS TO REPRODUCE

Add to inventory two identical routeros host.
In one host set identity to something with parenthesis

/system identity set name="12(13)"
---
- name: RouterOS testing
  hosts: all
  gather_facts: false
  tasks:

    - name: Do nothing
      community.routeros.command:
        commands:
          - /
EXPECTED RESULTS

Normal run

ACTUAL RESULTS
PLAY [RouterOS testing] *******************************************************************************************************************************************************************

TASK [Do nothing] *************************************************************************************************************************************************************************
ok: [10.0.151.135]
fatal: [10.0.255.50]: FAILED! => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "msg": "command timeout triggered, timeout value is 60 secs.\nSee the timeout setting options in the Network Debug and Troubleshooting Guide."}

PLAY RECAP ********************************************************************************************************************************************************************************
10.0.151.135               : ok=1    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0
10.0.255.50                : ok=0    changed=0    unreachable=0    failed=1    skipped=0    rescued=0    ignored=0

Add ~ option to routeros.api query parameter

SUMMARY

Add ~ option to routeros.api query parameter

https://docs.ansible.com/ansible/latest/collections/community/routeros/api_module.html#ansible-collections-community-routeros-api-module

The current documenation says: "WHERE valid operators are ==, !=, >, <."

But I would like to gather information from files using CONTAINS (~) operator.

e.g /file print where contents~"blaah"

ISSUE TYPE
  • Feature Idea
COMPONENT NAME

Update the already existing module.

ADDITIONAL INFORMATION

I want to search if a ssh pubkey file is present in the system. Ofcourse I could delete the previous one, but I would like to check its contents, and searching the contents with the full == operator is not viable. Also the mikrotik search seems to "brake" when it encounters a weird character.

[root@blaah] > /file print where contents~"ssh-rsa blaah+n"
 # NAME                                                                                                                        TYPE                                                                                                                             SIZE CREATION-TIME       
[root@blaah] > /file print where contents~"ssh-rsa blaah+" 
 # NAME                                                                                                                        TYPE                                                                                                                             SIZE CREATION-TIME       
 0 flash/blaah.pub                                                                                                          ssh key                                                                                                                           739 nov/01/2021 12:26:50

As you can see if I add anything after the + the search will break, even though the next letter is correct. Something to keep in mind.

api_modify: Some routes shows "changed" when they shouldn't

SUMMARY

Some routes (I currently experiencing this only in ip dhcp-client, but there can be more) show changed, when there actually no changes. For example when I executing the following task muliple times:

- name: Set DHCP client
  community.routeros.api_modify:
    path: ip dhcp-client
    data:
      - interface: ether1
        add-default-route: True
        default-route-distance: 1
        disabled: false
        use-peer-dns: True
        use-peer-ntp: True
        dhcp-options: ""

it always shows changed status, when no actually changes are performed (it is visible when enabling verbose output and comparing old_data and new_data)

ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.routeros.api_modify

ANSIBLE VERSION
ansible [core 2.14.1]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python3.10/site-packages/ansible
  ansible collection location = /usr/share/ansible/collections
  executable location = /usr/bin/ansible
  python version = 3.10.9 (main, Dec 19 2022, 17:35:49) [GCC 12.2.0] (/usr/bin/python)
  jinja version = 3.1.2
  libyaml = True
COLLECTION VERSION
Collection         Version
------------------ -------
community.routeros 2.5.0  
CONFIGURATION

OS / ENVIRONMENT
  • Control host:
    • OS: Arch Linux
    • Python version: 3.10.9
  • Mikrotik RouterOS 7.7
STEPS TO REPRODUCE

Run a playbook with the task that modifies ip dhcp-client path of Mikrotik router

- name: Set DHCP client
  community.routeros.api_modify:
    path: ip dhcp-client
    data:
      - interface: ether1
        add-default-route: True
        default-route-distance: 1
        disabled: false
        use-peer-dns: True
        use-peer-ntp: True
        dhcp-options: ""
EXPECTED RESULTS

The status of task should be ok, not changed when applying the same configuration

ACTUAL RESULTS
PLAY RECAP *************
localhost                  : ok=0    changed=1

api_modify: Suspected strange beheviour of the `match_entries` and `essentially_same_weight` methods

Hello,
Maybe I am wrong but I find the behaviour of the match_entries and essentially_same_weight methods strange.

Context:

I have a set of RouterOS devices and I'm trying to manage a set of default firewall filter rules for those devices.
As the requirement for those devices may vary it's required to be able to add some custom rules manually (managed by local admin)

Problem:

As explained in the Context I can enabled "handle_absent_entries=remove" for those firewall filters as it will remove all the custom rules.

So in the method match_entries it falls in the else which uses the essentially_same_weight method.

def match_entries(new_entries, old_entries, path_info, module):
    matching_old_entries = [None for entry in new_entries]
    old_entries = list(old_entries)
    matches = []
    handle_absent_entries = module.params['handle_absent_entries']
    if handle_absent_entries == 'remove':
        for new_index, (unused, new_entry) in enumerate(new_entries):
            for old_index, (unused, old_entry) in enumerate(old_entries):
                modifications, unused = find_modifications(old_entry, new_entry, path_info, module, return_none_instead_of_fail=True)
                if modifications is not None:
                    matches.append((new_index, old_index, len(modifications)))
    else:
        for new_index, (unused, new_entry) in enumerate(new_entries):
            for old_index, (unused, old_entry) in enumerate(old_entries):
                weight = essentially_same_weight(old_entry, new_entry, path_info, module)
                if weight is not None:
                    matches.append((new_index, old_index, weight))
    matches.sort(key=lambda entry: entry[2])
    for new_index, old_index, rating in matches:
        if matching_old_entries[new_index] is not None or old_entries[old_index] is None:
            continue
        matching_old_entries[new_index], old_entries[old_index] = old_entries[old_index], None
    unmatched_old_entries = [index_entry for index_entry in old_entries if index_entry is not None]
    return matching_old_entries, unmatched_old_entries

My problems are the following one :

when adding a new "field"

The method essentially_same_weight return None and the method match_entries put it in the unmatched_old_entries collection which cause the creation of a new entry (firewall filter row)

when removing a "field"

If handle_entries_content is set to ignore this field will be ignored and remains in the router configuration
If handle_entries_content is set to something else than ignore then a new entry (firewall filter row) because the method return None as for the 'adding a new field' case.

def essentially_same_weight(old_entry, new_entry, path_info, module):
    for k, v in new_entry.items():
        if k == '.id':
            continue
        disabled_k = None
        if k.startswith('!'):
            disabled_k = k[1:]
        elif v is None or v == path_info.fields[k].remove_value:
            disabled_k = k
        if disabled_k is not None:
            if disabled_k in old_entry:
                return None
            continue
        if k not in old_entry and path_info.fields[k].default == v:
            continue
        if k not in old_entry or old_entry[k] != v:
            return None
    handle_entries_content = module.params['handle_entries_content']
    weight = 0
    for k in old_entry:
        if k == '.id' or k in new_entry or ('!%s' % k) in new_entry or k not in path_info.fields:
            continue
        field_info = path_info.fields[k]
        if field_info.default is not None and field_info.default == old_entry[k]:
            continue
        if handle_entries_content != 'ignore':
            return None
        else:
            weight += 1
    return weight

Am I doing something wrong?

Thanks for you support.

"move" command into RouterOS via api

Hi everyone,

I can't figure out how to implement the following command using Community.Routeros (it's important to use the api instead of ssh):
/radius move [/radius find address={{RADIUS_SERVER}}] destination=0
I know how to do add, remove, update, query via API, but I don't know how to do move.
Help please

Hope this is enough info.

Regards
Ilya

Empty passwords causes module to fail authentication

SUMMARY

When Mikrotiks come out of the box, they do not have a password. In order to do automatic provisioning, I need this module to be able to handle empty string passwords. The fix seems to be an adjustment to the call to paramiko.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.routeros.command

ANSIBLE VERSION
ansible 2.9.12
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/sutley/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/sutley/.local/lib/python3.6/site-packages/ansible
  executable location = /home/sutley/.local/bin/ansible
  python version = 3.6.9 (default, Oct  8 2020, 12:12:24) [GCC 8.4.0]

CONFIGURATION
HOST_KEY_CHECKING(/etc/ansible/ansible.cfg) = False
OS / ENVIRONMENT

Ubuntu

STEPS TO REPRODUCE
  1. Configure inventory for mikrotik host with a password = ""
- hosts: CPE
  become: yes
  gather_facts: no
  become_method: enable
  connection: ansible.netcommon.network_cli
  environment:
    remote_tmp: /
  tasks:
    - name: Display resource statistics (routeros)
      community.network.routeros_command:
        commands: /system resource print
      register: routeros_resources
    - debug:
        var: routeros_resources
EXPECTED RESULTS

Output the resources

ACTUAL RESULTS

Depends on if you provide a empty string password or not. If you don't then you get auth failure, if you do you get no existing session

sutley@netbox:/optimizing_cpes/ansible$ ansible-playbook -i netbox_inventory.yml ./routeros.yml -e "ansible_network_os=routeros ansible_password=" -vvv
ansible-playbook 2.9.12
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/sutley/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/sutley/.local/lib/python3.6/site-packages/ansible
  executable location = /home/sutley/.local/bin/ansible-playbook
  python version = 3.6.9 (default, Oct  8 2020, 12:12:24) [GCC 8.4.0]
Using /etc/ansible/ansible.cfg as config file
host_list declined parsing /optimizing_cpes/ansible/netbox_inventory.yml as it did not pass its verify_file() method
script declined parsing /optimizing_cpes/ansible/netbox_inventory.yml as it did not pass its verify_file() method
Fetching: https://172.16.100.56/api/dcim/sites/?limit=0
Fetching: https://172.16.100.56/api/dcim/regions/?limit=0
Fetching: https://172.16.100.56/api/tenancy/tenants/?limit=0
Fetching: https://172.16.100.56/api/dcim/racks/?limit=0
Fetching: https://172.16.100.56/api/dcim/device-roles/?limit=0
Fetching: https://172.16.100.56/api/dcim/platforms/?limit=0
Fetching: https://172.16.100.56/api/dcim/device-types/?limit=0
Fetching: https://172.16.100.56/api/dcim/manufacturers/?limit=0
Fetching: https://172.16.100.56/api/dcim/devices/?limit=0
Fetching: https://172.16.100.56/api/virtualization/virtual-machines/?limit=0
Parsed /optimizing_cpes/ansible/netbox_inventory.yml inventory source with auto plugin

PLAYBOOK: routeros.yml *************************************************************************************************************
1 plays in ./routeros.yml

PLAY [AUTOCPE] *********************************************************************************************************************
META: ran handlers

TASK [Display resource statistics (routeros)] **************************************************************************************
task path: /optimizing_cpes/ansible/routeros.yml:9
<192.168.255.3> ESTABLISH LOCAL CONNECTION FOR USER: sutley
<192.168.255.3> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/sutley/.ansible/tmp/ansible-local-99849lt4dzhe `"&& mkdir "` echo /home/sutley/.ansible/tmp/ansible-local-99849lt4dzhe/ansible-tmp-1604963164.6908667-9998-224365925208779 `" && echo ansible-tmp-1604963164.6908667-9998-224365925208779="` echo /home/sutley/.ansible/tmp/ansible-local-99849lt4dzhe/ansible-tmp-1604963164.6908667-9998-224365925208779 `" ) && sleep 0'
<AUTOCPE> Attempting python interpreter discovery
<192.168.255.3> EXEC /bin/sh -c 'echo PLATFORM; uname; echo FOUND; command -v '"'"'/usr/bin/python'"'"'; command -v '"'"'python3.7'"'"'; command -v '"'"'python3.6'"'"'; command -v '"'"'python3.5'"'"'; command -v '"'"'python2.7'"'"'; command -v '"'"'python2.6'"'"'; command -v '"'"'/usr/libexec/platform-python'"'"'; command -v '"'"'/usr/bin/python3'"'"'; command -v '"'"'python'"'"'; echo ENDFOUND && sleep 0'
<192.168.255.3> EXEC /bin/sh -c '/usr/bin/python && sleep 0'
Using module file /home/sutley/.ansible/collections/ansible_collections/community/network/plugins/modules/routeros_command.py
<192.168.255.3> PUT /home/sutley/.ansible/tmp/ansible-local-99849lt4dzhe/tmp_tyn5d4x TO /home/sutley/.ansible/tmp/ansible-local-99849lt4dzhe/ansible-tmp-1604963164.6908667-9998-224365925208779/AnsiballZ_routeros_command.py
<192.168.255.3> EXEC /bin/sh -c 'chmod u+x /home/sutley/.ansible/tmp/ansible-local-99849lt4dzhe/ansible-tmp-1604963164.6908667-9998-224365925208779/ /home/sutley/.ansible/tmp/ansible-local-99849lt4dzhe/ansible-tmp-1604963164.6908667-9998-224365925208779/AnsiballZ_routeros_command.py && sleep 0'
<192.168.255.3> EXEC /bin/sh -c 'remote_tmp=/ /usr/bin/python /home/sutley/.ansible/tmp/ansible-local-99849lt4dzhe/ansible-tmp-1604963164.6908667-9998-224365925208779/AnsiballZ_routeros_command.py && sleep 0'
<192.168.255.3> EXEC /bin/sh -c 'rm -f -r /home/sutley/.ansible/tmp/ansible-local-99849lt4dzhe/ansible-tmp-1604963164.6908667-9998-224365925208779/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
WARNING: The below traceback may *not* be related to the actual failure.
  File "/tmp/ansible_community.network.routeros_command_payload_1eNpxa/ansible_community.network.routeros_command_payload.zip/ansible_collections/community/network/plugins/module_utils/network/routeros/routeros.py", line 74, in get_capabilities
    capabilities = Connection(module._socket_path).get_capabilities()
  File "/tmp/ansible_community.network.routeros_command_payload_1eNpxa/ansible_community.network.routeros_command_payload.zip/ansible/module_utils/connection.py", line 185, in __rpc__
    raise ConnectionError(to_text(msg, errors='surrogate_then_replace'), code=code)
[DEPRECATION WARNING]: Distribution Ubuntu 18.04 on host AUTOCPE should use /usr/bin/python3, but is using /usr/bin/python for
backward compatibility with prior Ansible releases. A future Ansible release will default to using the discovered platform python
for this host. See https://docs.ansible.com/ansible/2.9/reference_appendices/interpreter_discovery.html for more information. This
feature will be removed in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
fatal: [AUTOCPE]: FAILED! => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "invocation": {
        "module_args": {
            "commands": [
                "/system resource print"
            ],
            "interval": 1,
            "match": "all",
            "retries": 10,
            "wait_for": null
        }
    },
    "msg": "No existing session"
}

file set command issue (asks for '=')

SUMMARY

Hello!

I try upload ssh public key to the mikrotik (RouterOS v7.6 stable) in the following way:

    - name: Generate empty ssh pub key
      community.routeros.api:
        path: "file"
        cmd: "print file=id_rsa.pub"

    - name: Put content to the ssh pub key
      community.routeros.api:
        path: "file"
        cmd: 'set id_rsa.pub.txt contents="{{ ssh_pub_key }}"'

The following error has appeared:

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ansible_collections.community.routeros.plugins.module_utils.quoting.ParseError: missing '=' after 'id_rsa.pub.txt'

Under routeros cli comannds:

/file print file=id_rsa.pub
/file set id_rsa.pub.txt contents="test"

work as expected.

Any help will be appreciated.

regards
Serhiy.

ISSUE TYPE
  • Bug Report
COMPONENT NAME

community.routeros.api

ANSIBLE VERSION
ansible [core 2.14.4]
  config file = /Users/gray/projects/ansible/routers/ansible.cfg
  configured module search path = ['/Users/gray/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /Users/gray/projects/ansible/venv/lib/python3.9/site-packages/ansible
  ansible collection location = /Users/gray/.ansible/collections:/usr/share/ansible/collections
  executable location = /Users/gray/projects/ansible/venv/bin/ansible
  python version = 3.9.6 (default, Mar 10 2023, 20:16:38) [Clang 14.0.3 (clang-1403.0.22.14.1)] (/Users/gray/projects/ansible/venv/bin/python)
  jinja version = 3.1.2
  libyaml = True
COLLECTION VERSION
ansible-galaxy collection list community.routeros

# ~/.ansible/collections/ansible_collections
Collection         Version
------------------ -------
community.routeros 2.8.0

# ~/projects/ansible/venv/lib/python3.9/site-packages/ansible_collections
Collection         Version
------------------ -------
community.routeros 2.8.0
CONFIGURATION
CONFIG_FILE() = ~/projects/ansible/routers/ansible.cfg
DEFAULT_HOST_LIST(~/projects/ansible/routers/ansible.cfg) = ['/Users/gray/projects/ansible/routers/hosts.yml']
OS / ENVIRONMENT

ProductName: macOS
ProductVersion: 13.3.1
BuildVersion: 22E261

STEPS TO REPRODUCE
    - name: Generate empty ssh pub key
      community.routeros.api:
        path: "file"
        cmd: "print file=id_rsa.pub"
    - name: Put content to the ssh pub key
      community.routeros.api:
        path: "file"
        cmd: 'set id_rsa.pub.txt contents="{{ ssh_pub_key }}"'
EXPECTED RESULTS

Contents from variable should be placed into the file.

ACTUAL RESULTS

An exception occurred during task execution. To see the full traceback, use -vvv. The error was: ansible_collections.community.routeros.plugins.module_utils.quoting.ParseError: missing '=' after 'id_rsa.pub.txt'

TASK [Put content to the ssh pub key] *************************************************************************************************************
fatal: [mikrotik]: FAILED! => {"changed": false, "module_stderr": "Traceback (most recent call last):\n  File \"~//.ansible/tmp/ansible-local-22960vt0f6yot/ansible-tmp-1681564975.694714-23025-254122928642250/AnsiballZ_api.py\", line 107, in <module>\n    _ansiballz_main()\n  File \"~//.ansible/tmp/ansible-local-22960vt0f6yot/ansible-tmp-1681564975.694714-23025-254122928642250/AnsiballZ_api.py\", line 99, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"~//.ansible/tmp/ansible-local-22960vt0f6yot/ansible-tmp-1681564975.694714-23025-254122928642250/AnsiballZ_api.py\", line 47, in invoke_module\n    runpy.run_module(mod_name='ansible_collections.community.routeros.plugins.modules.api', init_globals=dict(_module_fqn='ansible_collections.community.routeros.plugins.modules.api', _modlib_path=modlib_path),\n  File \"/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/runpy.py\", line 210, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/runpy.py\", line 97, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/Library/Developer/CommandLineTools/Library/Frameworks/Python3.framework/Versions/3.9/lib/python3.9/runpy.py\", line 87, in _run_code\n    exec(code, run_globals)\n  File \"/var/folders/p2/xtr9ql715bd78nvs0v71x25m0000gn/T/ansible_community.routeros.api_payload_n8r02h0l/ansible_community.routeros.api_payload.zip/ansible_collections/community/routeros/plugins/modules/api.py\", line 577, in <module>\n  File \"/var/folders/p2/xtr9ql715bd78nvs0v71x25m0000gn/T/ansible_community.routeros.api_payload_n8r02h0l/ansible_community.routeros.api_payload.zip/ansible_collections/community/routeros/plugins/modules/api.py\", line 573, in main\n  File \"/var/folders/p2/xtr9ql715bd78nvs0v71x25m0000gn/T/ansible_community.routeros.api_payload_n8r02h0l/ansible_community.routeros.api_payload.zip/ansible_collections/community/routeros/plugins/modules/api.py\", line 365, in __init__\n  File \"/var/folders/p2/xtr9ql715bd78nvs0v71x25m0000gn/T/ansible_community.routeros.api_payload_n8r02h0l/ansible_community.routeros.api_payload.zip/ansible_collections/community/routeros/plugins/modules/api.py\", line 547, in api_arbitrary\n  File \"/var/folders/p2/xtr9ql715bd78nvs0v71x25m0000gn/T/ansible_community.routeros.api_payload_n8r02h0l/ansible_community.routeros.api_payload.zip/ansible_collections/community/routeros/plugins/modules/api.py\", line 414, in list_to_dic\n  File \"/var/folders/p2/xtr9ql715bd78nvs0v71x25m0000gn/T/ansible_community.routeros.api_payload_n8r02h0l/ansible_community.routeros.api_payload.zip/ansible_collections/community/routeros/plugins/module_utils/quoting.py\", line 201, in convert_list_to_dictionary\nansible_collections.community.routeros.plugins.module_utils.quoting.ParseError: missing '=' after 'id_rsa.pub.txt'\n", "module_stdout": "", "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error", "rc": 1}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.