You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ansible中循环调用NetBox API查询各前缀的可用IP?

解决Ansible循环查询NetBox前缀可用IP的问题

问题场景

编写Ansible Playbook时,需先查询NetBox中符合条件的子前缀ID,再逐个用这些ID调用NetBox API查询对应前缀的可用IP(该功能未包含在netbox.netbox模块中)。已通过nb_lookup获取到前缀ID列表,但直接将整个列表传入API URL导致格式错误,无法完成逐个查询。

原Playbook代码

---
- 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 }}"

错误执行结果

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

解决方案

核心是使用Ansible的loop指令遍历每个前缀ID,逐个发起API请求,同时添加容错和结果过滤逻辑。

修正后的Playbook代码

---
- 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: "Extract prefix IDs"
      set_fact:
        prefix_ids: "{{ prefixes | json_query('[*].value.id') }}"

    - name: "Query available IPs for each prefix"
      uri:
        validate_certs: False
        url: "https://url-from-my-nb/api/ipam/prefixes/{{ item }}/available-ips/"
        headers:
          Authorization: "Token myToken"
      register: prefix_available_ips
      loop: "{{ prefix_ids }}"
      # 忽略无可用IP的情况,避免任务失败
      failed_when: false
      changed_when: false

    - name: "Display available IPs"
      debug:
        msg: "Prefix ID {{ item.item }} has available IP: {{ item.json[0].address }}"
      loop: "{{ prefix_available_ips.results }}"
      # 只输出有可用IP的有效结果
      when: item.status == 200 and item.json | length > 0

关键修改说明

  • 单独提取ID列表:新增Extract prefix IDs任务,将前缀ID单独存入prefix_ids变量,简化后续循环逻辑。
  • 循环遍历每个ID:在uri任务中添加loop: "{{ prefix_ids }}",让每个ID单独传入API URL,解决列表格式导致的URL错误。
  • 容错处理:通过failed_when: false和changed_when: false,避免因单个前缀无可用IP导致整个任务失败。
  • 过滤有效结果:在debug任务中通过when条件,只输出HTTP状态码为200且返回IP列表非空的结果,减少无效输出。

内容的提问来源于stack exchange,提问作者Renan Delfino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 08:50:44