在Ansible中将Python脚本的输出转换为dict

时间:2018-02-09 10:21:49

标签: python dictionary ansible ansible-2.x

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

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

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

- 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脚本。

1 个答案:

答案 0 :(得分:2)

<强>解释

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

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

<强>解决方案

将它写在一行而不是使用YAML块标量定义(>):

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"
    }
}