将 Python 脚本的输出转换为 Ansible 中的字典
Converting output of Python script to dict in Ansible
我有一个名为 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.A
或 Dict.B
.
等值
我尝试了现有的所有选项 ,但 none 对我有用。
在实现第一个答案时,这是我的剧本:
---
- 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 脚本。
说明
这是 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"
}
}
我有一个名为 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.A
或 Dict.B
.
我尝试了现有的所有选项
在实现第一个答案时,这是我的剧本:
---
- 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 脚本。
说明
这是 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"
}
}