Instantiate callback plugins only once so we can set play/task objects on them and they'll stick.

pull/2729/merge
Michael DeHaan 11 years ago
parent df93d7dd97
commit 53ac0bbec2

@ -45,10 +45,25 @@ if cowsay and noncow == 'random':
cows = out.split()
cows.append(False)
noncow = random.choice(cows)
callback_plugins = [x for x in utils.plugins.callback_loader.all()]
def set_play(callback, play):
''' used to notify callback plugins of context '''
callback.play = play
for callback_plugin in callback_plugins:
callback_plugin.play = play
def set_task(callback, task):
''' used to notify callback plugins of context '''
callback.task = task
for callback_plugin in callback_plugins:
callback_plugin.task = task
def call_callback_module(method_name, *args, **kwargs):
for callback_plugin in utils.plugins.callback_loader.all():
for callback_plugin in callback_plugins:
methods = [
getattr(callback_plugin, method_name, None),
getattr(callback_plugin, 'on_any', None)

@ -16,8 +16,8 @@
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
import ansible.inventory
import ansible.runner
import ansible.constants as C
import ansible.runner
from ansible.utils import template
from ansible import utils
from ansible import errors
@ -214,8 +214,9 @@ class PlayBook(object):
for (play_ds, play_basedir) in zip(self.playbook, self.play_basedirs):
play = Play(self, play_ds, play_basedir)
self.callbacks.play = play
self.runner_callbacks.play = play
assert play is not None
ansible.callbacks.set_play(self.callbacks, play)
ansible.callbacks.set_play(self.runner_callbacks, play)
matched_tags, unmatched_tags = play.compare_tags(self.only_tags)
matched_tags_all = matched_tags_all | matched_tags
@ -317,8 +318,8 @@ class PlayBook(object):
def _run_task(self, play, task, is_handler):
''' run a single task in the playbook and recursively run any subtasks. '''
self.callbacks.task = task
self.runner_callbacks.task = task
ansible.callbacks.set_task(self.callbacks, task)
ansible.callbacks.set_task(self.runner_callbacks, task)
self.callbacks.on_task_start(template.template(play.basedir, task.name, task.module_vars, lookup_fatal=False), is_handler)
if hasattr(self.callbacks, 'skip_task') and self.callbacks.skip_task:
@ -402,8 +403,8 @@ class PlayBook(object):
self.callbacks.on_setup()
self.inventory.restrict_to(host_list)
self.callbacks.task = None
self.runner_callbacks.task = None
ansible.callbacks.set_task(self.callbacks, None)
ansible.callbacks.set_task(self.runner_callbacks, None)
# push any variables down to the system
setup_results = ansible.runner.Runner(

@ -22,6 +22,7 @@ import imp
import ansible.constants as C
from ansible import errors
MODULE_CACHE = {}
_basedirs = []
def push_basedir(basedir):
@ -41,7 +42,11 @@ class PluginLoader(object):
self.config = config
self.subdir = subdir
self.aliases = aliases
self._module_cache = {}
if not class_name in MODULE_CACHE:
MODULE_CACHE[class_name] = {}
self._module_cache = MODULE_CACHE[class_name]
self._extra_dirs = []
def _get_package_path(self):
@ -111,6 +116,7 @@ class PluginLoader(object):
return getattr(self._module_cache[path], self.class_name)(*args, **kwargs)
def all(self, *args, **kwargs):
for i in self._get_paths():
for path in glob.glob(os.path.join(i, "*.py")):
name, ext = os.path.splitext(os.path.basename(path))
@ -120,10 +126,54 @@ class PluginLoader(object):
self._module_cache[path] = imp.load_source('.'.join([self.package, name]), path)
yield getattr(self._module_cache[path], self.class_name)(*args, **kwargs)
action_loader = PluginLoader('ActionModule', 'ansible.runner.action_plugins', C.DEFAULT_ACTION_PLUGIN_PATH, 'action_plugins')
callback_loader = PluginLoader('CallbackModule', 'ansible.callback_plugins', C.DEFAULT_CALLBACK_PLUGIN_PATH, 'callback_plugins')
connection_loader = PluginLoader('Connection', 'ansible.runner.connection_plugins', C.DEFAULT_CONNECTION_PLUGIN_PATH, 'connection_plugins', aliases={'paramiko': 'paramiko_ssh'})
module_finder = PluginLoader('', '', C.DEFAULT_MODULE_PATH, 'library')
lookup_loader = PluginLoader('LookupModule', 'ansible.runner.lookup_plugins', C.DEFAULT_LOOKUP_PLUGIN_PATH, 'lookup_plugins')
vars_loader = PluginLoader('VarsModule', 'ansible.inventory.vars_plugins', C.DEFAULT_VARS_PLUGIN_PATH, 'vars_plugins')
filter_loader = PluginLoader('FilterModule', 'ansible.runner.filter_plugins', C.DEFAULT_FILTER_PLUGIN_PATH, 'filter_plugins')
action_loader = PluginLoader(
'ActionModule',
'ansible.runner.action_plugins',
C.DEFAULT_ACTION_PLUGIN_PATH,
'action_plugins'
)
callback_loader = PluginLoader(
'CallbackModule',
'ansible.callback_plugins',
C.DEFAULT_CALLBACK_PLUGIN_PATH,
'callback_plugins'
)
connection_loader = PluginLoader(
'Connection',
'ansible.runner.connection_plugins',
C.DEFAULT_CONNECTION_PLUGIN_PATH,
'connection_plugins',
aliases={'paramiko': 'paramiko_ssh'}
)
module_finder = PluginLoader(
'',
'',
C.DEFAULT_MODULE_PATH,
'library'
)
lookup_loader = PluginLoader(
'LookupModule',
'ansible.runner.lookup_plugins',
C.DEFAULT_LOOKUP_PLUGIN_PATH,
'lookup_plugins'
)
vars_loader = PluginLoader(
'VarsModule',
'ansible.inventory.vars_plugins',
C.DEFAULT_VARS_PLUGIN_PATH,
'vars_plugins'
)
filter_loader = PluginLoader(
'FilterModule',
'ansible.runner.filter_plugins',
C.DEFAULT_FILTER_PLUGIN_PATH,
'filter_plugins'
)

@ -0,0 +1,31 @@
# (C) 2012, Michael DeHaan, <michael.dehaan@gmail.com>
# 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 <http://www.gnu.org/licenses/>.
import os
import time
import json
class CallbackModule(object):
"""
This is a very trivial example of how any callback function can get at play and task objects.
play will be 'None' for runner invocations, and task will be None for 'setup' invocations.
"""
def on_any(self, *args, **kwargs):
play = getattr(self, 'play', None)
task = getattr(self, 'task', None)
print "play = %s, task = %s, args = %s, kwargs = %s" % (play,task,args,kwargs)
Loading…
Cancel
Save