繁体   English   中英

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

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

首先,这是我关于 SO 的第一个问题——它可能不完全符合 SO 标准。

我正在尝试弄清楚如何将 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'))),
    ]
)

我想这样做的原因是,Play() 不接受原始 yaml 文件,并且该示例很好地挂钩到提供的 ResultsCollectorJSONCallback(),这为我提供了一种捕获 output 的好方法。我非常很清楚有一个 Playbook Executor 但并没有完全削减它,因为所有 output 都被转储到标准输出。

这段代码可以将其捕获到每个主机的文件中(也来自文档):

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']))

我试图找到 ansible 将 yaml 转换为 python 数据结构的任何文档。 评论清楚地说“这基本上是我们的 YAML 加载程序在内部所做的。” 但我无法弄清楚他们是如何做到的,甚至试图弄清楚 PlaybookExecutor 是如何做到的,但要看到真正发生的事情非常复杂。 我希望在 ansible 的 yaml 解析例程中的某处找到一个 yaml_to_datastructure function 但未能找到它。 有人有这方面的经验吗?

问候, Sjoerd

传递给Play().load的数据只是剧本中单个剧本的内容。 也就是说,如果我有一个看起来像这样的剧本:

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

我可以像这样加载它:

>>> 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)

等等。

注意我将playbook[0]传递给Play().load (剧本中的第一个剧本),而不是整个剧本。

但是,如果您的目标是使用 Python 运行 Ansible 剧本,那么使用 ansible -runner可能会更好。 看起来像:

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

此时, res.events包含由 playbook 运行生成的各个事件,并且可能包含您可能想要的所有数据。

暂无
暂无

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

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