Skip to content

Instantly share code, notes, and snippets.

@ashcrow
Created July 22, 2016 20:36
Show Gist options
  • Save ashcrow/3c03534824a00104efafe4f9e3ecac1e to your computer and use it in GitHub Desktop.
Save ashcrow/3c03534824a00104efafe4f9e3ecac1e to your computer and use it in GitHub Desktop.
Idea for using the CLI methods instead of the Ansible API directly
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'])
@ashcrow
Copy link
Author

ashcrow commented Jul 22, 2016

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

@mbarnes
Copy link

mbarnes commented Jul 25, 2016

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?

@ashcrow
Copy link
Author

ashcrow commented Jul 25, 2016

It does utilize the TaskQueueManager. I believe it would be easier to use since the CLI api doesn't change often.

@ashcrow
Copy link
Author

ashcrow commented Jul 30, 2016

@katrinahayes
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment