【问题标题】:Ansible / jinja2 outputAnsible / jinja2 输出
【发布时间】:2021-04-29 23:36:44
【问题描述】:

我在 RHEL 7.4 上运行 Ansible 2.7.5。 (我知道它很旧;我会尽快升级——保证)。 zip 功能出现在 Ansible 2.3 中。无论如何,我似乎无法通过 zip 过滤器获得几个列表来正确创建字典。

我从变量文件中读取了列表。该列表是network_interfaces['computer_type'] 在循环中,然后再往下;这是来自调试输出:

[{u'interface': u'bond0.160', u'notes': u'note160'},
 {u'interface': u'bond0.197', u'notes': u'note197'},
 {u'interface': u'bond1', u'notes': u'bonded, numa1, broadcom device'}]

问题是,我正在尝试将您在上面看到的接口名称连同它们的值一起放入字典中(现在作为示例是“注释”)。但是当我尝试执行dict (_keys|zip(_vals)) 时,如下面_reused_val 的第一个示例所示,我得到了相应的错误消息编号1。因此,为了调试,我重新运行了我的任务,未注释#2,随后使用#3未注释。

- debug:
    msg: >
         ITEM: {{ item }}
         *        :::network_interfaces::: {{ network_interfaces[computer_type] }}
         *        :::_keys::: {{ _keys }}
         *        :::_vals::: {{ _vals }}
         *        :::_reused_val::: {{ _reused_val }}
  loop: [ " {{ computer_type }} " ]
  vars:
    computer_type: big_computer
    _keys: "{{ network_interfaces[computer_type]|map(attribute='interface')|list }}"
    _vals: "{{ network_interfaces[computer_type] }}" # returns a list
    _reused_val: "{{ dict(_keys|zip(_vals)) }}"    #1
    #_reused_val: "{{ _keys|zip(_vals) | list }}"  #2
    #_reused_val: "{{ _keys|zip(_vals) }}"         #3

输出显示reused_val(我稍微调整了间距以使其更易于阅读):

1- "msg": "Unexpected templating type error occurred on ({{ dict(_keys|zip(_vals)) }}): <lambda>() takes exactly 0 arguments (1 given)"
2- [(u'bond0.160', {u'interface': u'bond0.160', u'notes': u'note160'}),
    (u'bond0.197', {u'interface': u'bond0.197', u'notes': u'note197'}),
    (u'bond1', {u'interface': u'bond1', u'notes': u'bonded, numa1, broadcom device'})]
3- <itertools.izip object at 0x7f311c048dd0>

#1 是我想要开始工作的 - dict(_keys|zip(_vals))

我不知道为什么#3 显示一个 itertools.izip 对象。我认为它应该返回一个列表。对于#2,我不知道这些括号是干什么用的。是不是因为列表中有 3 个字典?

最后,这里是案例 #3 的完整的 msg 输出;为了更容易阅读,我稍微打断了线条:

