netbox-community / ansible_modules

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

[Bug]: Invalid value when adding power_outlet_template #1115

Open an-ky opened 12 months ago

an-ky commented 12 months ago

Ansible NetBox Collection version

3.15.0

Ansible version

ansible [core 2.14.6]
  config file = /home/an-ky/projects/infrastructure/ansible/ansible.cfg
  configured module search path = ['/home/an-ky/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/an-ky/.virtualenvs/venv-ansible/lib/python3.10/site-packages/ansible
  ansible collection location = /home/an-ky/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/an-ky/.virtualenvs/venv-ansible/bin/ansible
  python version = 3.10.12 (main, Jun 11 2023, 05:26:28) [GCC 11.4.0] (/home/an-ky/.virtualenvs/venv-ansible/bin/python3)
  jinja version = 3.1.2
  libyaml = True

NetBox version

v3.6.4

Python version

3.10

Steps to Reproduce

Running the following playbook

- name: Setup Netbox
  hosts: localhost
  connection: local
  gather_facts: false

  vars:
    netbox_url: "http://localhost:8000"
    netbox_token: <your_token_here>

  tasks:
    - name: "Devices | add manufacturer"
      netbox.netbox.netbox_manufacturer:
        netbox_url: "{{ netbox_url }}"
        netbox_token: "{{ netbox_token }}"
        data:
          name: "other"
          description: "Acme Crazy Gear"

    - name: "Devices | add device type"
      netbox.netbox.netbox_device_type:
        netbox_url: "{{ netbox_url }}"
        netbox_token: "{{ netbox_token }}"
        data:
          model: Simple PDU
          manufacturer: "other"
          is_full_depth: false

    - name: "Devices | add interface template"
      netbox.netbox.netbox_device_interface_template:
        netbox_url: "{{ netbox_url }}"
        netbox_token: "{{ netbox_token }}"
        data:
          name: eth1
          type: 1000base-t
          mgmt_only: true
          device_type: Simple PDU

    - name: "Devices | add power port template"
      netbox.netbox.netbox_power_port_template:
        netbox_url: "{{ netbox_url }}"
        netbox_token: "{{ netbox_token }}"
        data:
          name: input
          type: iec-60309-2p-e-4h
          device_type: Simple PDU

    - name: "Devices | add power outlets"
      netbox.netbox.netbox_power_outlet_template:
        netbox_url: "{{ netbox_url }}"
        netbox_token: "{{ netbox_token }}"
        data:
          name: "C19-1"
          type: "iec-60320-c19"
          power_port_template: "input"
          feed_leg: "A"
          device_type: Simple PDU

Expected Behavior

A device type should be created with an interface template named eth1, a power port template named input and a power outlet template named C19-19

Observed Behavior

ansible playbook returns an error when creating the power_outlet_template

$ ansible-playbook netbox_bug_power_outlet_template.yaml 
[WARNING]: Found variable using reserved name: connection

PLAY [Setup Netbox] *********************************************************************************************************************************************************************************************************************************************************************************************

TASK [Devices | add manufacturer] *******************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Devices | add device type] ********************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Devices | add interface template] *************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Devices | add power port template] ************************************************************************************************************************************************************************************************************************************************************************
ok: [localhost]

TASK [Devices | add power outlets] ******************************************************************************************************************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {
    "changed": false
}

MSG:

{"devicetype_id":["“simple-pdu” is not a valid value."]}

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

The interface and power port templates are properly created, but using the model name as device_type when creating power_outlet_templates produces an error. When using the device_type id, the power_outlet_template is properly created.

sc68cal commented 12 months ago

@k-304 can you take a look at this since you were in that code area recently and have the expertise?

sc68cal commented 12 months ago

@an-ky what is the slug for the Simple PDU in NetBox? It does not appear to match simple-pdu so that's why you're getting the error.

an-ky commented 12 months ago

@an-ky what is the slug for the Simple PDU in NetBox? It does not appear to match simple-pdu so that's why you're getting the error.

The slug is auto-generated and seems to be correct. This is what the API returns for GET /api/dcim/device-types/

