是否可以使用 Jinja/Ansible 映射多个属性?

问题描述 投票:0回答:6

我想构建一个显示变量的键和值的输出。

以下效果完美...

# Format in Ansible

msg="{{ php_command_result.results | map(attribute='item') | join(', ') }}"

# Output
{'value': {'svn_tag': '20150703r1_6.36_homeland'}, 'key': 'ui'}, {'value': {'svn_tag': '20150702r1_6.36_homeland'}, 'key': 'api'}

我想要的是将

key
svn_tag
一起显示:

我可以显示

key
svn_tag
,但让它们组合在一起不起作用。

msg="{{ php_command_result.results | map(attribute='item.key') | join(', ') }}"

# Output
ui, api

然而,这就是我想要的。

# Desired Output
api - 20150702r1_6.36_homeland
ui - 20150703r1_6.36_homeland
jinja2 ansible
6个回答
15
投票

使用 Jinja 语句

- set_fact:
    php_command_result:
      results: [{"value":{"svn_tag":"20150703r1_6.36_homeland"},"key":"ui"},{"value":{"svn_tag":"20150702r1_6.36_homeland"},"key":"api"}]

- debug:
    msg: "{% for result in php_command_result.results %}\
        {{ result.key }} - {{ result.value.svn_tag }} |
      {% endfor %}"

输出:

ok: [localhost] => {
    "msg": "ui - 20150703r1_6.36_homeland | api - 20150702r1_6.36_homeland | "
}

如果您想要将结果放在单独的行上:

- debug:
    msg: "{% set output = [] %}\
        {% for result in php_command_result.results %}\
          {{ output.append( result.key ~ ' - ' ~ result.value.svn_tag) }}\
        {% endfor %}\
      {{ output }}"

输出:

ok: [localhost] => {
    "msg": [
        "ui - 20150703r1_6.36_homeland", 
        "api - 20150702r1_6.36_homeland"
    ]
}

如果需要,可以将其中任何一个放在一行上:

- debug:
    msg: "{% for result in php_command_result.results %}{{ result.key }} - {{ result.value.svn_tag }} | {% endfor %}"

- debug:
    msg: "{% set output = [] %}{% for result in php_command_result.results %}{{ output.append( result.key ~ ' - ' ~ result.value.svn_tag) }}{% endfor %}{{ output }}"

8
投票

这是没有自定义filter_plugin或运行shell命令的解决方案。但是,它需要在 with_items 循环中设置额外的事实(php_fmt)。

- hosts: localhost
  connection: local
  gather_facts: false 
  tasks:
    - set_fact: 
        php_command_result:
          results: '[{"value":{"svn_tag":"20150703r1_6.36_homeland"},"key":"ui"},{"value":{"svn_tag":"20150702r1_6.36_homeland"},"key":"api"}]'

    - set_fact:
        php_fmt: "{{ php_fmt|default([])|union([item.key+' -- '+item.value.svn_tag ]) }}"
      with_items: "{{ php_command_result.results }}"

    - debug: 
        msg: "{{php_fmt|join(',')}}"

8
投票

当我搜索处理类似任务的方法时,我发现了这个问题,但我希望输出是另一个包含各个元素的 JSON 列表。我在

map
filter
甚至 Jinja2
for
循环上花了很多注意力,所以我也将在这里发布答案。只需创建以下文件并通过
ansible-playbook
:

运行
- hosts: localhost
  connection: local
  vars:
    to_test: [ {'value': {'svn_tag': '20150703r1_6.36_homeland'}, 'key': 'ui'}, {'value': {'svn_tag': '20150702r1_6.36_homeland'}, 'key': 'api'} ]
  tasks:
  - debug:
      msg: "to_test: {{ to_test }}"
  - debug:
      msg: "to_test reduced: {{ to_test | json_query('[].{key: key, svn_tag: value.svn_tag}') | list }}"
  - debug:
      msg: "to_test reduced: {{ to_test | json_query(query1) | list }}"
    vars:
      query1: "[].{key: key, svn_tag: value.svn_tag}"

最终结果是一个漂亮的 JSON 数组:

[{'key': 'ui', 'svn_tag': '20150703r1_6.36_homeland'}, {'key': 'api', 'svn_tag': '20150702r1_6.36_homeland'}]"