"ITEM:  big_computer  *        :::network_interfaces:::
[{u'interface': u'bond0.160', u'notes': u'note160'}, {u'interface': u'bond0.197', u'notes': u'note1
97'}, {u'interface': u'bond1', u'notes': u'bonded, numa1, broadcom device'}]
*        :::_keys::: [u'bond0.160', u'bond0.197', u'bond1']
*        :::_vals::: [{u'interface': u'bond0.160', u'notes': u'note160'}, {u'interface': u'bond0.197', u'notes': u'note197'}, {u'interface': u'bond1', u'notes': u'bonded, numa1, broadcom device'}]
*        :::_reused_val::: <itertools.izip object at 0x7fc768049cb0>\n"

这项工作是我在Ansible: need to combine information from 2 files for a task later 提问的结果 我正在尝试按照示例进行操作,但经过一天的工作,我仍然陷入困境。谢谢。

【问题讨论】:

    标签: ansible yaml jinja2


    【解决方案1】:

    我认为你应该升级你的 Ansible。

    使用 ansible 2.10.8,以下 playbook 运行没有错误,我认为它会产生您想要的输出。这与您所拥有的基本相同,只是我在debug 任务中使用了一个列表来生成更清晰的输出。

    - hosts: localhost
      gather_facts: false
      vars:
        network_interfaces:
          big_computer:
            - interface: bond0.160
              notes: note160
            - interface: bond0.197
              notes: note197
            - interface: bond1
              notes: 'bonded, numa1, broadcom devices'
    
      tasks:
        - debug:
            msg:
              - "ITEM: {{ item }}"
              - "network_interfaces: {{ network_interfaces[computer_type] }}"
              - "keys: {{ _keys }}"
              - "vals: {{ _vals }}"
              - "reused_val: {{ _reused_val }}"
          loop: [ " {{ computer_type }} " ]
          vars:
            computer_type: big_computer
            _keys: "{{ network_interfaces[computer_type]|map(attribute='interface')|list }}"
            _vals: "{{ network_interfaces[computer_type] }}" # returns a list
            _reused_val: "{{ dict(_keys|zip(_vals)) }}"    #1
    

    运行它会产生:

    TASK [debug] *********************************************************************************************************************************************************************************
    ok: [localhost] => (item= big_computer ) => {
        "msg": [
            "ITEM:  big_computer ",
            "network_interfaces: [{'interface': 'bond0.160', 'notes': 'note160'}, {'interface': 'bond0.197', 'notes': 'note197'}, {'interface': 'bond1', 'notes': 'bonded, numa1, broadcom devices'}]",
            "keys: ['bond0.160', 'bond0.197', 'bond1']",
            "vals: [{'interface': 'bond0.160', 'notes': 'note160'}, {'interface': 'bond0.197', 'notes': 'note197'}, {'interface': 'bond1', 'notes': 'bonded, numa1, broadcom devices'}]",
            "reused_val: {'bond0.160': {'interface': 'bond0.160', 'notes': 'note160'}, 'bond0.197': {'interface': 'bond0.197', 'notes': 'note197'}, 'bond1': {'interface': 'bond1', 'notes': 'bonded, numa1, broadcom devices'}}"
        ]
    }
    

    如果我使用 Ansible 2.7.5 运行它,我仍然看不到您报告的任何错误(这就是为什么在你的问题),但我也没有得到与 2.10.8 相同的行为。我明白了:

    TASK [debug] *********************************************************************************************************************************************************************************
    ok: [localhost] => (item= big_computer ) => {
        "msg": [
            "ITEM:  big_computer ",
            "network_interfaces: [{'interface': 'bond0.160', 'notes': 'note160'}, {'interface': 'bond0.197', 'notes': 'note197'}, {'interface': 'bond1', 'notes': 'bonded, numa1, broadcom devices'}]",
            "keys: ['bond0.160', 'bond0.197', 'bond1']",
            "vals: [{'interface': 'bond0.160', 'notes': 'note160'}, {'interface': 'bond0.197', 'notes': 'note197'}, {'interface': 'bond1', 'notes': 'bonded, numa1, broadcom devices'}]",
            "reused_val: {'[': '[', \"'\": 's', 'b': \"'\", 'o': 'n', 'n': 'o', 'd': 't', '0': 'd', '.': '0', '1': 'e', '6': 'a', ',': \"'\", ' ': ',', '9': '1', '7': '6', ']': \"'\"}"
        ]
    }
    

    所以,除了最后一步,一切都很好。这里最大的问题是 Ansible 2.7.5 不能很好地处理字符串值以外的任何内容。当你写这个...

    _keys: "{{ network_interfaces[computer_type]|map(attribute='interface')|list }}"
    

    结果是一个 字符串 值,而不是一个列表,而在最近的 在 Ansible 的版本中,_keys 变量 是一个列表。我们可以工作 通过显式序列化和反序列化所有内容来解决这个问题 到/从 JSON:

    - debug:
        msg:
          - "ITEM: {{ item }}"
          - "network_interfaces: {{ network_interfaces[computer_type] }}"
          - "keys: {{ _keys }}"
          - "vals: {{ _vals }}"
          - "reused_val: {{ _reused_val }}"
      loop: [ " {{ computer_type }} " ]
      vars:
        computer_type: big_computer
        _keys: "{{ network_interfaces[computer_type]|map(attribute='interface')|list|to_json }}"
        _vals: "{{ network_interfaces[computer_type]|to_json }}"
        _reused_val: "{{ dict(_keys|from_json|zip(_vals|from_json)) }}"
    
    

    这会产生与 2.10.8 的原始版本相同的输出:

    TASK [debug] *********************************************************************************************************************************************************************************
    ok: [localhost] => (item= big_computer ) => {
        "msg": [
            "ITEM:  big_computer ",
            "network_interfaces: [{'interface': 'bond0.160', 'notes': 'note160'}, {'interface': 'bond0.197', 'notes': 'note197'}, {'interface': 'bond1', 'notes': 'bonded, numa1, broadcom devices'}]",
            "keys: [\"bond0.160\", \"bond0.197\", \"bond1\"]",
            "vals: [{\"interface\": \"bond0.160\", \"notes\": \"note160\"}, {\"interface\": \"bond0.197\", \"notes\": \"note197\"}, {\"interface\": \"bond1\", \"notes\": \"bonded, numa1, broadcom devices\"}]",
            "reused_val: {'bond0.160': {'interface': 'bond0.160', 'notes': 'note160'}, 'bond0.197': {'interface': 'bond0.197', 'notes': 'note197'}, 'bond1': {'interface': 'bond1', 'notes': 'bonded, numa1, broadcom devices'}}"
        ]
    }
    

    ...但这是一个糟糕的解决方案,而且它会更清洁 升级。

    【讨论】:

    • 是的,它在 2.9.3 上运行对我来说没有问题。在 2.7.5 上失败。我将立即升级
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-10
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    相关资源
    最近更新 更多