import functools import hashlib from ansible.constants import config from ansible.errors import AnsibleError from ansible.plugins.loader import cache_loader, lookup_loader from ansible.plugins.lookup import LookupBase, display DOCUMENTATION = """ lookup: cache author: Dustin C. Hatch options: cache_plugin: description: - Cache plugin to use type: str required: false default: memory env: - name: ANSIBLE_LOOKUP_CACHE_PLUGIN ini: - section: lookup key: cache_plugin cache_timeout: description: - Cache duration in seconds default: 3600 type: int env: - name: ANSIBLE_LOOKUP_CACHE_TIMEOUT ini: - section: lookup key: cache_timeout cache_connection: description: - Cache connection data or path, read cache plugin documentation for specifics. type: str env: - name: ANSIBLE_LOOKUP_CACHE_CONNECTION ini: - section: lookup key: cache_connection cache_prefix: description: - Prefix to use for cache plugin files/tables default: '' env: - name: ANSIBLE_LOOKUP_CACHE_PREFIX ini: - section: lookup key: cache_prefix """ def _get_option(key: str): return config.get_config_value( key, plugin_type='lookup', plugin_name='cache' ) @functools.cache def _get_cache(): cache_plugin = _get_option('cache_plugin') cache_options = {} if cache_connection := _get_option('cache_connection'): cache_options['_uri'] = cache_connection if cache_timeout := _get_option('cache_timeout'): cache_options['_timeout'] = cache_timeout if cache_prefix := _get_option('cache_prefix'): cache_options['_prefix'] = cache_prefix return cache_loader.get(cache_plugin, **cache_options) class LookupModule(LookupBase): def run(self, terms, variables=None, **kwargs): cache = _get_cache() display.v(f'lookup cache: using cache plugin {cache.plugin_name}') h = hashlib.sha1() h.update(str((terms, kwargs)).encode('utf-8')) key = h.hexdigest() try: result = cache.get(key) except KeyError: result = None if result is None: lookup_name, terms = terms[0], terms[1:] lookup = lookup_loader.get( lookup_name, loader=self._loader, templar=self._templar ) if lookup is None: raise AnsibleError( f'Could not find lookup plugin {lookup_name!r}' ) result = lookup.run(terms, variables=variables, **kwargs) cache.set(key, result) else: str_terms = ', '.join(repr(t) for t in terms) str_kwargs = ', '.join(f'{k}={v!r}' for k, v in kwargs.items()) display.v( 'lookup cache: found cached value for' f' lookup({str_terms}, {str_kwargs})' ) return result