theforeman / foreman-ansible-modules

Ansible modules for interacting with the Foreman API and various plugin APIs such as Katello
GNU General Public License v3.0
147 stars 163 forks source link

Problem serializing network in foreman_subnet #305

Closed nstrug closed 5 years ago

nstrug commented 5 years ago
SUMMARY

I get the following error when trying to create a subnet:

 "msg": "Error while creating Subnet: Object of type IPAddress is not JSON serializable"
ISSUE TYPE
ANSIBLE VERSION
$ ansible --version
ansible 2.7.10
  config file = /home/nstrug/projects/clone-satellite/ansible.cfg
  configured module search path = ['/home/nstrug/projects/clone-satellite/foreman-ansible-modules/modules']
  ansible python module location = /usr/lib/python3.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 3.7.3 (default, Mar 27 2019, 13:36:35) [GCC 9.0.1 20190227 (Red Hat 9.0.1-0.8)]
KATELLO/FOREMAN VERSION
# rpm -q tfm-rubygem-katello foreman
tfm-rubygem-katello-3.7.0.rc1.4-0.1.rc1.4.el7sat.noarch
foreman-1.18.0.1-1.el7sat.noarch
NAILGUN VERSION
$ pip3 show nailgun | grep Version
Version: 0.32.0

$ pip3 show netaddr | grep Version
Version: 0.7.19
STEPS TO REPRODUCE
- name: Generate Subnets
  foreman_subnet:
    server_url: "{{ target_foreman_server_url }}"
    username: "{{ target_foreman_username }}"
    password: "{{ target_foreman_password }}"
    verify_ssl: "{{ foreman_verify_ssl }}"
    name: "{{ item.Name }}"
    boot_mode: "{{ item['Boot Mode'] }}"
    cidr: "{{ item['Network Prefix'] }}"
    dhcp_proxy: "{{ inventory_hostname }}"
    dns_primary: "{{ item['Primary DNS'] }}"
    dns_secondary: "{{ item['Secondary DNS'] }}"
    dns_proxy: "{{ inventory_hostname }}"
    tftp_proxy: "{{ inventory_hostname }}"
    from_ip: "{{ item['Start of IP Range'] }}"
    to_ip: "{{ item['End of IP Range'] }}"
    gateway: "{{ item['Gateway Addr'] }}"
    ipam: "{{ (item.IPAM == 'None')|ternary(omit,item.IPAM) }}"
    mtu: "{{ item.MTU|int }}"
    vlanid: "{{ item['VLAN ID']|int }}"
    network_type: "{{ item.Protocol }}"
    network: "{{ item['Network Addr'] }}"
    domains: "{{ item.Domains | json_query('[*].Name') }}"
    organizations:
      - Default_Organization
    locations: "{{ item.Locations | json_query('[*].Name') }}"
    state: present
  loop: [{'Id': 1, 'Name': '192.168.0.0/24', 'Protocol': 'IPv4', 'Priority': None, 'Network Addr': '192.168.0.0', 'Network Prefix': 24, 'Network Mask': '255.255.255.0', 'Gateway Addr': '', 'Primary DNS': '', 'Secondary DNS': '', 'Smart Proxies': {'DNS': {}, 'TFTP': {'Name': 'sat62.oldstables', 'Id': 1}, 'DHCP': {}}, 'IPAM': 'None', 'Start of IP Range': '', 'End of IP Range': '', 'VLAN ID': None, 'MTU': 1500, 'Boot Mode': 'DHCP', 'Domains': [{'Name': 'oldstables', 'Id': 1}], 'Locations': [{'Name': 'Default_Location', 'Id': 2}], 'Organisations': [{'Name': 'Default_Organization', 'Id': 1}], 'Parameters': []}, {'Id': 2, 'Name': '192.168.100.0/24', 'Description': '', 'Protocol': 'IPv4', 'Priority': None, 'Network Addr': '192.168.100.0', 'Network Prefix': 24, 'Network Mask': '255.255.255.0', 'Gateway Addr': '192.168.100.1', 'Primary DNS': '192.168.100.10', 'Secondary DNS': '', 'Smart Proxies': {'DNS': {'Name': 'sat62.oldstables', 'Id': 1}, 'TFTP': {'Name': 'sat62.oldstables', 'Id': 1}, 'DHCP': {'Name': 'sat62.oldstables', 'Id': 1}}, 'IPAM': 'DHCP', 'Start of IP Range': '192.168.100.100', 'End of IP Range': '192.168.100.250', 'VLAN ID': None, 'MTU': 1500, 'Boot Mode': 'DHCP', 'Domains': [{'Name': 'libvirt.oldstables', 'Id': 3}], 'Locations': [{'Name': 'Default_Location', 'Id': 2}], 'Organisations': [{'Name': 'Default_Organization', 'Id': 1}], 'Parameters': []}]
  delegate_to: localhost
EXPECTED RESULTS

Create a new subnet.

