136 lines
5.7 KiB
Python
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 []
|