Ansible:列表的 pretty-print 元素

标签 ansible jinja2

我想漂亮地打印上一个任务已注册的结果列表中的每一项。我天真的做法是这样的:

- hosts: localhost
  gather_facts: no
  tasks:
    - command: "echo number {{item}}"
      with_items: [1, 2, 3]
      register: result
    - debug:
        msg: "=== {{ item.cmd|join(' ') }} ===\n{{ item.stdout|indent(first=true) }}"
      with_items: "{{ result.results }}"

我在 ansible.cfg 中使用 stdout_callback = debug 来使输出更易于阅读。

上述内容几乎有效。输出看起来符合预期,但不幸的是,除了我的 msg 表达式之外,debug 模块还记录了完整的循环项,这使输出出现了很大的困惑:

TASK [debug] ************************************************************************************************************************************************************
ok: [localhost] => (item={'cmd': ['echo', 'number', '1'], 'stdout': 'number 1', 'stderr': '', 'rc': 0, 'start': '2021-12-20 13:36:29.488443', 'end': '2021-12-20 13:36:29.490032', 'delta': '0:00:00.001589', 'changed': True, 'invocation': {'module_args': {'_raw_params': 'echo number 1', 'warn': True, '_uses_shell': False, 'stdin_add_newline': True, 'strip_empty_ends': True, 'argv': None, 'chdir': None, 'executable': None, 'creates': None, 'removes': None, 'stdin': None}}, 'stdout_lines': ['number 1'], 'stderr_lines': [], 'failed': False, 'item': 1, 'ansible_loop_var': 'item'}) => {}

MSG:

=== echo number 1 ===
    number 1

设置 no_log: true 会抑制所有输出,因此没有帮助。有没有办法只打印msg

我已经尝试了很多,但唯一接近我想法的解决方案是取消 debug 任务中的循环并使用自定义过滤器插件来打印项目。

    - debug:
        msg: "{{ result.results | map('format_result',  '=== {} ===\n{}') | join('\n\n') }}"

其中 filter_plugins/format_result.py 如下所示:

def format_result(res, pattern):
    return (pattern.format(" ".join(res['cmd']), res['stdout']))

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

过滤器插件方法满足了我的要求,但我问自己是否没有更简单的解决方案。

2021 年 12 月 21 日更新:

感谢@Zeitounator 下面的评论,我想出了这个:

- hosts: localhost
  gather_facts: no
  tasks:
    - command: "echo number {{item}}"
      with_items: [1, 2, 3]
      register: result
      loop_control:
        label: "\nThe item is: {{ result.stdout|indent(first=true) }}\n"

我还没有弄清楚如何在不使用register的情况下访问循环内的循环结果。

2022 年 2 月 3 日更新:

尝试总结我所学到的东西(感谢大家并原谅我的无知,正如你所看到的,我几乎是一个 ansible 菜鸟):

  • 我的第一种方法的错误是忽略了 ansible 为每个简单任务以及带有循环的任务的每次迭代打印结果行。
  • 带有循环的调试任务将为每次迭代打印一个结果行,后跟实际消息。
  • 我想要抑制的冗长输出只是这个结果行,而不是调试模块本身的输出。
  • 由于上述原因,带有循环的调试任务通常不会削减它以获得 pretty-print 输出。
  • 因此,必须将循环移至模板中,就像 β.εηοιτ.βε 的解决方案或我最初的“自定义过滤器”方法一样。

最佳答案

您实际上可以使用 Jinja 渲染,就像在 debug 任务的模板中使用它一样,as suggested in the comment .

鉴于剧本:

- hosts: localhost
  gather_facts: no

  tasks:
    - command: "echo number {{ item }}"
      with_items: [1, 2, 3]
      register: result

    - debug:
        msg: >-
          {% for _result in result.results %}
          === {{ _result.invocation.module_args._raw_params }} ===
               {{ _result.stdout }}
          {% endfor %}

这将给出您预期的输出:

ok: [localhost] => {}

MSG:

 === echo number 1 ===
     number 1
 === echo number 2 ===
     number 2
 === echo number 3 ===
     number 3

关于Ansible:列表的 pretty-print 元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70422006/

相关文章:

Ansible-安装固定到主要版本的软件包

git - 如何使用ansible playbook从本地机器添加/更新git标签?

jinja2 - 如何使用 jinja2 过滤器过滤掉空列表?

python - Flask 表单字段的动态默认值设置

Ansible 模块 s3 - 模式=获取错误

java - 如何使用 Ansible Playbook 检查目标机器中安装的不同 JAVA?

windows - 在 Windows 上安装 Ansible

python - 如何有效地使用 `pyjade` 导入混合?

dictionary - ansible 扁平化 map 过滤结果

python - 如何在 Jinja2 中将时间戳更新为全局变量?