HTTP 200 OK
Allow: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "count": 1,
    "next": null,
    "previous": null,
    "results": [
        {
            "id": 27,
            "url": "http://localhost:8000/api/dcim/device-types/27/",
            "display": "Simple PDU",
            "manufacturer": {
                "id": 14,
                "url": "http://localhost:8000/api/dcim/manufacturers/14/",
                "display": "other",
                "name": "other",
                "slug": "other"
            },
            "default_platform": null,
            "model": "Simple PDU",
            "slug": "simple-pdu",
            "part_number": "",
            "u_height": 1.0,
            "is_full_depth": false,
            "subdevice_role": null,
            "airflow": null,
            "weight": null,
            "weight_unit": null,
            "front_image": null,
            "rear_image": null,
            "description": "",
            "comments": "",
            "tags": [],
            "custom_fields": {},
            "created": "2023-11-08T22:21:50.158844Z",
            "last_updated": "2023-11-08T22:21:50.158857Z",
            "device_count": 0,
            "console_port_template_count": 0,
            "console_server_port_template_count": 0,
            "power_port_template_count": 1,
            "power_outlet_template_count": 0,
            "interface_template_count": 1,
            "front_port_template_count": 0,
            "rear_port_template_count": 0,
            "device_bay_template_count": 0,
            "module_bay_template_count": 0,
            "inventory_item_template_count": 0
        }
    ]
}
sc68cal commented 12 months ago

I think it's this section of code? https://github.com/netbox-community/ansible_modules/blob/159f30927d184d1850518c04bf659cae3758d8d1/plugins/module_utils/netbox_utils.py#L1039

k-304 commented 12 months ago

@k-304 can you take a look at this since you were in that code area recently and have the expertise?

I'll try to take a 1st look in the next 1 or 2 weeks.

an-ky commented 12 months ago

As it just happened: Adding front_port_template produces the same error, rear_port_template works properly.

k-304 commented 10 months ago

I could not replicate this issue, it seems to work for me: Create a device type -> create a power port template for that device type -> create a power outlet template for that device type with the previous created port template.

As code, (I did add some custom tests to the existing integration tests) this looks like:

- name: "POWER_PORT_TEMPLATE 0: Necessary info creation"
  netbox.netbox.netbox_power_port_template:
    netbox_url: http://localhost:32768
    netbox_token: 0123456789abcdef0123456789abcdef01234567
    data:
      name: Power Port Template
      device_type: Device Type Power Tests
      type: iec-60309-2p-e-4h
    state: present
  register: test_zero

- name: "POWER_OUTLET_TEMPLATE 1: Create with power port template"
  netbox.netbox.netbox_power_outlet_template:
    netbox_url: http://localhost:32768
    netbox_token: 0123456789abcdef0123456789abcdef01234567
    data:
      name: Power Outlet Template
      device_type: Device Type Power Tests
      power_port_template: Power Port Template
      type: "iec-60320-c19"
    state: present
  register: test_one

- name: "POWER_OUTLET_TEMPLATE 1: ASSERT - Create with power port template"
  assert:
    that:
      - test_one is changed

- name: "POWER_OUTLET_TEMPLATE 2: Create duplicate"
  netbox.netbox.netbox_power_outlet_template:
    netbox_url: http://localhost:32768
    netbox_token: 0123456789abcdef0123456789abcdef01234567
    data:
      name: Power Outlet Template
      device_type: Device Type Power Tests
      power_port_template: Power Port Template
      type: "iec-60320-c19"
    state: present
  register: test_two

- name: "POWER_OUTLET_TEMPLATE 2: ASSERT - Create duplicate"
  assert:
    that:
      - test_two is not changed

- name: "POWER_OUTLET_TEMPLATE 3: Update power_outlet_template with other fields"
  netbox.netbox.netbox_power_outlet_template:
    netbox_url: http://localhost:32768
    netbox_token: 0123456789abcdef0123456789abcdef01234567
    data:
      name: Power Outlet Template
      device_type: Device Type Power Tests
      type: "iec-60320-c19"
      feed_leg: B
    state: present
  register: test_three

- name: "POWER_OUTLET_TEMPLATE 3: ASSERT - Update power_outlet_template with other fields"
  assert:
    that:
      - test_three is changed

- fail:

And the Ansible output to it is:

PLAY [testhost] ****************************************************************

TASK [Gathering Facts] *********************************************************
ok: [testhost]

TASK [v3.6 : NETBOX_POWER_OUTLET_TEMPLATE TESTS] *******************************
included: /home/user/code/work/sysmonkeys/sysmonkeys-ansible/ansible_collections/netbox/netbox/tests/output/.tmp/integration/v3.6-wv5_0efz-
 ÑŚÌβŁÈ/tests/integration/targets/v3.6/tasks/netbox_power_outlet_template.yml for testhost

TASK [v3.6 : POWER_PORT_TEMPLATE 0: Necessary info creation] *******************
changed: [testhost] => {"changed": true, "msg": "power_port_template Power Port Template created", "power_port_template": {"allocated_draw": null, "created": "2023-12-18T14:05:48.477537Z", "description": "", "device_type": 6, "display": "Power Port Template", "id": 9, "label": "", "last_updated": "2023-12-18T14:05:48.477547Z", "maximum_draw": null, "module_type": null, "name": "Power Port Template", "type": "iec-60309-2p-e-4h", "url": "http://localhost:32768/api/dcim/power-port-templates/9/"}}

TASK [v3.6 : POWER_OUTLET_TEMPLATE 1: Create with power port template] *********
changed: [testhost] => {"changed": true, "msg": "power_outlet_template Power Outlet Template created", "power_outlet_template": {"created": "2023-12-18T14:05:48.871963Z", "description": "", "device_type": 6, "display": "Power Outlet Template", "feed_leg": null, "id": 16, "label": "", "last_updated": "2023-12-18T14:05:48.871973Z", "module_type": null, "name": "Power Outlet Template", "power_port": 9, "type": "iec-60320-c19", "url": "http://localhost:32768/api/dcim/power-outlet-templates/16/"}}

TASK [v3.6 : POWER_OUTLET_TEMPLATE 1: ASSERT - Create with power port template] ***
ok: [testhost] => {
    "changed": false,
    "msg": "All assertions passed"
}

TASK [v3.6 : POWER_OUTLET_TEMPLATE 2: Create duplicate] ************************
ok: [testhost] => {"changed": false, "msg": "power_outlet_template Power Outlet Template already exists", "power_outlet_template": {"created": "2023-12-18T14:05:48.871963Z", "description": "", "device_type": 6, "display": "Power Outlet Template", "feed_leg": null, "id": 16, "label": "", "last_updated": "2023-12-18T14:05:48.871973Z", "module_type": null, "name": "Power Outlet Template", "power_port": 9, "type": "iec-60320-c19", "url": "http://localhost:32768/api/dcim/power-outlet-templates/16/"}}

TASK [v3.6 : POWER_OUTLET_TEMPLATE 2: ASSERT - Create duplicate] ***************
ok: [testhost] => {
    "changed": false,
    "msg": "All assertions passed"
}

TASK [v3.6 : POWER_OUTLET_TEMPLATE 3: Update power_outlet_template with other fields] ***
changed: [testhost] => {"changed": true, "msg": "power_outlet_template Power Outlet Template updated", "power_outlet_template": {"created": "2023-12-18T14:05:48.871963Z", "description": "", "device_type": 6, "display": "Power Outlet Template", "feed_leg": "B", "id": 16, "label": "", "last_updated": "2023-12-18T14:05:48.871973Z", "module_type": null, "name": "Power Outlet Template", "power_port": 9, "type": "iec-60320-c19", "url": "http://localhost:32768/api/dcim/power-outlet-templates/16/"}}

TASK [v3.6 : POWER_OUTLET_TEMPLATE 3: ASSERT - Update power_outlet_template with other fields] ***
ok: [testhost] => {
    "changed": false,
    "msg": "All assertions passed"
}

TASK [v3.6 : fail] *************************************************************
fatal: [testhost]: FAILED! => {"changed": false, "msg": "Failed as requested from task"}

GUI view after playbook with the newly created outlet: NetBox GUI Port Template

k-304 commented 10 months ago

I think it's this section of code?

https://github.com/netbox-community/ansible_modules/blob/159f30927d184d1850518c04bf659cae3758d8d1/plugins/module_utils/netbox_utils.py#L1039

Please see my comment above, this seems to work for me on 3.15.0 and NetBox 3.5 as well as v3.6.7.