【问题标题】:Getting error while using jinja2 selectattr in ansible在 ansible 中使用 jinja2 selectattr 时出错
【发布时间】:2022-01-22 19:25:01
【问题描述】:

我有如下变量,(用户输入这些)

 vlanlist:
   - 3
   - 18 
   - 700
   - 57

以下是我从设备收集的内容,输出如下:

output5.msg:

[
    {
        "INTERFACE": "Ethernet1/1",
        "TRUNKING_VLANS": "2-18,20,24,48,52,54,56-66,68,70,72,76,80-82,84,86,88,90,92-94,96-104,108,112,116-127,700"
    },
    {
        "INTERFACE": "Ethernet1/2",
        "TRUNKING_VLANS": "2-18,20,24,48,52,54,56-66,68,70,72,76,80-82,84,86,88,90,92-94,96-104,108,112,116-127"
    }
]

场景:用户输入vlanlist,我必须根据vlans下面的列表是预期的结果:

vlan 3 - allowed on Etherent1/1,Etherent1/2
vlan 18 - allowed on Etherent1/1,Etherent1/2
vlan 57 - allowed on Etherent1/1,Etherent1/2
vlan 700 - allowed on Etherent1/1
vlan 700 - NOT allowed on Etherent1/2

我正在尝试使用selectattr 查找/查找vlanlist 在每个接口TRUNKING_VLANS 中:

- set_fact:
     vlan_info: "{{ vlan_info|d({})|combine({item : info}) }}"
   loop: "{{ vlanlist }}"
   vars:
     info: "{{ output5.msg|
              selectattr('TRUNKING_VLANS', 'contains', item)|list }}"

 - debug: msg="{{vlan_info}}"

得到错误:

{"msg": "An unhandled exception occurred while templating '{{ output5.msg| selectattr('TRUNKING_VLANS', 'contains', item)|list }}'. Error was a <class 'ansible.errors.AnsibleError'>, original message: Unexpected templating type error occurred on ({{ output5.msg| selectattr('TRUNKING_VLANS', 'contains', item)|list }}): 'in <string>' requires string as left operand, not int"}

【问题讨论】:

  • TRUNKING_VLANS 不是列表,因此您不能在其上使用简单的contains。然后,错误消息是不言自明的,包含可以比较字符串,但 vlans 包含 int。您应该将它们转换为string
  • 另外请注意,您的 contains 不会匹配 3,因为它在 TRUNKING_VLANS 中定义为范围 2-18
  • @β.εηοιτ.βε 你能分享任何示例或帖子,我可以参考和修复我的代码,尝试谷歌搜索一段时间找不到,谢谢
  • 修复您的错误消息就像{{ output5.msg | selectattr('TRUNKING_VLANS', 'contains', item | string) | list }} 一样简单。但这并不能满足您的需求,因为您的需求并不像您想象的那么微不足道。

标签: ansible jinja2


【解决方案1】:

展开列表,例如创建文件

shell> cat expand_vlans.yml
- set_fact:
    _vlans: []
- set_fact:
    _vlans: "{{ _vlans + range(start|int, stop|int + 1)|list }}"
  loop: "{{ i.TRUNKING_VLANS.split(',') }}"
  vars:
    start: "{{ item.split('-')|first }}"
    stop: "{{ item.split('-')|last }}"
- set_fact:
    vlan_exp: "{{ vlan_exp|d([]) + [{'INTERFACE': i.INTERFACE,
                                     'TRUNKING_VLANS': _vlans}] }}"

并迭代数据

    - include_tasks: expand_vlans.yml
      loop: "{{ output5.msg }}"
      loop_control:
        loop_var: i

给予

  vlan_exp:
    - INTERFACE: Ethernet1/1
      TRUNKING_VLANS: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20,
        24, 48, 52, 54, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 70, 72, 76, 80,
        81, 82, 84, 86, 88, 90, 92, 93, 94, 96, 97, 98, 99, 100, 101, 102, 103, 104, 108,
        112, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127, 700]
    - INTERFACE: Ethernet1/2
      TRUNKING_VLANS: [2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 20,
        24, 48, 52, 54, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 68, 70, 72, 76, 80,
        81, 82, 84, 86, 88, 90, 92, 93, 94, 96, 97, 98, 99, 100, 101, 102, 103, 104, 108,
        112, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 127]

然后创建信息

    - set_fact:
        vlan_info: "{{ vlan_info|d({})|combine({item: info}) }}"
      loop: "{{ vlanlist }}"
      vars:
        info: "{{ vlan_exp|
                  selectattr('TRUNKING_VLANS', 'contains', item)|
                  map(attribute='INTERFACE')|
                  list }}"

给予

  vlan_info:
    3: [Ethernet1/1, Ethernet1/2]
    18: [Ethernet1/1, Ethernet1/2]
    57: [Ethernet1/1, Ethernet1/2]
    700: [Ethernet1/1]

【讨论】:

  • 谢谢弗拉基米尔,你想出答案/解决方案的方式给我留下了深刻的印象。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-03-19
相关资源
最近更新 更多