ACTUAL RESULTS
The full traceback is:
  File "/tmp/ansible_foreman_subnet_payload_9kh9utu4/ansible_foreman_subnet_payload.zip/ansible/module_utils/ansible_nailgun_cement.py", line 178, in create_entity
    result = entity.create()
  File "/usr/local/lib/python3.7/site-packages/blinker_herald/base.py", line 137, in wrapper
    result = fn(*args, **kwargs)
  File "/usr/local/lib/python3.7/site-packages/nailgun/entity_mixins.py", line 964, in create
    return self.read(attrs=self.create_json(create_missing))
  File "/usr/local/lib/python3.7/site-packages/nailgun/entity_mixins.py", line 933, in create_json
    response = self.create_raw(create_missing)
  File "/usr/local/lib/python3.7/site-packages/nailgun/entity_mixins.py", line 918, in create_raw
    **self._server_config.get_client_kwargs()
  File "/usr/local/lib/python3.7/site-packages/nailgun/client.py", line 164, in post
    data = dumps(data)
  File "/usr/lib64/python3.7/json/__init__.py", line 231, in dumps
    return _default_encoder.encode(obj)
  File "/usr/lib64/python3.7/json/encoder.py", line 199, in encode
    chunks = self.iterencode(o, _one_shot=True)
  File "/usr/lib64/python3.7/json/encoder.py", line 257, in iterencode
    return _iterencode(o, 0)
  File "/usr/lib64/python3.7/json/encoder.py", line 179, in default
    raise TypeError(f'Object of type {o.__class__.__name__} '

failed: [sat63.nstrug.faa.redhat.com -> localhost] (item={'Id': 1, 'Name': '192.168.0.0/24', 'Protocol': 'IPv4', 'Priority': 'None', 'Network Addr': '192.168.0.0', 'Network Prefix': 24, 'Network Mask': '255.255.255.0', 'Gateway Addr': '', 'Primary DNS': '', 'Secondary DNS': '', 'Smart Proxies': {'DNS': {}, 'TFTP': {'Name': 'sat62.oldstables', 'Id': 1}, 'DHCP': {}}, 'IPAM': 'None', 'Start of IP Range': '', 'End of IP Range': '', 'VLAN ID': 'None', 'MTU': 1500, 'Boot Mode': 'DHCP', 'Domains': [{'Name': 'oldstables', 'Id': 1}], 'Locations': [{'Name': 'Default_Location', 'Id': 2}], 'Organisations': [{'Name': 'Default_Organization', 'Id': 1}], 'Parameters': []}) => {
    "changed": false,
    "invocation": {
        "module_args": {
            "boot_mode": "DHCP",
            "cidr": 24,
            "dhcp_proxy": "sat63.nstrug.faa.redhat.com",
            "discovery_proxy": null,
            "dns_primary": "",
            "dns_proxy": "sat63.nstrug.faa.redhat.com",
            "dns_secondary": "",
            "domains": [
                "oldstables"
            ],
            "from_ip": "",
            "gateway": "",
            "ipam": "DHCP",
            "locations": [
                "Default_Location"
            ],
            "mask": null,
            "mtu": 1500,
            "name": "192.168.0.0/24",
            "network": "192.168.0.0",
            "network_type": "IPv4",
            "organizations": [
                "Default_Organization"
            ],
            "remote_execution_proxies": null,
            "state": "present",
            "tftp_proxy": "sat63.nstrug.faa.redhat.com",
            "to_ip": "",
            "vlanid": 0
        }
    },
    "item": {
        "Boot Mode": "DHCP",
        "Domains": [
            {
                "Id": 1,
                "Name": "oldstables"
            }
        ],
        "End of IP Range": "",
        "Gateway Addr": "",
        "IPAM": "None",
        "Id": 1,
        "Locations": [
            {
                "Id": 2,
                "Name": "Default_Location"
            }
        ],
        "MTU": 1500,
        "Name": "192.168.0.0/24",
        "Network Addr": "192.168.0.0",
        "Network Mask": "255.255.255.0",
        "Network Prefix": 24,
        "Organisations": [
            {
                "Id": 1,
                "Name": "Default_Organization"
            }
        ],
        "Parameters": [],
        "Primary DNS": "",
        "Priority": "None",
        "Protocol": "IPv4",
        "Secondary DNS": "",
        "Smart Proxies": {
            "DHCP": {},
            "DNS": {},
            "TFTP": {
                "Id": 1,
                "Name": "sat62.oldstables"
            }
        },
        "Start of IP Range": "",
        "VLAN ID": "None"
    },
    "msg": "Error while creating Subnet: Object of type IPAddress is not JSON serializable"
evgeni commented 5 years ago

Thanks!

I can reproduce this with the following smaller example:

  - hosts: localhost
    tasks:
      - name: Generate Subnets
        foreman_subnet:
          server_url: "https://foreman.example.com"
          username: "admin"
          password: "changeme"
          verify_ssl: False
          name: "192.168.0.0/24"
          cidr: "24"
          network: "192.168.0.0"
          state: present
evgeni commented 5 years ago

And it works fine if I pass mask instead of cidr