ansible-collections / community.routeros

Ansible modules for managing MikroTik RouterOS instances.
https://galaxy.ansible.com/ui/repo/published/community/routeros/
GNU General Public License v3.0
99 stars 45 forks source link

Confusion regarding supported keys #104

Closed travenec closed 2 years ago

travenec commented 2 years ago

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
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\"."
}
felixfontein commented 2 years ago

Thanks for creating this issue. This is exactly what I was hoping for when I wrote

Note that this module is still heavily in development, and only supports some paths. If you want to support new paths, or think you found problems with existing paths, please first create an issue in the community.routeros Issue Tracker.

in the documentation :-)

Unfortunately RouterOS is not very helpful to figure out all the available keys for all paths, that's why it's likely that some keys are missing for some paths - like this one. https://github.com/ansible-collections/community.routeros/blob/main/plugins/module_utils/_api_data.py#L765-L773 does not have domain. I will take a closer look at this and add this, but I won't get around to do that until in ~a week.

travenec commented 2 years ago

Thank you for the reply, Felix.

I read the note and I totally respect that. Again, very thankful for your work. The note is the reason I tried to humbly ask. I was also not able to find definition files you just pointed out (_api_data.py) to clarify my confusion.

Can I be anyhow helpful with fixing that? I guess adding a key to the python file and testing it is something I could manage...

There is also one other failure I experienced. Sorry for not filing it as another issue. I also tried to add ip dhcp-server lease records. This is in fact crutial for me. And that got even weirder:

The task:

    - name: "Test"
      community.routeros.api_modify:
        hostname: "{{ ansible_host }}"
        password: "{{ ansible_ssh_pass }}"
        username: "{{ ansible_user }}"
        path: ip dhcp-server lease
        data:
          - address: 10.0.0.1
            mac-address: 00:00:00:00:00:03
            server: all
          - address: 10.0.0.2
            mac-address: 00:00:00:00:00:08
            server: all

Response:

