diff --git a/lib/ansible/callback_plugins/noop.py b/lib/ansible/callback_plugins/noop.py
index 54a2b254fc..8af5a133e6 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 1322a53b10..4f94c81e5f 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 9f6763c100..ec1f32bace 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 0000000000..94a415e8b4
--- /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 0000000000..3bed373bf7
--- /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 0000000000..b3049153f1
--- /dev/null
+++ b/test/test_callbacks/test_playbook.yml
@@ -0,0 +1,5 @@
+---
+- hosts: 127.0.0.1
+ connection: local
+ tasks:
+ shell: id