netbox-community / ansible_modules

NetBox modules for Ansible using Ansible Collections
GNU General Public License v3.0
333 stars 216 forks source link

[Bug]: netbox_module returns error "More than one result returned for module_bay" #1267

Open LoneSnowMonkey opened 5 months ago

LoneSnowMonkey commented 5 months ago

Ansible NetBox Collection version

v3.19.1

Ansible version

ansible [core 2.17.0]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/foouser/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/foouser/ansible/lib/python3.10/site-packages/ansible
  ansible collection location = /home/foouser/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/foouser/ansible/bin/ansible
  python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/home/foouser/ansible/bin/python3)
  jinja version = 3.1.2
  libyaml = True

NetBox version

v3.7.3

Python version

3.10

Steps to Reproduce

I hope this is not a misunderstanding. In the past I've wanted to use netbox ansible modules to 'insert' a module into a module bay on a device. And while we could create a module_bay and a module_type, there wasn't such functionality. I did it using the URI module, but it of course required some additional logic and was not idempotent without further steps. I perused updates and see the new (to me) netbox_module.

I spin up a playbook to test this as I am doing more of this sort of work this week. I've been modeling my Dell servers with a module bay called network card bay. This allows me to have the same model of server but to account for the fact that one might have been ordered with an installed 4 port Gb integrated NIC, whilst another might have pair of 10Gb SFP+ ports and a pair of gigabit. I poll the host during discovery, add the correct module, which then populates the appropriate network interfaces and such. Example playbook sanitized of details:

- name: Update network card module in host
  hosts: localhost
  gather_facts: false

  tasks:
    - name: Set facts
      set_fact:
        netbox_url: https://netbox.host
        netbox_token: redactedTokenStringfoobar

    - name: Update network bay module
      netbox.netbox.netbox_module:
        netbox_url: "{{ netbox_url }}"
        netbox_token: "{{ netbox_token }}"
        data:
          device:
            name: foo-device
          module_bay:
            name: network card bay
          module_type:
            manufacturer: Dell
            model: 4Gb NIC
          status: active
        state: present

Expected Behavior

I expected to see a Changed outcome to my playbook results and foo-device updated in network to now have a 4-port gigabit integrated network card, along with the new network interfaces.

Observed Behavior

My original problem was that I got state is present but all of the following are missing: status. I found this odd as I needed to have state present in my playbook to indicate whether or not the module should be in the given module bay. Status was not listed as a required field so I left it out originally. In Netbox 3.X there is no status to a module. I put the status as active and re-ran the playbook. Now I get the error More than one result returned for module_bay. This took me a bit to understand as I interpreted it to mean it searched all of the modules bays in foo-device and it found multiple with the name network card bay. That wasn't the case, of course. It wasn't until later that I realized looking through my nginx logs that theres a search for device with name foo-device and then a search for all module_bays with the name network card bay.

::ffff:192.168.1.1 - - [DATESTAMP] "GET /api/dcim/devices/?name=foo-dev&limit=0 HTTP/1.1" 200 2562 "-" "python-requests/2.31.0"
::ffff:192.168.1.1 - - [DATESTAMP] "GET /api/dcim/module-bays/?name=network+card+bay&limit=0 HTTP/1.1" 200 80993 "-" "python-requests/2.31.0"

I find this odd because, at least this is how I do it, I add module bays to device templates. I have one for iDRAC, a network card bay for the integrated NIC ordered for the machine. PCI slots. PSU slots. But they all have the same names in every device of that device type. Its network card bay not hostname's network card bay.

But that appears to be the source of the error, it's returning hundreds of results because I use that same module bay naming on every Dell server, regardless of model. But I've given it the host I am using.

I am unable to test against a Netbox 4.x server because of a different problem I am having. There I get Failed to establish connection to NetBox API when I talk to my 4.x dev server. Not sure why, the same token works from Postman. Added my $.02 to another open issue about this.

LoneSnowMonkey commented 5 months ago

To add to my earlier comment, I noticed module status in my 3.x installation, just not as 'up front' as it is in 4.x. The module documentation should be updated to say its a required field. Original, main issue of the module not working remains.

Timewarrener commented 3 months ago

Here to report the same issue. I have all my module bays listed the same for easy automation.

But found out that the module plugin searches all module bays before checking which device.

Timewarrener commented 3 months ago

So messing around with netbox's API I figured a way to get netbox to use a device specific module bay.

Not sure if this will work in the ansible galaxy collection

      module_bay:
        name: network card bay
        device__name: foo-device