0

I'm creating a playbook where I query some NetBox child prefixes and then use the ID of each child prefix to look up the available IP's in each one (This doesn't exist in the netbox.netbox module).

To do this, I used nb_lookup to return the IDs of each child prefix, and then I used ansible's own URI module to query the NetBox API (api/ipam/prefixes//available-ips/) and return the available IP.

My difficulty is querying all the IDs, one at a time, as I need to get the first available IP from the queried prefixes.

I'm new to YAML development, and I don't really know how to do this. Here is my code:

---
- name: NetBox
  hosts: localhost
  connection: local
  gather_facts: no
  collections:
    - netbox.netbox
  tasks:

    - name: "Get Prefixes"
      set_fact:
        prefixes: "{{ query('netbox.netbox.nb_lookup', 'prefixes',
                  api_endpoint='https://url-from-my-nb',
                  api_filter='role=valid status=active',
                  validate_certs=False,
                  token='myToken') }}"


    - name: Teste
      debug:
        msg: "{{ prefixes | json_query('[*].value.id') }}"

    - name: Teste 2
      uri:
        validate_certs: False
        url: "https://url-from-my-nb/api/ipam/prefixes/{{ prefixes | json_query('[*].value.id') }}/available-ips/"
        headers:
          Authorization: "Token myToken"
      register: prefix
      until: prefix

    - name: Teste
      debug:
        msg: "{{ prefix.json[0].address }}"

Result:

PLAY [NetBox] *********************************************************************************************************************************************************************************

TASK [Get Prefixes] *******************************************************************************************************************************************************************************************
/usr/local/lib/python3.9/site-packages/urllib3/connectionpool.py:1045: InsecureRequestWarning: Unverified HTTPS request is being made to host 'url-from-my-nb'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/1.26.x/advanced-usage.html#ssl-warnings
  warnings.warn(
ok: [localhost]

TASK [Teste] **************************************************************************************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        2,
        4,
        5,
        6,
        11,
        7,
        8,
        10,
        12,
        13,
        14,
        15,
        16,
        17,
        18,
        19,
        20,
        21,
        22,
        23,
        24,
        25,
        26,
        27,
        29,
        51,
        52,
        28
    ]
}

TASK [Teste 2] ************************************************************************************************************************************************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: http.client.InvalidURL: URL can't contain control characters. '/api/ipam/prefixes/[2, 4, 5, 6, 11, 7, 8, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 51, 52, 28]/available-ips/' (found at least ' ')
fatal: [localhost]: FAILED! => {"attempts": 1, "changed": false, "elapsed": 0, "msg": "Status code was -1 and not [200]: An unknown error occurred: URL can't contain control characters. '/api/ipam/prefixes/[2, 4, 5, 6, 11, 7, 8, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 51, 52, 28]/available-ips/' (found at least ' ')", "redirected": false, "status": -1, "url": "https://ipam.getcard.com.br/api/ipam/prefixes/[2, 4, 5, 6, 11, 7, 8, 10, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 51, 52, 28]/available-ips/"}

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

How can I loop to query one ID at a time and check if there is an available IP for it?

1 Answers1

0

use a loop to revise all the items in the variable:

    - name: Teste 2
      ansible.builtin.uri:
        validate_certs: false
        url: "https://url-from-my-nb/api/ipam/prefixes/{{ item }}/available-ips/"
        headers:
          Authorization: "Token myToken"
      register: prefix
      with_items: "{{ prefixes | json_query('[*].value.id') }}"


Edit: Adding example of how to group and process each result

In this case, it will be needed to group some tasks and apply it for each one of the results obtained with the IP addresses, one way to do it is to set the loop in an include_tasks task:

  1. Separate the tasks that need to be grouped in a different YAML file, let's name it assign_ip.yaml
---
# Content of assign_ip.yaml
- name: Set the variable with the value received
  ansible.builtin.set_fact:
    prefix_ip: "{{ item }}"

- name: Teste 2
  ansible.builtin.uri:
    validate_certs: false
    url: "https://url-from-my-nb/api/ipam/prefixes/{{ prefix_ip }}/available-ips/"
    headers:
      Authorization: "Token myToken"
  register: prefix

- name: Teste
  ansible.builtin.debug:
    msg: "{{ prefix.json[0].address }}"
...

  1. In the original playbook, execute those tasks
- name: NetBox
  hosts: localhost
  connection: local
  gather_facts: false
  collections:
    - netbox.netbox
  tasks:

    - name: "Get Prefixes"
      ansible.builtin.set_fact:
        prefixes: "{{ query('netbox.netbox.nb_lookup', 'prefixes',
                  api_endpoint='https://url-from-my-nb',
                  api_filter='role=valid status=active',
                  validate_certs=False,
                  token='myToken') }}"


    - name: Teste
      ansible.builtin.debug:
        msg: "{{ prefixes | json_query('[*].value.id') }}"

    - name: Check IP
      ansible.builtin.include_tasks:
        file: "assign_ip.yaml"
      with_items: "{{ prefixes | json_query('[*].value.id') }}"
Carlos Monroy Nieblas
  • 2,225
  • 2
  • 16
  • 27
  • thanks, that works amazing, but now, i don't know how to capture the address information and stops the loop after the first has finded. "{{ prefix.json[0].address }}" not works anymore, i have this issue: ` fatal: [localhost]: FAILED! => {"msg": "The task includes an option with an undefined variable. The error was: 'prefix' is undefined\n\nThe error appears to be in '/data/projects/vmware/prefix.yaml': line 32, column 7, but may\nbe elsewhere in the file depending on the exact syntax problem.\n\nThe offending line appears to be:\n\n\n - name: Teste\n ^ here\n"} ` – Renan Delfino Jan 09 '23 at 16:35