96 lines
3.1 KiB
Python
96 lines
3.1 KiB
Python
""" Custom Ansible Lookup Plugin for reading dotenv files.
|
|
|
|
Ansible officially supports Python 2.7 and 3.5+, but this requires Python 3.8+.
|
|
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
from typing import Sequence
|
|
|
|
from ansible.errors import AnsibleFileNotFound, AnsibleLookupError
|
|
from ansible.plugins.lookup import LookupBase
|
|
from re import compile
|
|
|
|
|
|
__all__ = "DOCUMENTATION", "EXAMPLES", "RETURN", "LookupModule"
|
|
|
|
|
|
# Options not documented will be ignored during processing.
|
|
|
|
DOCUMENTATION = """
|
|
name: dotenv
|
|
author:
|
|
- Michael Klatt <mdklatt(at)alumni.ou.edu>
|
|
short_description: Retrieve values from dotenv files
|
|
requirements:
|
|
- Anisble must be running under Python 3.8+.
|
|
description:
|
|
- Retrieve values from dotenv values.
|
|
seealso:
|
|
- name: RFC 2 - .env file
|
|
description: Smartmob RFC for a .env file standard
|
|
link: https://smartmob-rfc.readthedocs.io/en/latest/2-dotenv.html
|
|
notes:
|
|
- The RFC 2 continuation line syntax is not yet supported.
|
|
options:
|
|
_terms:
|
|
description: The key(s) to look up.
|
|
required: True
|
|
file:
|
|
description: Path to the dotenv file.
|
|
default: '.env'
|
|
""" # YAML
|
|
|
|
|
|
RETURN = """
|
|
_raw:
|
|
description:
|
|
- value(s) of the search term(s) in the dotenv file
|
|
type: list
|
|
elements: str
|
|
""" # YAML
|
|
|
|
|
|
EXAMPLES = """
|
|
- name: Retrieve value from the .env file in the current working directory.
|
|
debug:
|
|
msg: "{{ lookup('dotenv', 'VAR') }}"
|
|
- name: Use a non-default dotenv file.
|
|
debug:
|
|
msg: "{{ lookup('dotenv', 'VAR', file='path/to/.env') }}"
|
|
""" # YAML
|
|
|
|
|
|
class LookupModule(LookupBase): # class name is not arbitrary, DO NOT CHANGE
|
|
""" Look up values from a dotenv file.
|
|
|
|
"""
|
|
def run(self, terms: Sequence[str], variables=None, **options) -> list:
|
|
""" Execute the lookup.
|
|
|
|
:param terms: search terms
|
|
:param variables: mapping of defined Ansible variables
|
|
:param options: options passed directly as keyword arguments
|
|
:return: list of found values
|
|
"""
|
|
# Adapted from 'ansible.builtin.ini' lookup.
|
|
# <https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/lookup/ini.py>
|
|
# <https://docs.ansible.com/ansible/latest/dev_guide/developing_plugins.html#developing-lookup-plugins>
|
|
self.set_options(var_options=variables, direct=options)
|
|
params = self.get_options()
|
|
path = self.find_file_in_search_path(variables, "files", params["file"])
|
|
if not path:
|
|
raise AnsibleFileNotFound(f"Could not find file {params['file']}")
|
|
var_pattern = compile(r"^\s*([a-zA-Z_]+[a-zA-Z0-9_]*)\s*=\s*(\S*)")
|
|
variables = {}
|
|
for line in open(path, "rt").readlines():
|
|
# Parse the dotenv file permissively, accepting valid NAME=VALUE
|
|
# lines while ignoring everything else.
|
|
# TODO: Support RFC 2 line continuation syntax.
|
|
if match := var_pattern.match(line):
|
|
variables[match.group(1)] = match.group(2)
|
|
try:
|
|
return [variables[key] for key in terms]
|
|
except KeyError as err:
|
|
key = err.args[0]
|
|
raise AnsibleLookupError(f"No value for '{key}' in {path}") |