简体   繁体   English

如何将 ansible 剧本(yaml)转换为 python 数据结构

[英]how to convert an ansible playbook (yaml) to a python data structure

First of all, this is my very first question on SO - it might not entirely conform SO standards.首先,这是我关于 SO 的第一个问题——它可能不完全符合 SO 标准。

I am trying to figure out how to convert an ansible playbook-file to a python data structure as mentioned in this document from docs.ansible.com.我正在尝试弄清楚如何将 ansible 剧本文件转换为 python 数据结构,如本文档中提到的来自 docs.ansible14BEC50D236ADD9A0DADDAD

    # create data structure that represents our play, including tasks, this is basically what our YAML loader does internally.
play_source = dict(
    name="Ansible Play",
    hosts=host_list,
    gather_facts='no',
    tasks=[
        dict(action=dict(module='shell', args='ls'), register='shell_out'),
        dict(action=dict(module='debug', args=dict(msg='{{shell_out.stdout}}'))),
        dict(action=dict(module='command', args=dict(cmd='/usr/bin/uptime'))),
    ]
)

The reason I want to do this is, is that Play() does not accept a raw yaml-file and that the example nicely hooks to the provided ResultsCollectorJSONCallback() which gives me a very good way to capture output.. I'm very well aware there is a Playbook Executor but doesn't quite cut it because all output is dumped to stdout.我想这样做的原因是,Play() 不接受原始 yaml 文件,并且该示例很好地挂钩到提供的 ResultsCollectorJSONCallback(),这为我提供了一种捕获 output 的好方法。我非常很清楚有一个 Playbook Executor 但并没有完全削减它,因为所有 output 都被转储到标准输出。

This piece of code make it possible to capture it to file for each host (also from the documentation):这段代码可以将其捕获到每个主机的文件中(也来自文档):

print("UP ***********")
for host, result in results_callback.host_ok.items():
    print('{0} >>> {1}'.format(host, result._result['stdout']))

print("FAILED *******")
for host, result in results_callback.host_failed.items():
    print('{0} >>> {1}'.format(host, result._result['msg']))

print("DOWN *********")
for host, result in results_callback.host_unreachable.items():
    print('{0} >>> {1}'.format(host, result._result['msg']))

I tried to find any documentation where ansible converts a yaml to that python data structure.我试图找到 ansible 将 yaml 转换为 python 数据结构的任何文档。 The comment clearly says "this is basically what our YAML loader does internally."评论清楚地说“这基本上是我们的 YAML 加载程序在内部所做的。” but I can't figure out how they do it, even tried to figure out how the PlaybookExecutor does the trick but it's quite complicated to see what's really happening.但我无法弄清楚他们是如何做到的,甚至试图弄清楚 PlaybookExecutor 是如何做到的,但要看到真正发生的事情非常复杂。 I was hoping to find a yaml_to_datastructure function somewhere in the ansible's yaml-parsing routines but failed to find it.我希望在 ansible 的 yaml 解析例程中的某处找到一个 yaml_to_datastructure function 但未能找到它。 Anyone experience with this?有人有这方面的经验吗?

Regards, Sjoerd问候, Sjoerd

The data passed to Play().load is just the content of a single play from a playbook.传递给Play().load的数据只是剧本中单个剧本的内容。 That is, if I have a playbook that looks like:也就是说,如果我有一个看起来像这样的剧本:

- hosts: localhost
  tasks:
    - debug:
        msg: "This is a test"

I can load it like this:我可以像这样加载它:

>>> import yaml
>>> from ansible.inventory.manager import InventoryManager
>>> from ansible.parsing.dataloader import DataLoader
>>> from ansible.vars.manager import VariableManager
>>> from ansible.playbook.play import Play
>>> loader = DataLoader()
>>> inventory = InventoryManager(loader=loader)
[WARNING]: No inventory was parsed, only implicit localhost is available
>>> variable_manager = VariableManager(loader=loader, inventory=inventory)
>>> with open('playbook.yml') as fd:
...     playbook = yaml.safe_load(fd)
...
>>> play = Play().load(playbook[0], variable_manager=variable_manager, loader=loader)

Etc.等等。

Note where I'm passing playbook[0] to Play().load (the first play in the playbook), rather than the entire playbook.注意我将playbook[0]传递给Play().load (剧本中的第一个剧本),而不是整个剧本。

But if your goal is to run Ansible playbooks using Python, you might be better of using ansible-runner .但是,如果您的目标是使用 Python 运行 Ansible 剧本,那么使用 ansible -runner可能会更好。 That looks like:看起来像:

>>> import ansible_runner
>>> res = ansible_runner.interface.run(private_data_dir='.',playbook='playbook.yml')
[WARNING]: provided hosts list is empty, only localhost is available. Note that
the implicit localhost does not match 'all'

PLAY [localhost] ***************************************************************

TASK [Gathering Facts] *********************************************************
ok: [localhost]

TASK [debug] *******************************************************************
ok: [localhost] => {
    "msg": "This is a test"
}

PLAY RECAP *********************************************************************
localhost                  : ok=2    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

At this point, res.events contains the individual events generated by the playbook run and probably has all the data you could want.此时, res.events包含由 playbook 运行生成的各个事件,并且可能包含您可能想要的所有数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM