-
-
Save ashcrow/3c03534824a00104efafe4f9e3ecac1e to your computer and use it in GitHub Desktop.
import logging | |
import os | |
# HACK: MONKEY PATCH to catch output | |
from ansible.utils.display import Display | |
class LogForward(Display): | |
""" | |
Quick hack of a log forwarder | |
""" | |
def display(self, msg, screen_only=None, *args, **kwargs): | |
""" | |
Pass display data to the logger. | |
:param msg: The message to log. | |
:type msg: str | |
:param args: All other non-keyword arguments. | |
:type args: list | |
:param kwargs: All other keyword arguments. | |
:type kwargs: dict | |
""" | |
# Ignore if it is screen only output | |
if screen_only: | |
return | |
logging.getLogger('transport').info(msg) | |
# Forward it all to display | |
info = display | |
warning = display | |
error = display | |
# # Ignore debug | |
debug = lambda s, *a, **k: True | |
# Set up our logging | |
logger = logging.getLogger('transport') | |
logger.setLevel(logging.INFO) | |
handler = logging.StreamHandler() | |
handler.formatter = logging.Formatter('%(name)s - %(message)s') | |
logger.addHandler(handler) | |
display = LogForward() | |
# END MONKEY PATCH | |
# Real code starts | |
from ansible.cli.playbook import PlaybookCLI | |
from ansible.errors import AnsibleOptionsError, AnsibleParserError | |
def execute_playbook(playbook, hosts): | |
""" | |
:param playbook: Full path to the playbook to execute. | |
:type playbook: str | |
:param hosts: A host or hosts to target the playbook against. | |
:type hosts: str, list, or tuple | |
""" | |
# Set hosts args up right for the ansible parser | |
if isinstance(hosts, basestring): | |
hosts = hosts + ',' | |
elif hasattr(hosts, '__iter__'): | |
hosts = ','.join(hosts) | |
else: | |
raise Exception('Can not parse hosts of type {}'.format(type(hosts))) | |
# Create the cli object | |
cli_args = ['playbook', '-i', hosts, os.path.realpath(playbook)] | |
logger.info('Executing: {}'.format(' '.join(cli_args))) | |
cli = PlaybookCLI(cli_args) | |
# Parse args and run it | |
try: | |
cli.parse() | |
cli.run() | |
except AnsibleParserError as error: | |
print(error) | |
raise error | |
except AnsibleOptionsError as error: | |
print(error) | |
raise error | |
if __name__ == '__main__': | |
# This would execute the ping.yaml playbook in the CWD | |
# against the hosts 127.0.0.1 and 127.0.0.2 | |
execute_playbook('ping.yaml', ['127.0.0.1', '127.0.0.2']) |
Looks pretty straight-forward. Is this API any more stable than what we were using before?
Reading Ansible code, it appears PlaybookCLI.run()
returns the same TaskQueueManager
integer status that we've been using?
It does utilize the TaskQueueManager
. I believe it would be easier to use since the CLI api doesn't change often.
@mbarnes / @cooktheryan Updated exmple and post on it at https://stevemilner.org/2016/07/30/programmatic-ansible-middle-ground/
I'm working on a setup almost identical to this, and it works beautifully. However, I've been unable to pass options to cli_args that contain parameters, eg '--start-at-task="generate."' The parameter isn't passed, so start-at-task simply skips all of my tasks. How do I pass that parameter? I've tried a number of different variations.
/cc @mbarnes @cooktheryan
This would give us the ability to execute as if we were running commands but without exposing our calls to the underlying system.