Loading collection ansible.netcommon from /Users/xxx/.ansible/collections/ansible_collections/ansible/netcommon
<10.56.155.254> attempting to start connection
<10.56.155.254> using connection plugin ansible.netcommon.network_cli
Found ansible-connection at path /usr/local/bin/ansible-connection
<10.56.155.254> local domain socket does not exist, starting it
<10.56.155.254> control socket path is /Users/xxx/.ansible/pc/677633fcf0
<10.56.155.254> Loading collection ansible.netcommon from /Users/xxx/.ansible/collections/ansible_collections/ansible/netcommon
<10.56.155.254> Loading collection community.routeros from /Users/xxx/.ansible/collections/ansible_collections/community/routeros
<10.56.155.254> local domain socket listeners started successfully
<10.56.155.254> loaded cliconf plugin ansible_collections.community.routeros.plugins.cliconf.routeros from path /Users/xxx/.ansible/collections/ansible_collections/community/routeros/plugins/cliconf/routeros.py for network_os community.routeros.routeros
<10.56.155.254> ssh type is set to auto
<10.56.155.254> autodetecting ssh_type
[WARNING]: ansible-pylibssh not installed, falling back to paramiko
<10.56.155.254> ssh type is now set to paramiko
<10.56.155.254> 
<10.56.155.254> local domain socket path is /Users/xxx/.ansible/pc/677633fcf0
<10.56.155.254> ESTABLISH LOCAL CONNECTION FOR USER: xxx
<10.56.155.254> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro `"&& mkdir "` echo /Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro/ansible-tmp-1659558679.8782232-83204-130921458741643 `" && echo ansible-tmp-1659558679.8782232-83204-130921458741643="` echo /Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro/ansible-tmp-1659558679.8782232-83204-130921458741643 `" ) && sleep 0'
Using module file /Users/xxx/.ansible/collections/ansible_collections/community/routeros/plugins/modules/api_modify.py
<10.56.155.254> PUT /Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro/tmp76zlz3_j TO /Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro/ansible-tmp-1659558679.8782232-83204-130921458741643/AnsiballZ_api_modify.py
<10.56.155.254> EXEC /bin/sh -c 'chmod u+x /Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro/ansible-tmp-1659558679.8782232-83204-130921458741643/ /Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro/ansible-tmp-1659558679.8782232-83204-130921458741643/AnsiballZ_api_modify.py && sleep 0'
<10.56.155.254> EXEC /bin/sh -c '/usr/local/Cellar/ansible/5.7.1/libexec/bin/python3.10 /Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro/ansible-tmp-1659558679.8782232-83204-130921458741643/AnsiballZ_api_modify.py && sleep 0'
<10.56.155.254> EXEC /bin/sh -c 'rm -f -r /Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro/ansible-tmp-1659558679.8782232-83204-130921458741643/ > /dev/null 2>&1 && sleep 0'
The full traceback is:
Traceback (most recent call last):
  File "/Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro/ansible-tmp-1659558679.8782232-83204-130921458741643/AnsiballZ_api_modify.py", line 107, in <module>
    _ansiballz_main()
  File "/Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro/ansible-tmp-1659558679.8782232-83204-130921458741643/AnsiballZ_api_modify.py", line 99, in _ansiballz_main
    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)
  File "/Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro/ansible-tmp-1659558679.8782232-83204-130921458741643/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/local/Cellar/python@3.10/3.10.4/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py", line 209, in run_module
    return _run_module_code(code, init_globals, run_name, mod_spec)
  File "/usr/local/Cellar/python@3.10/3.10.4/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py", line 96, in _run_module_code
    _run_code(code, mod_globals, init_globals,
  File "/usr/local/Cellar/python@3.10/3.10.4/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py", line 86, in _run_code
    exec(code, run_globals)
  File "/var/folders/62/x5knyvf90zq7kyv6wf8fv35w0000gn/T/ansible_community.routeros.api_modify_payload_5gpxy0k9/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py", line 918, in <module>
  File "/var/folders/62/x5knyvf90zq7kyv6wf8fv35w0000gn/T/ansible_community.routeros.api_modify_payload_5gpxy0k9/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py", line 914, in main
  File "/var/folders/62/x5knyvf90zq7kyv6wf8fv35w0000gn/T/ansible_community.routeros.api_modify_payload_5gpxy0k9/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py", line 664, in sync_with_primary_keys
  File "/var/folders/62/x5knyvf90zq7kyv6wf8fv35w0000gn/T/ansible_community.routeros.api_modify_payload_5gpxy0k9/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py", line 664, in <genexpr>
KeyError: 'server'
fatal: [gw]: FAILED! => {
    "changed": false,
    "module_stderr": "Traceback (most recent call last):\n  File \"/Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro/ansible-tmp-1659558679.8782232-83204-130921458741643/AnsiballZ_api_modify.py\", line 107, in <module>\n    _ansiballz_main()\n  File \"/Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro/ansible-tmp-1659558679.8782232-83204-130921458741643/AnsiballZ_api_modify.py\", line 99, in _ansiballz_main\n    invoke_module(zipped_mod, temp_path, ANSIBALLZ_PARAMS)\n  File \"/Users/xxx/.ansible/tmp/ansible-local-83193ia1285ro/ansible-tmp-1659558679.8782232-83204-130921458741643/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/local/Cellar/python@3.10/3.10.4/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py\", line 209, in run_module\n    return _run_module_code(code, init_globals, run_name, mod_spec)\n  File \"/usr/local/Cellar/python@3.10/3.10.4/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py\", line 96, in _run_module_code\n    _run_code(code, mod_globals, init_globals,\n  File \"/usr/local/Cellar/python@3.10/3.10.4/Frameworks/Python.framework/Versions/3.10/lib/python3.10/runpy.py\", line 86, in _run_code\n    exec(code, run_globals)\n  File \"/var/folders/62/x5knyvf90zq7kyv6wf8fv35w0000gn/T/ansible_community.routeros.api_modify_payload_5gpxy0k9/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py\", line 918, in <module>\n  File \"/var/folders/62/x5knyvf90zq7kyv6wf8fv35w0000gn/T/ansible_community.routeros.api_modify_payload_5gpxy0k9/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py\", line 914, in main\n  File \"/var/folders/62/x5knyvf90zq7kyv6wf8fv35w0000gn/T/ansible_community.routeros.api_modify_payload_5gpxy0k9/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py\", line 664, in sync_with_primary_keys\n  File \"/var/folders/62/x5knyvf90zq7kyv6wf8fv35w0000gn/T/ansible_community.routeros.api_modify_payload_5gpxy0k9/ansible_community.routeros.api_modify_payload.zip/ansible_collections/community/routeros/plugins/modules/api_modify.py\", line 664, in <genexpr>\nKeyError: 'server'\n",
    "module_stdout": "",
    "msg": "MODULE FAILURE\nSee stdout/stderr for the exact error",
    "rc": 1
}
felixfontein commented 2 years ago

106 adds support for the missing options in ip dhcp-server network.

felixfontein commented 2 years ago

The second error you are reporting seems to be that there is at least one DHCP lease on your router that does not have a server entry. From my understanding, that should not be possible. Can you do a /ip dhcp-server lease export verbose and check whether there are lines with no server?

travenec commented 2 years ago

@felixfontein, this is interesting. You are actually correct. There was an entry with server set to "all". Apperently, "all" means empty value, have a look:

[admin@MikroTik] > /ip dhcp-server lease export verbose
/ip dhcp-server lease
add address=10.0.0.1 address-lists="" dhcp-option="" disabled=no !insert-queue-before mac-address=00:00:00:00:00:03 server=test-dhcp1
add address=10.0.0.2 address-lists="" dhcp-option="" disabled=no !insert-queue-before mac-address=00:00:00:00:00:08

After deleting these entries it works. Setting server to "all" in playbook or in mikrotik breaks it. Gladly, this is not really common use case.

felixfontein commented 2 years ago

107 fixes the problem with server=all being absent.

felixfontein commented 2 years ago

2.2.1 is now out with fixes for these. I'm closing this. If there are other problems, please create a new issue, and if there are problems with the two problems mentioned in here, please comment here (then I'll reopen). Thanks :)