bunkerweb/gen/Templator.py
2022-06-03 17:24:14 +02:00

136 lines
5.7 KiB
Python

import jinja2, glob, importlib, os, pathlib, copy, string, random
class Templator :
def __init__(self, templates, core, plugins, output, target, config) :
self.__templates = templates
self.__core = core
self.__plugins = plugins
self.__output = output
if not self.__output.endswith("/") :
self.__output += "/"
self.__target = target
if not self.__target.endswith("/") :
self.__target += "/"
self.__config = config
self.__jinja_env = self.__load_jinja_env()
def render(self) :
self.__render_global()
servers = [self.__config["SERVER_NAME"]]
if self.__config["MULTISITE"] == "yes" :
servers = self.__config["SERVER_NAME"].split(" ")
for server in servers :
self.__render_server(server)
def __load_jinja_env(self) :
searchpath = [self.__templates]
for subpath in glob.glob(self.__core + "/*") + glob.glob(self.__plugins + "/*") :
if os.path.isdir(subpath) :
searchpath.append(subpath + "/confs")
return jinja2.Environment(loader=jinja2.FileSystemLoader(searchpath=searchpath), lstrip_blocks=True, trim_blocks=True)
def __find_templates(self, contexts) :
templates = []
for template in self.__jinja_env.list_templates() :
if "global" in contexts and "/" not in template :
templates.append(template)
continue
for context in contexts :
if template.startswith(context + "/") :
templates.append(template)
return templates
def __write_config(self, subpath=None, config=None) :
real_path = self.__output
if subpath != None :
real_path += subpath + "/"
real_path += "variables.env"
real_config = self.__config
if config != None :
real_config = config
pathlib.Path(os.path.dirname(real_path)).mkdir(parents=True, exist_ok=True)
with open(real_path, "w") as f :
for k, v in real_config.items() :
f.write(k + "=" + v + "\n")
def __render_global(self) :
self.__write_config()
templates = self.__find_templates(["global", "http", "stream", "default-server-http"])
for template in templates :
self.__render_template(template)
def __render_server(self, server) :
templates = self.__find_templates(["modsec", "modsec-crs", "server-http", "server-stream"])
if self.__config["MULTISITE"] == "yes" :
config = copy.deepcopy(self.__config)
for variable, value in self.__config.items() :
if variable.startswith(server + "_") :
config[variable.replace(server + "_", "", 1)] = value
self.__write_config(subpath=server, config=config)
for template in templates :
subpath = None
config = None
name = None
if self.__config["MULTISITE"] == "yes" :
subpath = server
config = copy.deepcopy(self.__config)
for variable, value in self.__config.items() :
if variable.startswith(server + "_") :
config[variable.replace(server + "_", "", 1)] = value
config["NGINX_PREFIX"] = self.__target + server + "/"
server_key = server + "_SERVER_NAME"
if server_key not in self.__config :
config["SERVER_NAME"] = server
root_confs = ["server.conf", "access-lua.conf", "init-lua.conf", "log-lua.conf"]
for root_conf in root_confs :
if template.endswith("/" + root_conf) :
name = os.path.basename(template)
break
self.__render_template(template, subpath=subpath, config=config, name=name)
def __render_template(self, template, subpath=None, config=None, name=None) :
# Get real config and output folder in case it's a server config and we are in multisite mode
real_config = copy.deepcopy(self.__config)
if config :
real_config = copy.deepcopy(config)
real_config["all"] = copy.deepcopy(real_config)
real_config["import"] = importlib.import_module
real_config["is_custom_conf"] = Templator.is_custom_conf
real_config["has_variable"] = Templator.has_variable
real_config["random"] = Templator.random
real_config["read_lines"] = Templator.read_lines
real_output = self.__output
if subpath :
real_output += "/" + subpath + "/"
real_name = template
if name :
real_name = name
jinja_template = self.__jinja_env.get_template(template)
pathlib.Path(os.path.dirname(real_output + real_name)).mkdir(parents=True, exist_ok=True)
with open(real_output + real_name, "w") as f :
f.write(jinja_template.render(real_config))
def is_custom_conf(path) :
return glob.glob(path + "/*.conf")
def has_variable(all_vars, variable, value) :
if variable in all_vars and all_vars[variable] == value :
return True
if all_vars["MULTISITE"] == "yes" :
for server_name in all_vars["SERVER_NAME"].split(" ") :
if server_name + "_" + variable in all_vars and all_vars[server_name + "_" + variable] == value :
return True
return False
def random(nb) :
characters = string.ascii_letters + string.digits
return "".join(random.choice(characters) for i in range(nb))
def read_lines(file) :
try :
with open(file, "r") as f :
return f.readlines()
except :
return []