Shared lib of small but usefull functions and other
This commit adds 'sharedlib' loader that allows to organize
functions into tree structure. Salt doesn't allow this as it
only imports top-level modules
https://github.com/saltstack/salt/issues/37273
See README for more details.
Change-Id: I7827c42f8f0d4caef56eff6352a49fe1a95a50cc
diff --git a/_modules/sharedlib/__init__.py b/_modules/sharedlib/__init__.py
new file mode 100644
index 0000000..609d13c
--- /dev/null
+++ b/_modules/sharedlib/__init__.py
@@ -0,0 +1,110 @@
+from inspect import getmembers, isclass, isfunction
+from functools import wraps
+
+import importlib
+import pkgutil
+import sys
+
+
+class Loader(object):
+ def __init__(self, name):
+ self.name = name
+ self.loader = pkgutil.get_loader(self.name)
+ self.path = self.loader.filename
+ sys.path.append(self.path)
+
+ def get(self, name, *args, **kwargs):
+ parts = name.split('.')
+ module_name = '.'.join(parts[:-1])
+ module = importlib.import_module(module_name)
+ module.__salt__ = __salt__
+ return getattr(module, parts[-1])
+
+ def info(self, name, *args, **kwargs):
+ return {name: getattr(self.get(name), '__doc__')}
+
+ def call(self, name, *args, **kwargs):
+ return self.get(name)(*args, **kwargs)
+
+ def list(self, *args, **kwargs):
+ classes = set()
+ functions = set()
+ for _,name,ispkg in pkgutil.walk_packages([self.path,]):
+ if ispkg:
+ continue
+ try:
+ module = importlib.import_module(name)
+ for member_name,_ in getmembers(module, isfunction):
+ functions.add('.'.join((name, member_name)))
+ for member_name,_ in getmembers(module, isclass):
+ classes.add('.'.join((name, member_name)))
+ except:
+ pass
+ return {'functions': sorted(functions), 'classes': sorted(classes)}
+
+
+LOADER = Loader('sharedlib')
+
+
+def loader_attr(name):
+ def wrapper(f):
+ @wraps(f)
+ def func_wrapper(*args, **kwargs):
+ return getattr(LOADER, name)(*args, **kwargs)
+ return func_wrapper
+ return wrapper
+
+
+def wrap_output(f):
+ @wraps(f)
+ def wrapper(*args, **kwargs):
+ return {kwargs.get('__pub_fun'): f(*args, **kwargs)}
+ return wrapper
+
+
+@wrap_output
+@loader_attr('list')
+def list(*args, **kwargs):
+ '''
+ List available functions.
+
+ .. code-block:: text
+
+ salt-call sharedlib.list
+ '''
+
+@wrap_output
+@loader_attr('info')
+def info(name, *args, **kwargs):
+ '''
+ Returns info about function.
+
+ .. code-block:: text
+
+ salt-call sharedlib.info function.name
+ '''
+
+@loader_attr('get')
+def get(name):
+ '''
+ Returns function / class object (but not calls it) for later use.
+ This is mostly useful in jinja templates.
+
+ .. code-block:: jinja
+
+ {%- set func = salt['sharedlib.get']('function.name') %}
+ {%- func(*args, **kwargs) %}
+ '''
+
+@loader_attr('call')
+def call(name, *args, **kwargs):
+ '''
+ Calls a function from library.
+
+ For more information about a function being called use 'sharedlib.info'.
+
+ .. code-block:: jinja
+
+ {%- set x = salt['sharedlib.call']('function.name', *args, **kwargs) %}
+ '''
+