简体   繁体   English

如何使用子流程运行Ansible剧本

[英]How to run ansible playbooks with subprocess

I am new to ansible and no matter what I have tried I am failing to call a simple playbook through a python script. 我是ansible的新手,无论我尝试了什么,都无法通过python脚本调用简单的剧本。

Sample of code: 代码示例:

import subprocess


def sample(host, user):
    cmd = ["ansible-playbook",
           "-i {},".format(host),
           "-e ansible_user={}".format(user),
           "sample.yml",
           "-v"]

    subprocess.run(cmd)


def main():
    sample("hostname,", "user")


if __name__ == '__main__':
    main()

Sample of STDOUT: STDOUT示例:

PLAY [all] *********************************************************************

TASK [Gathering Facts] *********************************************************

The script remains like this until I terminate it. 在我终止脚本之前,脚本一直保持这样。

When I execute the ansible play book from command line $ ansible-playbook sample.yml -i "hostname," -e "user=user" I get the expected STDOUT: 当我从命令行$ ansible-playbook sample.yml -i "hostname," -e "user=user"执行$ ansible-playbook sample.yml -i "hostname," -e "user=user"我得到了预期的STDOUT:

PLAY [all] **********************************************************************************************************************************************************************************************************************************

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

TASK [debug] ********************************************************************************************************************************************************************************************************************************
ok: [hostname] => {
    "msg": "I'm on hostname"
}

PLAY RECAP **********************************************************************************************************************************************************************************************************************************
hostname              : ok=2    changed=0    unreachable=0    failed=0

My goal is to overwrite the groups with a single host this is why I am using the syntax -i "hostname," . 我的目标是用一个主机覆盖这些组,这就是为什么我使用语法-i "hostname,"

Sample of the sample.yml file: sample.yml文件的样本:

---
- hosts: all
  remote_user: '{{ ansible_user }}'
  any_errors_fatal: true
  tasks:
    - debug:
        msg: "I'm on {{ ansible_host }}"

Where I am going so wrong? 我要去哪里错了?

The passing of command-line arguments is missing. 缺少命令行参数的传递。 See sys.argv . 请参阅sys.argv The rest of the code is fine. 其余代码很好。

from sys import argv
import subprocess
[...]

def main():
    script, hostname, user = argv
    sample(hostname, user)
[...]

Notes 笔记

1) To test the playbook the extra argument should be ansible_user 1)要测试剧本,额外的参数应为ansible_user

$ ansible-playbook sample.yml -i "hostname," -e "ansible_user=user"

2) With sample("hostname,", "user") the playbook has always run at "hostname" as "user" 2)使用sample("hostname,", "user") ,剧本始终以"user"身份在"hostname"运行

3) It is possible to use -l instead of -i and avoid the coma 3)可以使用-l代替-i并避免昏迷

$ ansible-playbook sample.yml -l "hostname" -e "ansible_user=user"

4) Take a look at Ansible Runner . 4)看一看Ansible Runner

So the only thing that managed to make it work for both WSL and also LinuxOS is: 因此,唯一可以使其同时适用于WSL和LinuxOS的事情是:

#!/usr/bin/python3

import pprint
import subprocess
import sys


def sample(host, user):
    cmd = ["ansible-playbook",
           "-i {},".format(host),
           "-e ansible_user={}".format(user),
           "-e ANSIBLE_HOST_KEY_CHECKING=False",
           "sample.yml",
           "-v"]

    proc = subprocess.Popen(cmd,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            )

    try:
        outs, errs = proc.communicate(timeout=15)
        pprint.pprint(outs.decode().split('\n'))
    except subprocess.SubprocessError as errs:
        proc.kill()
        sys.exit("Error: {}".format(errs))

def main():
    sample("hostname", "user")


if __name__ == '__main__':
    main()

You can simply execute it as: 您可以简单地将其执行为:

$ python3 test.py
['Using /etc/ansible/ansible.cfg as config file',
 '',
 'PLAY [all] '
 '*********************************************************************',
 '',
 'TASK [Gathering Facts] '
 '*********************************************************',
 'ok: [hostname]',
 '',
 'TASK [debug] '
 '*******************************************************************',
 'ok: [hostname] => {',
 '    "msg": "I\'m on hostname"',
 '}',
 '',
 'PLAY RECAP '
 '*********************************************************************',
 'hostname              : ok=2    changed=0    unreachable=0    '
 'failed=0   ',
 '',
 '']

UPDATE: In case you want to have compatibility with both Python2 and Python3 the code needs to be minimized a bit: 更新:如果要同时与Python2和Python3兼容,则需要将代码最小化:

import pprint
import subprocess
import sys


def sample(host, user):
    cmd = ["ansible-playbook",
           "-i {},".format(host),
           "-e ansible_user={}".format(user),
           "-e ANSIBLE_HOST_KEY_CHECKING=False",
           "sample.yml",
           "-v"]

    proc = subprocess.Popen(cmd,
                            stdin=subprocess.PIPE,
                            stdout=subprocess.PIPE,
                            )

    try:
        if sys.version_info > (3, 0):
            # Python 3 code in this block
            outs, errs = proc.communicate(timeout=15)
            pprint.pprint(outs.decode().split('\n'))
        else:
            # Python 2 code in this block
            outs, errs = proc.communicate()
            pprint.pprint(outs.decode().split('\n'))
    except subprocess.SubprocessError as errs:
        proc.kill()
        sys.exit("Error: {}".format(errs))


def main():
    sample("hostname", "user")


if __name__ == '__main__':
    main()

Then simply you can test with the following: 然后,您可以简单地进行以下测试:

$ python test.py
['Using /etc/ansible/ansible.cfg as config file',
 '',
 'PLAY [all] *********************************************************************',
 '',
 'TASK [Gathering Facts] *********************************************************',
 'ok: [hostname]',
 '',
 'TASK [debug] *******************************************************************',
 'ok: [hostname] => {',
 '    "msg": "I\'m on hostname"',
 '}',
 '',
 'PLAY RECAP *********************************************************************',
 'hostname              : ok=2    changed=0    unreachable=0    failed=0   ',
 '',
 '']

For Python3 simply: 对于Python3而言:

$ python3 test.py
['Using /etc/ansible/ansible.cfg as config file',
 '',
 'PLAY [all] '
 '*********************************************************************',
 '',
 'TASK [Gathering Facts] '
 '*********************************************************',
 'ok: [hostname]',
 '',
 'TASK [debug] '
 '*******************************************************************',
 'ok: [hostname] => {',
 '    "msg": "I\'m on hostname"',
 '}',
 '',
 'PLAY RECAP '
 '*********************************************************************',
 'hostname              : ok=2    changed=0    unreachable=0    '
 'failed=0   ',
 '',
 '']
````

One problem that I have noticed here a minor problem is that [pycharm][1] installed on WindowsOS and running with Python2/3 2/3 Ubuntu wsl://UBUNTU/usr/bin/python is unfortunately stays frozen as shown above, but if you execute the code from terminal everything works as expected.

I have installed WSL not WSL2 maybe this problem is fixed on WSL2.


  [1]: https://www.jetbrains.com/pycharm/

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

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