【问题标题】:Converting output of Python script to dict in Ansible在 Ansible 中将 Python 脚本的输出转换为 dict
【发布时间】:2018-02-09 10:21:48
【问题描述】:

我有一个名为 test.py 的 Python 脚本:

#!/usr/bin/python
a = "A:2\nB:5"
print a

现在在我的 Ansible 剧本中,我正在运行此脚本并使用此任务将输出注册到变量

- name: Create variable from the command
  command: "python ./test.py"
  register: command_output

我想将输出转换为 ansible 中的字典 Dict,以便在后续任务中可以访问 Dict.ADict.B 等值。

我尝试了here 提供的所有选项,但没有一个对我有用。

在实现第一个答案时,这是我的剧本:

---
- hosts: localhost
  gather_facts: no
  become: yes
  tasks:
    - name: Create variable from command
      command: "python ./test.py"
      register: command_output

    - name: set parameter values as fact
      set_fact:
        parameter: >
          "{{ parameter | default({}) | combine ( { item.split(':')[0]: item.split(':')[1] } ) }}"
      with_items: "{{command_output.stdout_lines}}"

    - debug:
        msg: "{{parameter}}"

为此,我收到错误:

TASK [set parameter values as fact] **************************************************************************************************************************************************************
ok: [localhost] => (item=A:2)
fatal: [localhost]: FAILED! => {"msg": "|combine expects dictionaries, got u'\"{u\\'A\\': u\\'2\\'}\"\\n'"}

第二个答案我写了这个脚本

---
- hosts: localhost
  gather_facts: no
  become: yes
  tasks:

    - name: Create variable from command
      command: "python ./test.py"
      register: command_output


    - name: set parameter values as fact
      set_fact:
        parameter: >
          {{
            parameter | default({})|
            combine(
              dict([item.partition(':')[::2]|map('trim')])
            )
          }}
      with_items: "{{command_output.stdout_lines}}"

    - debug:
        msg: "{{parameter.B}}"

在这种情况下,我收到此错误

fatal: [localhost]: FAILED! => {"msg": "Unexpected templating type error occurred on ({{ dict([item.partition(':')[::2]|map('trim')]) }}): <lambda>() takes exactly 0 arguments (1 given)"}

我不知道如何将 python 脚本的输出转换为 Ansible 中的字典。我可以将输出作为列表、字符串或字典本身从 python 发送,但无论如何,它在 Ansible 中注册为字符串,之后,我无法将其转换回 Ansible 中的字典。

如果有任何其他方法可以实现这一点,请提供帮助。我正在考虑为此编写 ansible 模块,但即使在那里我也不确定 ansible 将如何处理模块的输出,因为本质上它也是一个 python 脚本。

【问题讨论】:

    标签: python dictionary ansible ansible-2.x


    【解决方案1】:

    说明

    这是 YAML 解释的问题。您在块标量定义&gt; 之后使用" 显式定义了一个字符串,这意味着在第一次迭代之后parameter 变量被定义为字符串。

    然后第二次迭代失败,因为您将该字符串传递给 combine 过滤器(而不是它所期望的字典)。


    解决方案

    要么将其写在一行中,而不是使用 YAML 块标量定义 (&gt;):

    parameter: "{{ parameter | default({}) | combine ( { item.split(':')[0]: item.split(':')[1] } ) }}"
    

    或者去掉引号:

    parameter: >
      {{ parameter | default({}) | combine ( { item.split(':')[0]: item.split(':')[1] } ) }}
    

    输出:

    TASK [Create variable from the command] *************************************************************************************
    changed: [localhost]
    
    TASK [set parameter values as fact] *****************************************************************************************
    ok: [localhost] => (item=A:2)
    ok: [localhost] => (item=B:5)
    
    TASK [debug] ****************************************************************************************************************
    ok: [localhost] => {
        "msg": {
            "A": "2",
            "B": "5"
        }
    }
    

    【讨论】:

    • 没有。输出是正确的。错误|combine expects dictionaries 仅在您定义了块标量时才会发生。
    • 是的,您的解决方案有效。工作正常。感谢一个looooot人。我不知道这可能是问题所在。我被困了一天多。
    猜你喜欢
    • 2019-02-04
    • 2014-05-24
    • 2012-10-15
    • 2019-01-16
    • 1970-01-01
    • 2018-07-12
    • 2019-10-08
    • 2013-06-15
    • 2011-08-08
    相关资源
    最近更新 更多