I use a playbook runner like so:
stats = callbacks.AggregateStats()
playbook_cb = callbacks.PlaybookCallbacks(verbose=1)
runner_cb = callbacks.PlaybookRunnerCallbacks(stats, verbose=1)
pb = ansible.playbook.PlayBook(
... # basic info
)
results = pb.run()
The results variable contains output like the following:
{"status": 1, "result": {"127.0.0.1": {"unreachable": 0, "skipped": 0, "ok": 3, "changed": 2, "failures": 0}}}
Which is fine. But I also need the task level output like the dict shown below:
changed: [127.0.0.1] => {"changed": true, "name": "apache2", "state": "started"}
I tried changing the verbosity, but that was not what I wanted.
After digging around I managed to get the output to a log file like so:
from ansible import constants as C
C.DEFAULT_LOG_PATH = 'project.log'
reload(callbacks)
But I need access to it in my code.
You can use the Ansible Python API to control nodes, you can extend Ansible to respond to various Python events, you can write plugins, and you can plug in inventory data from external data sources. This document gives a basic overview and examples of the Ansible execution and playbook API.
How do I keep secret data in my playbook? ¶ If you would like to keep secret data in your Ansible content and still share it publicly or keep things in source control, see Vault. This can be used to keep verbose output but hide sensitive information from others who would otherwise like to be able to see the output.
While you can write Ansible modules in any language, most Ansible modules are written in Python, including the ones central to letting Ansible work. By default, Ansible assumes it can find a /usr/bin/python on your remote system that is either Python2, version 2.6 or higher or Python3, 3.5 or higher.
By default Ansible modules require python to be present in the target machines, since they are all written in python.
You probably can't get exactly the json format you wanted, but you can get the same information by extending the callback classes and write your own handlers to events that you are interested.
Also make sure that you give the classes to the Playbook instance like this:
pb = ansible.playbook.PlayBook(
... # basic info
callbacks= playbook_cb,
runner_callbacks=runner_cb
)
Links:
Edit: In this case the solution was to extend the AggregateStat class instead. Code examples below provided by @Tom_Sawyyer
from ansible.callbacks import AggregateStats
class CustomAggregateStats(AggregateStats):
"""
Holds stats about per-host activity during playbook runs.
"""
def __init__(self):
super(CustomAggregateStats, self).__init__()
self.results = {}
def compute(self, runner_results, setup=False, poll=False,
ignore_errors=False):
"""
Walk through all results and increment stats.
"""
super(CustomAggregateStats, self).compute(runner_results, setup, poll,
ignore_errors)
for (host, value) in runner_results.get('contacted', {}).iteritems():
if 'invocation' in value:
if value['invocation']['module_name'] == 'service':
self.results['service_name'] = value['name']
def summarize(self, host):
"""
Return information about a particular host
"""
summarized_info = super(CustomAggregateStats, self).summarize(host)
# Adding the info I need
summarized_info['result'] = self.results
return summarized_info
And finally:
my_stats = CustomAggregateStats()
pb = ansible.playbook.PlayBook(
... # basic info
stats=my_stats,
)
Giving output:
{"127.0.0.1": {"skipped": 0, "ok": 3, "changed": 2, "result": {"service_name": "apache2"}, "failures": 0, "unreachable": 0}}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With