pluginstorage.py 3.37 KB
Newer Older
1
import glob
Martin Matějek's avatar
Martin Matějek committed
2
import os
3
import logging
Martin Matějek's avatar
Martin Matějek committed
4

5
from functools import lru_cache
6

Martin Matějek's avatar
Martin Matějek committed
7
from .plugin import Plugin
8
from .notificationskeleton import NotificationSkeleton
Martin Matějek's avatar
Martin Matějek committed
9

10 11
logger = logging.getLogger(__name__)

Martin Matějek's avatar
Martin Matějek committed
12 13 14

class PluginStorage:
    """Storage for plugins"""
15
    META_ATTRS = ['name', 'version', 'timeout', 'severity', 'persistent', 'explicit_dismiss']
16

17
    def __init__(self, plugin_dir, templates_dir):
18
        # print("Constructing new PluginStorage")
Martin Matějek's avatar
Martin Matějek committed
19
        self.plugin_dir = plugin_dir
20
        self.templates_dir = templates_dir
Martin Matějek's avatar
Martin Matějek committed
21 22

        self.plugins = {}
23

Martin Matějek's avatar
Martin Matějek committed
24 25 26 27
        self.load()

    def load(self):
        """Load plugins from FS"""
28
        for filepath in glob.glob(os.path.join(self.plugin_dir, '*.yml')):
29
            p = Plugin.from_file(filepath, self.templates_dir)
Martin Matějek's avatar
Martin Matějek committed
30

31 32
            if p:
                self.plugins[p.name] = p
Martin Matějek's avatar
Martin Matějek committed
33 34

    def get_plugin(self, name):
Martin Matějek's avatar
Martin Matějek committed
35
        """Return plugin specified by name"""
Martin Matějek's avatar
Martin Matějek committed
36 37 38 39 40 41
        return self.plugins[name]

    def get_all(self):
        """Return all plugins"""
        return self.plugins

42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
    def valid_id(self, skel_id):
        try:
            plugin_name, skel_name = skel_id.split('.')
        except ValueError:
            logger.warning("Malformed skeleton id '%s'", skel_id)
            return False

        if plugin_name not in self.plugins:
            logger.warning("No such plugin '%s'", plugin_name)
            return False

        if skel_name not in self.plugins[plugin_name].get_notification_types():
            logger.warning("No such skeleton: '%s'", skel_name)
            return False

        return True

59
    @lru_cache(maxsize=256)
60 61 62
    def get_skeleton(self, skel_id):
        """
        Return notification skeleton based on id
63

64
        input param in form 'PluginName.SkeletonName'
65 66
        so it need to be parsed to get skel_id

67
        skeleton object either exists cached or will be added when needed
68
        """
69 70 71 72

        if not self.valid_id(skel_id):
            return None

73
        plugin_name, skel_name = skel_id.split('.')
74

75
        plugin = self.plugins[plugin_name]
76

77 78 79
        notification_types = plugin.get_notification_types()
        plugin_actions = plugin.get_actions()
        templates = plugin.get_templates()
80

81
        skeleton = notification_types[skel_name]
82

83 84 85
        # TODO: refactor/simplify this code
        notification_args = {}
        notification_args['plugin_name'] = plugin_name
86

87
        skel_actions = {}
88 89 90
        for action in skeleton['actions']:
            if action in plugin_actions:
                skel_actions[action] = plugin_actions[action]
91

92
        notification_args['actions'] = skel_actions
93

94 95 96
        tmpl_name = skeleton['template']
        template = templates[tmpl_name]
        notification_args['template'] = template
97

98 99 100
        for attr in self.META_ATTRS:
            if attr in skeleton:
                notification_args[attr] = skeleton[attr]
101

102
        notification_args['jinja_env'] = plugin.get_jinja_env()
103

104
        return NotificationSkeleton(**notification_args)
105

Martin Matějek's avatar
Martin Matějek committed
106
    def get_notification_types(self):
Martin Matějek's avatar
Martin Matějek committed
107
        """Return all notification types from plugins"""
108
        ret = []
Martin Matějek's avatar
Martin Matějek committed
109

110
        for name, plugin in self.plugins.items():
111
            logger.debug("%s - %s", name, plugin)
112 113 114

            args = plugin.get_notification_types()

115
            logger.debug("Plugin metadata: %s", args)
116

117 118
            type_names = ["{}.{}".format(name, type_name) for type_name in args.keys()]
            ret.extend(type_names)
Martin Matějek's avatar
Martin Matějek committed
119 120

        return ret