6
投票

这是另一个使用

filter_plugins
的答案,我发现它非常容易使用。

如果有人仍然需要这个,你可以使用以下代码(放入 playbooks/filter_plugins/mapattributes.py):

#!/usr/bin/env python
class FilterModule(object):
  def filters(self):
    return { 'mapattributes': self.mapattributes }

  def mapattributes(self, list_of_dicts, list_of_keys):
    l = []
    for di in list_of_dicts:
      newdi = { }
      for key in list_of_keys:
        # newdi[key] = di[key]
        if di.get(key, None) != None:
          newdi[key] = di[key]

      l.append(newdi)
    return l

假设您有这个列表,您只需从中键入:

    INTERFACES:
      - { name: GigabitEthernet1/0/24 , enabled: yes, state: up , description: FRONT }
      - { name: GigabitEthernet1/0/9  , enabled: yes, state: up , description: BACK  }

让我们创建另一个变量,仅过滤所需的

key:values

    test: "{{ INTERFACES | mapattributes(['name', 'description']) }}"

测试输出

    - debug:
        var: test
ok: [R1] => {
    "test": [
        {
            "description": "FRONT",
            "name": "GigabitEthernet1/0/24"
        },
        {
            "description": "BACK",
            "name": "GigabitEthernet1/0/9"
        }
    ]
}

这让我可以拥有一本大字典,并且只对我需要传递给的键进行切片

ios_interface/aggregate

感谢 Nee6ione,我在 Pallet/jinja github 上找到了它 issue


4
投票

您可以使用以下技术来做到这一点:

  1. 创建

    filter_plugin
    。在 ansible.cfg 中添加
    filter_plugins = <path to the folder>
    。然后创建一个文件说
    my_plugin.py
    :

    class FilterModule(object):
    ''' Custom filter '''
        def filters(self, my_arg):
           return <parse it here......>
    

示例:

playbook.yml

---
- hosts: localhost
  gather_facts: no
  connection: local
  tasks:
    - set_fact: 
        php_command_result:
          results: {'value': {'svn_tag': '20150703r1_6.36_homeland'}, 'key': 'ui'}
    - debug: msg="Hey look what I got '{{ php_command_result.results | a }}'"

我的插件.py

import json

class FilterModule(object):
    def filters(self):
      return {'a': a}

def a(a):
  r = '%s - %s' % (a['key'], a['value']['svn_tag'])
  return r
  1. 快速简单的方法:只需使用

    python/php/shell
    或您喜欢的
    shell
    模块即可。像这样的东西:

    - name: Pars output
      shell: python -c "import json; json.loads('{{ php_command_result.results }}') ....
    

0
投票

仅使用 ansible 内置过滤器的解决方案

这里没有花哨的多行 jinja 语句。都不是自定义的 python filter_plugin。

代码

创建以下任务:

- ansible.builtin.debug: msg: "{{ keys | zip(svn_tags) | map('join', ' - ') }}" vars: php_command_results: [{'value': {'svn_tag': '20150703r1_6.36_homeland'}, 'key': 'ui'}, {'value': {'svn_tag': '20150702r1_6.36_homeland'}, 'key': 'api'}] keys: "{{ php_command_results | map(attribute='key') }}" svn_tags: "{{ php_command_results | map(attribute='value') | map(attribute='svn_tag')}}"
哪个输出:

ok: [controller] => { "msg": [ "ui - 20150703r1_6.36_homeland", "api - 20150702r1_6.36_homeland" ] }
好处

    将转换后的数据保存在由 ansible 正确管理的 python 结构中(此处为列表)。
  1. 在大量数据上使用多行 jinja2 语句可以更快地执行该操作,就像此处获得最多支持的答案中的语句一样。
  2. 仍然可以将结果转换为纯文本,例如将其放入受管节点上的数据文件中。使用此任务,使用与我的第一个示例相同的变量:
- ansible.builtin.copy: content: "{{ keys | zip(svn_tags) | map('join', ' - ') | join ('\n') }}" dest: data.txt
以下是被管节点上的 data.txt 文件的内容:

$ cat data.txt ui - 20150703r1_6.36_homeland api - 20150702r1_6.36_homeland
希望这有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.