diegus
diegus

Reputation: 1188

Ansible python API 2.0: run a playbook in a python script for windows clients

I am trying to re-write this script (How to use Ansible 2.0 Python API to run a Playbook?) to call an ansible playbook within a python script that runs against windows clients. I have a test folder that contains the playbook (deploy.yml) the host file (hosts) and additional variables (ansible_user,ansible_port..) in the subfolder group_vars/win_clones.yml.

I would like to point to these files to run my playbook within the python script. I did so for deploy.yml and hosts files but I don't know where to point to group_vars/win_clones.yml. How can i make this work?

from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars import VariableManager
from ansible.inventory import Inventory
from ansible.executor.playbook_executor import PlaybookExecutor 

variable_manager = VariableManager()
loader = DataLoader()

inventory = Inventory(loader=loader, variable_manager=variable_manager,  host_list='fullpath/to/hosts')
playbook_path = 'fullpath/to/deploy.yml'

if not os.path.exists(playbook_path):
    print '[INFO] The playbook does not exist'
    sys.exit()

Options = namedtuple('Options', ['listtags', 'listtasks', 'listhosts', 'syntax', 'connection','module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check'])
options = Options(listtags=False, listtasks=False, listhosts=False, syntax=False, connection='ssh', module_path=None, forks=100, remote_user='slotlocker', private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=True, become_method=None, become_user='root', verbosity=None, check=False)

variable_manager.extra_vars = {'ansible_user': 'ansible', 'ansible_port': '5986', 'ansible_connection': 'winrm', 'ansible_password': 'pass', 'ansible_winrm_server_cert_validation': 'ignore'} # Here are the variables used in the winclones.yml

passwords = {}

pbex = PlaybookExecutor(playbooks=[playbook_path], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords)
results = pbex.run()

EDIT 1

This is the output of the play run through python script:

TASK [setup]     *******************************************************************
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AttributeError: 'NoneType' object has no attribute 'upper'
fatal: [cl3]: FAILED! => {"failed": true, "msg": "Unexpected failure during module execution.", "stdout": ""}
An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AttributeError: 'NoneType' object has no attribute 'upper'
fatal: [cl1]: FAILED! => {"failed": true, "msg": "Unexpected failure during module execution.", "stdout": ""}

Upvotes: 3

Views: 3977

Answers (1)

ashokkumarprajapati
ashokkumarprajapati

Reputation: 316

I have had same issue while using Ansible python APIs. After a long research and some dig into ansible code, i found the possible cause. As per Ansible Documentation you should, set become_method when supplying become and become_user, you should also set become_method value. In general CLI command this would read from ansible.cfg file. However in API case, you set become_method as None explicitly, which is internally called while becoming as specific user (root in your case).

Set become_method as one of the values from (sudo, , su, pbrun, pfexec, doas,dzdo) and it should work fine.

from collections import namedtuple
from ansible.parsing.dataloader import DataLoader
from ansible.vars import VariableManager
from ansible.inventory import Inventory
from ansible.playbook.play import Play
from ansible.executor.playbook_executor import PlaybookExecutor 

variable_manager = VariableManager()
loader = DataLoader()

inventory = Inventory(loader=loader, variable_manager=variable_manager,      host_list='fullpath/to/hosts')
playbook_path = 'fullpath/to/deploy.yml'

if not os.path.exists(playbook_path):
    print '[INFO] The playbook does not exist'
    sys.exit()

Options = namedtuple('Options', ['listtags', 'listtasks', 'listhosts', 'syntax', 'connection','module_path', 'forks', 'remote_user', 'private_key_file', 'ssh_common_args', 'ssh_extra_args', 'sftp_extra_args', 'scp_extra_args', 'become', 'become_method', 'become_user', 'verbosity', 'check'])
options = Options(listtags=False, listtasks=False, listhosts=False, syntax=False, connection='ssh', module_path=None, forks=100, remote_user='slotlocker', private_key_file=None, ssh_common_args=None, ssh_extra_args=None, sftp_extra_args=None, scp_extra_args=None, become=True, become_method='sudo', become_user='root', verbosity=None, check=False)

variable_manager.extra_vars = {'ansible_user': 'ansible', 'ansible_port': '5986', 'ansible_connection': 'winrm', 'ansible_password': 'pass', 'ansible_winrm_server_cert_validation': 'ignore'} # Here are the variables used in the winclones.yml

passwords = {}

pbex = PlaybookExecutor(playbooks=[playbook_path], inventory=inventory, variable_manager=variable_manager, loader=loader, options=options, passwords=passwords)
results = pbex.run()

Upvotes: 4

Related Questions