首页 > 解决方案 > Ansible 循环遍历一组 dicts,注册该列表,然后打印特定的输出

问题描述

这是我想要做的。

  1. 使用内置网络模块登录网络交换机并发送命令。
  2. 将该命令注册为 var
  3. 打印该变量或在剧本内的其他地方使用该变量。

这看起来很简单吧?但这是我面临的问题。

首先,我正在登录一个设备(当前),然后在循环内发出一个简单的命令(这变成 2 个命令和 2 个输出)。

我想将两个命令的输出放入一个列表中。接下来我想遍历这个列表并检查每个命令的返回值(记住这是 2 个输出)。

这是当前的播放:

- name: Checking for free ports
  nxos_command: 
    provider: 
      host: "{{inventory_hostname}}" 
      username: "{{user.stdout}}"
    commands: "show run interface {{ item.interface }}"
  when: device.ansible_facts.ansible_device_os == 'nxos' 
  loop: "{{ device_vars[inventory_hostname] }}"
  register: ports

然后当我使用调试时,我得到一堆数据:

- debug: 
    var: item.stdout
  loop: "{{ports.results}}"
  register: ports_output

然后我设置事实,然后再次调试(打印):

- name: Setting var
  set_fact: 
    port_list: "{{item.stdout}}"
  loop: "{{ports.results}}"

- debug: var=port_list

我遇到的问题是,即使port_list是一个列表,ansible 也只返回该列表的一个值。这是初始播放的最后一个值/命令。所以我假设它在某处被覆盖。

这将是我想要的输出:

ok: [device1] => {
    "port_list": [
        "1st output from the device",
        "2nd output from the device"
    ]
}

但我能得到的只有这个:

ok: [device1] => {
    "port_list": [
        "2nd output from the device"
    ]
}

这是我在我的内部声明的变量site.yml

  vars:
    device_vars:
      device1:                                                                 
      - interface: Ethernet1/1
        description: "some description
        vlan: 1
      - interface: Ethernet1/2
        description: "some description"
        vlan: 1
    port_list: []

我认为我的问题是我正在使用列表等的字典,而 Ansible 似乎对此并不友好。我已经设法将数据转换成这种格式(省略):

{
"ports": 
    {
    "results": 
        [
            {
              "stdout": 
                [
                  "1st output from the device"
                ]
            },
            {
              "stdout":
                [
                  "2nd output from the device"
                ]
            } 
        ]
    }
}

我已经花了 3 天的时间,似乎无法找到解决方案。

标签: ansible

解决方案


在循环set_fact覆盖变量期间,您只会看到正在设置的最后一个变量。但是,您也可以使用set_fact附加先前分配的值并包括所有变量,如下所示:

- name: Setting var
  set_fact: 
    port_list: "{{ port_list|default([]) + [item.stdout] }}"
  loop: "{{ports.results}}"

default([])上面的过滤器是为port_list变量分配一个初始值。


推荐阅读