diff --git a/lib/ansible/callback_plugins/noop.py b/lib/ansible/callback_plugins/noop.py index 54a2b254fc7..8af5a133e6c 100644 --- a/lib/ansible/callback_plugins/noop.py +++ b/lib/ansible/callback_plugins/noop.py @@ -21,11 +21,16 @@ class CallbackModule(object): """ this is an example ansible callback file that does nothing. You can drop other classes in the same directory to define your own handlers. Methods - you do not use can be omitted. + you do not use can be omitted. If self.disabled is set to True, the plugin + methods will not be called. example uses include: logging, emailing, storing info, etc """ + def __init__(self): + #if foo: + # self.disabled = True + pass def on_any(self, *args, **kwargs): pass diff --git a/lib/ansible/callbacks.py b/lib/ansible/callbacks.py index 1322a53b10d..4f94c81e5fb 100644 --- a/lib/ansible/callbacks.py +++ b/lib/ansible/callbacks.py @@ -144,6 +144,10 @@ def display(msg, color=None, stderr=False, screen_only=False, log_only=False, ru def call_callback_module(method_name, *args, **kwargs): for callback_plugin in callback_plugins: + # a plugin that set self.disabled to True will not be called + # see osx_say.py example for such a plugin + if getattr(callback_plugin, 'disabled', False): + continue methods = [ getattr(callback_plugin, method_name, None), getattr(callback_plugin, 'on_any', None) diff --git a/plugins/callbacks/osx_say.py b/plugins/callbacks/osx_say.py index 9f6763c100f..ec1f32bace9 100644 --- a/plugins/callbacks/osx_say.py +++ b/plugins/callbacks/osx_say.py @@ -17,19 +17,28 @@ # along with Ansible. If not, see . import subprocess +import os FAILED_VOICE="Zarvox" REGULAR_VOICE="Trinoids" HAPPY_VOICE="Cellos" LASER_VOICE="Princess" +SAY_CMD="/usr/bin/say" def say(msg, voice): - subprocess.call(["/usr/bin/say", msg, "--voice=%s" % (voice)]) + subprocess.call([SAY_CMD, msg, "--voice=%s" % (voice)]) class CallbackModule(object): """ makes Ansible much more exciting on OS X. """ + def __init__(self): + # plugin disable itself if say is not present + # ansible will not call any callback if disabled is set to True + if not os.path.exists(SAY_CMD): + self.disabled = True + print "%s does not exist, plugin %s disabled" % \ + (SAY_CMD, os.path.basename(__file__)) def on_any(self, *args, **kwargs): pass diff --git a/test/TestCallback.py b/test/TestCallback.py new file mode 100644 index 00000000000..94a415e8b48 --- /dev/null +++ b/test/TestCallback.py @@ -0,0 +1,60 @@ +# (C) 2013, Michael Scherer, + +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + + +import os +import unittest +import subprocess + +# if you change here, also change in the plugin +FILE_DISABLE = '/tmp/ansible_test_disable' +FILE_RUN = '/tmp/ansible_test_finish' + + +class TestInventory(unittest.TestCase): + + def setUp(self): + self.cwd = os.getcwd() + os.chdir(os.path.join(os.path.dirname(__file__), 'test_callbacks')) + + def clean_file(self): + if os.path.exists(FILE_RUN): + os.unlink(FILE_RUN) + if os.path.exists(FILE_DISABLE): + os.unlink(FILE_DISABLE) + + def tearDown(self): + os.chdir(self.cwd) + + def run_ansible_playbook(self): + subprocess.call('source ../../hacking/env-setup 2>&1 >/dev/null; ansible-playbook -i "127.0.0.1," test_playbook.yml 2>&1 >/dev/null', shell=True) + + def test_callback(self): + self.clean_file() + + self.run_ansible_playbook() + assert os.path.exists(FILE_RUN) + self.clean_file() + + def test_callback_disabled(self): + self.clean_file() + open(FILE_DISABLE, 'w').close() + + self.run_ansible_playbook() + assert not os.path.exists(FILE_RUN) + + self.clean_file() diff --git a/test/test_callbacks/callback_plugins/test_log.py b/test/test_callbacks/callback_plugins/test_log.py new file mode 100644 index 00000000000..3bed373bf7a --- /dev/null +++ b/test/test_callbacks/callback_plugins/test_log.py @@ -0,0 +1,27 @@ +# (C) 2013, Michael Scherer, + +# This file is part of Ansible +# +# Ansible is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Ansible is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Ansible. If not, see . + +import os + + +class CallbackModule(object): + def playbook_on_play_start(self, foo): + if os.path.exists('/tmp/ansible_test_disable'): + self.disabled = True + + def playbook_on_stats(self, stats): + open('/tmp/ansible_test_finish', 'w').close() diff --git a/test/test_callbacks/test_playbook.yml b/test/test_callbacks/test_playbook.yml new file mode 100644 index 00000000000..b3049153f15 --- /dev/null +++ b/test/test_callbacks/test_playbook.yml @@ -0,0 +1,5 @@ +--- +- hosts: 127.0.0.1 + connection: local + tasks: + shell: id