feat: add option to load templates from remote git sources

This commit is contained in:
Robert Kaussow 2023-01-22 16:29:08 +01:00
parent 878cce1791
commit ca6662145a
Signed by: xoxys
GPG Key ID: 4E692A2EAECC03C0
3 changed files with 53 additions and 39 deletions

View File

@ -27,6 +27,10 @@ class Config():
- provides cli parameters - provides cli parameters
""" """
TEMPLATE_SRC = os.path.join(
os.path.dirname(os.path.realpath(__file__)), *["templates", "readme"]
)
SETTINGS = { SETTINGS = {
"config_file": { "config_file": {
"default": "", "default": "",
@ -67,15 +71,9 @@ class Config():
"file": True, "file": True,
"type": environs.Env().str "type": environs.Env().str
}, },
"template_dir": { "template_src": {
"default": os.path.join(os.path.dirname(os.path.realpath(__file__)), "templates"), "default": f"local>{TEMPLATE_SRC}",
"env": "TEMPLATE_DIR", "env": "template_src",
"file": True,
"type": environs.Env().str
},
"template": {
"default": "readme",
"env": "TEMPLATE",
"file": True, "file": True,
"type": environs.Env().str "type": environs.Env().str
}, },
@ -163,6 +161,7 @@ class Config():
self.config = None self.config = None
self._set_config() self._set_config()
self.is_role = self._set_is_role() or False self.is_role = self._set_is_role() or False
self.template = self._set_template()
def _get_args(self, args): def _get_args(self, args):
cleaned = dict(filter(lambda item: item[1] is not None, args.items())) cleaned = dict(filter(lambda item: item[1] is not None, args.items()))
@ -257,7 +256,7 @@ class Config():
if self._validate(args): if self._validate(args):
anyconfig.merge(defaults, args, ac_merge=anyconfig.MS_DICTS) anyconfig.merge(defaults, args, ac_merge=anyconfig.MS_DICTS)
fix_files = ["output_dir", "template_dir", "custom_header"] fix_files = ["output_dir", "custom_header"]
for file in fix_files: for file in fix_files:
if defaults[file] and defaults[file] != "": if defaults[file] and defaults[file] != "":
defaults[file] = self._normalize_path(defaults[file]) defaults[file] = self._normalize_path(defaults[file])
@ -320,15 +319,32 @@ class Config():
annotations.append(k) annotations.append(k)
return annotations return annotations
def get_template(self): def _set_template(self):
""" allowed_provider = ["local", "git"]
Get the base dir for the template to use.
:return: str abs path try:
""" provider, path = self.config.get("template_src").split(">", 1)
template_dir = self.config.get("template_dir") except ValueError as e:
template = self.config.get("template") raise ansibledoctor.exception.ConfigError(
return os.path.realpath(os.path.join(template_dir, template)) "Malformed option 'template_src'", str(e)
) from e
provider = provider.strip().lower()
path = path.strip()
if provider not in allowed_provider:
raise ansibledoctor.exception.ConfigError(
f"Unknonw template provider '{provider}'",
f"the template provider has to be one of [{', '.join(allowed_provider)}]"
)
if provider == "local":
path = self._normalize_path(os.path.realpath(path))
if provider == "git":
pass
return provider, path
class SingleConfig(Config, metaclass=Singleton): class SingleConfig(Config, metaclass=Singleton):

View File

@ -2,7 +2,6 @@
"""Prepare output and write compiled jinja2 templates.""" """Prepare output and write compiled jinja2 templates."""
import glob import glob
import ntpath
import os import os
import re import re
from functools import reduce from functools import reduce
@ -36,19 +35,18 @@ class Generator:
:return: None :return: None
""" """
template_dir = self.config.get_template() provider, template_src = self.config.template
if os.path.isdir(template_dir): if os.path.isdir(template_src):
self.logger.info(f"Using template dir: {template_dir}") self.logger.info(f"Using template dir: {template_src}")
else: else:
self.log.sysexit_with_message(f"Can not open template dir {template_dir}") self.log.sysexit_with_message(f"Can not open template dir {template_src}")
for file in glob.iglob(template_dir + "/**/*." + self.extension, recursive=True): for workfile in glob.iglob(f"{template_src}/**/*.{self.extension}", recursive=True):
relative_file = file[len(template_dir) + 1:] if not os.path.basename(workfile).startswith("_"):
if ntpath.basename(file)[:1] != "_": self.logger.debug(f"Found template file: {os.path.basename(workfile)}")
self.logger.debug(f"Found template file: {relative_file}") self.template_files.append(workfile)
self.template_files.append(relative_file)
else: else:
self.logger.debug(f"Ignoring template file: {relative_file}") self.logger.debug(f"Ignoring template file: {os.path.basename(workfile)}")
def _create_dir(self, directory): def _create_dir(self, directory):
if not self.config.config["dry_run"] and not os.path.isdir(directory): if not self.config.config["dry_run"] and not os.path.isdir(directory):
@ -94,25 +92,25 @@ class Generator:
self.logger.debug(str(e)) self.logger.debug(str(e))
self.log.sysexit_with_message("Aborted...") self.log.sysexit_with_message("Aborted...")
for file in self.template_files: for workfile in self.template_files:
doc_file = os.path.join( doc_file = os.path.join(
self.config.config.get("output_dir"), self.config.config.get("output_dir"),
os.path.splitext(file)[0] os.path.splitext(os.path.basename(workfile))[0]
) )
source_file = self.config.get_template() + "/" + file
self.logger.debug(f"Writing doc output to: {doc_file} from: {source_file}") self.logger.debug(f"Writing doc output to: {doc_file} from: {workfile}")
# make sure the directory exists # make sure the directory exists
self._create_dir(os.path.dirname(doc_file)) self._create_dir(os.path.dirname(doc_file))
if os.path.exists(source_file) and os.path.isfile(source_file): if os.path.exists(workfile) and os.path.isfile(workfile):
with open(source_file) as template: with open(workfile) as template:
data = template.read() data = template.read()
if data is not None: if data is not None:
try: try:
provider, template_src = self.config.template
jenv = Environment( # nosec jenv = Environment( # nosec
loader=FileSystemLoader(self.config.get_template()), loader=FileSystemLoader(template_src),
lstrip_blocks=True, lstrip_blocks=True,
trim_blocks=True, trim_blocks=True,
autoescape=jinja2.select_autoescape() autoescape=jinja2.select_autoescape()
@ -133,7 +131,7 @@ class Generator:
) as e: ) as e:
self.log.sysexit_with_message( self.log.sysexit_with_message(
"Jinja2 templating error while loading file: '{}'\n{}".format( "Jinja2 templating error while loading file: '{}'\n{}".format(
file, str(e) workfile, str(e)
) )
) )
except UnicodeEncodeError as e: except UnicodeEncodeError as e:

View File

@ -37,7 +37,7 @@ logging:
# Path to write rendered template file. Default is the current working directory. # Path to write rendered template file. Default is the current working directory.
output_dir: output_dir:
# Default is built-in templates directory. # Default is built-in templates directory.
template_dir: template_src:
template: readme template: readme
# Don't ask to overwrite if output file exists. # Don't ask to overwrite if output file exists.
@ -93,7 +93,7 @@ ANSIBLE_DOCTOR_DRY_RUN=false
ANSIBLE_DOCTOR_LOG_LEVEL=warning ANSIBLE_DOCTOR_LOG_LEVEL=warning
ANSIBLE_DOCTOR_LOG_JSON=false ANSIBLE_DOCTOR_LOG_JSON=false
ANSIBLE_DOCTOR_OUTPUT_DIR= ANSIBLE_DOCTOR_OUTPUT_DIR=
ANSIBLE_DOCTOR_TEMPLATE_DIR= ANSIBLE_DOCTOR_template_src=
ANSIBLE_DOCTOR_TEMPLATE=readme ANSIBLE_DOCTOR_TEMPLATE=readme
ANSIBLE_DOCTOR_FORCE_OVERWRITE=false ANSIBLE_DOCTOR_FORCE_OVERWRITE=false
ANSIBLE_DOCTOR_CUSTOM_HEADER= ANSIBLE_DOCTOR_CUSTOM_HEADER=