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

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

@ -46,9 +46,24 @@ if cowsay and noncow == 'random':
cows.append(False) cows.append(False)
noncow = random.choice(cows) 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): def call_callback_module(method_name, *args, **kwargs):
for callback_plugin in utils.plugins.callback_loader.all(): for callback_plugin in callback_plugins:
methods = [ methods = [
getattr(callback_plugin, method_name, None), getattr(callback_plugin, method_name, None),
getattr(callback_plugin, 'on_any', None) getattr(callback_plugin, 'on_any', None)

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

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