From 18af9e7b6f909d1da847440e3b3b51f7faa1fc84 Mon Sep 17 00:00:00 2001 From: Zack Cerza Date: Wed, 2 Mar 2016 15:08:38 -0700 Subject: [PATCH] Adapt failure_log plugin to work with ansible 2.0 This commit maintains backward compatibility Signed-off-by: Zack Cerza --- callback_plugins/failure_log.py | 47 +++++++++++++++++++++++++++------ 1 file changed, 39 insertions(+), 8 deletions(-) diff --git a/callback_plugins/failure_log.py b/callback_plugins/failure_log.py index 78ddbfcf..e0c62238 100644 --- a/callback_plugins/failure_log.py +++ b/callback_plugins/failure_log.py @@ -5,14 +5,21 @@ or logging. A log will not be written unless the environment variable ANSIBLE_FAILURE_LOG is present and contains a path to a file to write the log to. - -NOTE: This plugin was only tested on ansible version 1.9.2 and does not support -v2 style plugins """ import yaml import os import logging +import ansible +ANSIBLE_MAJOR = int(ansible.__version__.split('.')[0]) + +if ANSIBLE_MAJOR >= 2: + from ansible.parsing.yaml.objects import AnsibleUnicode + from ansible.plugins.callback import CallbackBase as callback_base +else: + callback_base = object + + log = logging.getLogger(__name__) # We only want to log if this env var is populated with # a file path of where the log should live. @@ -31,27 +38,51 @@ def log_failure(host, result): if fail_log: failure = {"{0}".format(host): dict()} failure[host] = result + if ANSIBLE_MAJOR >= 2: + failure = sanitize_dict(failure) log.error(yaml.safe_dump(failure)) -class CallbackModule(object): +def sanitize_dict(obj): + """ + Replace AnsibleUnicode objects with strings to avoid RepresenterError when + dumping to yaml + + Only needed in ansible >= 2.0 + """ + for key in obj.keys(): + value = obj[key] + if isinstance(value, AnsibleUnicode): + value = str(value) + obj[key] = value + elif isinstance(value, dict): + value = sanitize_dict(value) + obj[key] = value + return obj + + +class CallbackModule(callback_base): """ This Ansible callback plugin writes task failures to a yaml file. """ + CALLBACK_VERSION = 2.0 + CALLBACK_TYPE = 'notification' + CALLBACK_NAME = 'failure_log' def runner_on_failed(self, host, result, ignore_errors=False): """ A hook that will be called on every task failure. """ - if ignore_errors: return - - log_failure(host, result) + try: + log_failure(host, result) + except: + import traceback + traceback.print_exc() def runner_on_unreachable(self, host, result): """ A hook that will be called on every task that is unreachable. """ - log_failure(host, result) -- 2.47.3