【问题标题】:loop with set_fact in ansible 2.13.2在 ansible 2.13.2 中使用 set_fact 循环
【发布时间】:2022-11-14 06:57:07
【问题描述】:

我有一个任务,我已经在使用并在 Ansible 版本中按预期工作。 2.9.17。然而,相同的任务在 2.13 版中表现不同。

我有以下循环的列表元素:

vlan_list: [
             "uni/tn-TST-CUSTOMER2/ap-TST-CUSTOMER2/epg-VLAN20"
             "uni/tn-TST-CUSTOMER1/ap-TST-CUSTOMER1/epg-VLAN10"
             "uni/tn-TST-CUSTOMER3/ap-TST-CUSTOMER3/epg-VLAN30"
           ]

任务本身如下:

- name: gather only IDs
  set_fact:
    epg_list: "{{ epg_list }} + [ '{{ item.split('/')[-1] | regex_replace('epg-VLAN') }}' ]"
  loop: "{{ vlan_list | flatten(levels=1) }}"
  when: vlan_list|length > 0

ansible v2.9 中上述任务的输出为:

ok: [my_host.com] => (item=uni/tn-TST-CUSTOMER2/ap-TST-CUSTOMER2/epg-VLAN20) => {
    "ansible_facts": {
        "epg_list": [
            "20"
        ]
    }, 
    "ansible_loop_var": "item", 
    "changed": false, 
    "item": "uni/tn-TST-CUSTOMER2/ap-TST-CUSTOMER2/epg-VLAN20"
}
ok: [my_host.com] => (item=uni/tn-TST-CUSTOMER1/ap-TST-CUSTOMER1/epg-VLAN10) => {
    "ansible_facts": {
        "epg_list": [
            "20", 
            "10"
        ]
    }, 
    "ansible_loop_var": "item", 
    "changed": false, 
    "item": "uni/tn-TST-CUSTOMER1/ap-TST-CUSTOMER1/epg-VLAN10"
}
ok: [my_host.com] => (item=uni/tn-TST-CUSTOMER3/ap-TST-CUSTOMER3/epg-VLAN30) => {
    "ansible_facts": {
        "epg_list": [
            "20", 
            "10", 
            "30"
        ]
    }, 
    "ansible_loop_var": "item", 
    "changed": false, 
    "item": "uni/tn-TST-CUSTOMER3/ap-TST-CUSTOMER3/epg-VLAN30"
}

同样的任务在 v2.13 中给出了以下内容:(扣除)

.
.
.
ok: [my_host.com] => (item=uni/tn-TST-CUSTOMER3/ap-TST-CUSTOMER3/epg-VLAN30) => {
    "ansible_facts": {
        "epg_list": "[] + [ '20' ] + [ '10' ] + [ '30' ]"
    },
    "ansible_loop_var": "item",
    "changed": false,
    "item": "uni/tn-TST-CUSTOMER3/ap-TST-CUSTOMER3/epg-VLAN30"
.
.
.

在第二个输出中,有一个空列表,每个列表都与 + 所以我的问题是,我正在做的是正常的方式,还是有一种最佳实践方式来循环列表并从中提取一些值?

【问题讨论】:

    标签: ansible


    【解决方案1】:

    它在 ansible 2.9 中“工作”的事实纯属巧合。您的 set_fact 任务的语法应该是错误的(在未首先定义变量时增加一点安全性):

    - name: gather only IDs
      set_fact:
        epg_list: "{{ epg_list | d([]) + [item.split('/')[-1] | regex_replace('epg-VLAN')] }}"
      loop: "{{ vlan_list | flatten(levels=1) }}"
      when: vlan_list | length > 0
    

    请注意,flatten 过滤器纯粹是可选的,如果您的数据总是看起来像您在问题中粘贴的那个

    此外,在这种情况下使用 set_fact 和 loop 是一种过度杀伤,因为您可以使用单个 jinja2 表达式获得结果,如下面的剧本所示:

    ---
    - hosts: localhost
      gather_facts: false
    
      vars:
        vlan_list:
          - uni/tn-TST-CUSTOMER2/ap-TST-CUSTOMER2/epg-VLAN20
          - uni/tn-TST-CUSTOMER1/ap-TST-CUSTOMER1/epg-VLAN10
          - uni/tn-TST-CUSTOMER3/ap-TST-CUSTOMER3/epg-VLAN30
    
        epg_list: '{{ vlan_list
          | map("regex_replace", "^.*/epg-VLAN([0-9]+)$", "g<1>")
          | map("int") | sort }}'
    
      tasks:
        - debug:
            var: epg_list
    

    这使:

    TASK [debug] *********************************************************
    ok: [localhost] => {
        "epg_list": [
            10,
            20,
            30
        ]
    }
    

    【讨论】:

      猜你喜欢
      • 2022-11-23
      • 2022-10-21
      • 1970-01-01
      • 2017-08-13
      • 1970-01-01
      • 2015-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多