Ansible:将对象列表传递给Python脚本

huangapple go评论98阅读模式
英文:

Ansible: passing a list of objects to a python script

问题

我正在使用script模块编写一个Ansible角色。脚本本身位于角色的files库中。环境变量test_var位于整个剧本的group_vars文件夹下的YAML文件中:

---
- name: 执行脚本
  script: python_script.py {{ test_var }}
  args:
    executable: python

如果只是一个简单的“key=value”类型的参数,这可以正常工作。但是,我不确定如何传递复杂的项目,比如列表或对象列表到Python脚本中,以便将其用作Python字典。

这方面有最佳实践吗?

上面的Ansible角色只返回列表的第一项。

YAML输入如下:

test_var:
  - val:
      something: 1
  - other_val:
    - '1'
    - '2'
    - '3'

Python代码如下:

import sys

i = 0

print('第一个参数:')
print(sys.argv[1])
print(' ')

tmp_string = ""

print('打印出每个参数:')
for x in sys.argv:
  if i > 0:
    print(x)
    tmp_string += x
  i += 1

print(' ')
print('将每个参数连接在一起:')
print(tmp_string)

结果如下:

changed: [localhost] => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to localhost closed.\r\n",
    "stderr_lines": [
        "Shared connection to localhost closed."
    ],
    "stdout": "第一个参数:\r\n[{uval:\r\n \r\n打印出每个参数:\r\n[{uval:\r\n{usomething:\r\n1}},\r\n{uother_val:\r\n[u1,\r\nu2,\r\nu3]}]\r\n \r\n将每个参数连接在一起:\r\n[{uval:{usomething:1}},{uother_val:[u1,u2,u3]}]\r\n",
    "stdout_lines": [
        "第一个参数:",
        "[{uval:",
        " ",
        "打印出每个参数:",
        "[{uval:",
        "{usomething:",
        "1}},",
        "{uother_val:",
        "[u1,",
        "u2,",
        "u3]}]",
        " ",
        "将每个参数连接在一起:",
        "[{uval:{usomething:1}},{uother_val:[u1,u2,u3]}]"
    ]
}

我不确定如何处理每行开头的u字符。

我注意到Ansible将YAML的每一行都传递为不同的命令行参数,因此第一个参数只包含第一行。我可以使用for循环将它们连接成一个字符串,但我不确定如何将其转换为Python可以使用的字典或其他数据结构。

英文:

I'm writing an Ansible role using the script module. The script itself is located within the role's files library. The environment variable test_var is located within a YAML file under the group_vars folder of the whole playbook:

---
- name: execute script
  script: python_script.py {{ test_var }}
  args:
    executable: python

This works fine and well if it's only one simple "key=value" kind of parameter, however I'm not sure how should I pass complex items like lists or list of objects to the python script to use it as a python dictionary.

Is there a best practice for this?

The Ansible role above only returns the first item of the list.

The yaml input:

test_var:
  - val:
      something: 1
  - other_val:
    - '1'
    - '2'
    - '3'

The python code:

import sys

i = 0

print('The first argument: ')
print sys.argv[1]
print(' ')

tmp_string = ""

print('Every argument printed out:')
for x in sys.argv:
  if i > 0:
    print x
    tmp_string += x
  i += 1

print(' ')
print('Concatenating together each argument:')
print tmp_string

Results:

changed: [localhost] => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to localhost closed.\r\n",
    "stderr_lines": [
        "Shared connection to localhost closed."
    ],
    "stdout": "The first argument: \r\n[{uval:\r\n \r\nEvery argument printed out:\r\n[{uval:\r\n{usomething:\r\n1}},\r\n{uother_val:\r\n[u1,\r\nu2,\r\nu3]}]\r\n \r\nConcatenateing together each argument:\r\n[{uval:{usomething:1}},{uother_val:[u1,u2,u3]}]\r\n",
    "stdout_lines": [
        "The first argument: ",
        "[{uval:",
        " ",
        "Every argument printed out:",
        "[{uval:",
        "{usomething:",
        "1}},",
        "{uother_val:",
        "[u1,",
        "u2,",
        "u3]}]",
        " ",
        "Concatenateing together each argument:",
        "[{uval:{usomething:1}},{uother_val:[u1,u2,u3]}]"
    ]
}

I'm not sure what to do whit the us at the beginning of every line.

As I see Ansible passes every line of the yaml as a different command line argument, so the first one only contains the first line. I could concatenate these into a single string with a for loop, but I'm not sure how to convert that into a dictionary or something python can use.

答案1

得分: 1

Ansible 并没有提供一个很好的机制来将复杂数据传递给 script 模块。可能更简单的方法是编写自己的 Ansible 模块,然后像其他模块一样将数据传递给它:

---
- name: 运行我的模块
  mymodule:
    someparameter: "{{ test_var }}"

你的模块可以是一个带有一些现有代码顶部的 Python 脚本。以下是一个非常简单的模板,支持上面的示例:

#!/usr/bin/python

from __future__ import absolute_import, division, print_function  # NOQA

from ansible.module_utils.basic import AnsibleModule


def main():
    argument_spec = {
      'someparameter': dict(type='list', required=True),
    }

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    result = {'changed': False}
    
    data = module.params['someparameter']
    
    # ...在这里处理你的数据...

    module.exit_json(**result)


if __name__ == '__main__':
    main()

将你的模块放入你的角色的 library 目录中,然后你就可以使用了。

你可以在文档中找到更多信息:

英文:

Ansible doesn't really provide a great mechanism for passing complex data to the script module. It might be simpler to write your own Ansible module, and then pass your data to it like any other module:

---
- name: run my module
  mymodule:
    someparameter: "{{ test_var }}"
  

Your module can be a Python script with only a little boilerplate on top of your existing code. Here's a very simple template that would support the above example:

#!/usr/bin/python

from __future__ import absolute_import, division, print_function  # NOQA

from ansible.module_utils.basic import AnsibleModule


def main():
    argument_spec = {
      'someparameter': dict(type='list', required=True),
    }

    module = AnsibleModule(argument_spec=argument_spec,
                           supports_check_mode=True)

    result = {'changed': False}
    
    data = module.params['someparameter']
    
    # ...do something with your data here...

    module.exit_json(**result)


if __name__ == '__main__':
    main()

Drop your module into the library directory of your role and you're all set.

You can find more information in the docs:

答案2

得分: 0

可能需要对变量应用一个过滤器。请尝试以下内容:

---
- name: 执行脚本
  script: python_script.py {{ test_var | to_yaml }}
  args:
    executable: python
英文:

Probably, you need to apply a filter to the variable. Try this:

---
- name: execute script
  script: python_script.py {{ test_var | to_yaml }}
  args:
    executable: python

huangapple
  • 本文由 发表于 2020年1月3日 22:40:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/59580470.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定