configpolicy/plugins/lookup/cache.py

104 lines
2.9 KiB
Python

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 <dustin@hatch.name>
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