autoconf - controller classes

This commit is contained in:
bunkerity 2021-07-28 15:52:35 +02:00
parent 01bba1d3f6
commit a68ad53c3f
No known key found for this signature in database
GPG Key ID: 3D80806F12602A7C
5 changed files with 95 additions and 39 deletions

View File

@ -7,7 +7,8 @@ COPY confs/site/ /opt/bunkerized-nginx/confs/site
COPY jobs/ /opt/bunkerized-nginx/jobs COPY jobs/ /opt/bunkerized-nginx/jobs
COPY settings.json /opt/bunkerized-nginx/ COPY settings.json /opt/bunkerized-nginx/
COPY misc/cron /etc/crontabs/nginx COPY misc/cron /etc/crontabs/nginx
COPY autoconf/* /opt/bunkerized-nginx/entrypoint/ COPY autoconf/entrypoint.sh /opt/bunkerized-nginx/entrypoint/
COPY autoconf/src/* /opt/bunkerized-nginx/entrypoint/
RUN apk add --no-cache py3-pip bash certbot curl openssl && \ RUN apk add --no-cache py3-pip bash certbot curl openssl && \
pip3 install -r /opt/bunkerized-nginx/gen/requirements.txt && \ pip3 install -r /opt/bunkerized-nginx/gen/requirements.txt && \

View File

@ -15,6 +15,14 @@ class Controller(ABC) :
def get_env(self) : def get_env(self) :
pass pass
def _fix_env(self, env) :
fixed_env = env.copy()
blacklist = ["NGINX_VERSION", "NJS_VERSION", "PATH", "PKG_RELEASE"]
for key in blacklist :
if key in fixed_env :
del fixed_env[key]
return fixed_env
def gen_conf(self, env) : def gen_conf(self, env) :
return self.__config.gen(env) return self.__config.gen(env)

View File

@ -17,10 +17,20 @@ class DockerController(Controller) :
def get_env(self) : def get_env(self) :
env = {} env = {}
for instance in self._get_instances() : for instance in self.__get_instances() :
for variable in instance.attrs["Config"]["Env"] : for variable in instance.attrs["Config"]["Env"] :
env[variable.split("=")[0]] = variable.replace(variable.split("=")[0] + "=", "", 1) env[variable.split("=")[0]] = variable.replace(variable.split("=")[0] + "=", "", 1)
pass first_servers = []
if "SERVER_NAME" in env :
first_servers = env["SERVER_NAME"].split(" ")
for container in self.__get_containers() :
first_server = container.labels["bunkerized-nginx.SERVER_NAME"].split(" ")[0]
first_servers.append(first_server)
for variable, value in instance.labels.items() :
if variable.startswith("bunkerized-nginx.") :
env[first_server + "_" + variable.replace("bunkerized-nginx.", "", 1)] = value
env["SERVER_NAME"] = " ".join(first_servers)
return self._fix_env(env)
def process_events(self, current_env) : def process_events(self, current_env) :
old_env = current_env old_env = current_env
@ -28,5 +38,5 @@ class DockerController(Controller) :
new_env = self.get_env() new_env = self.get_env()
if new_env != old_env : if new_env != old_env :
if (self.gen_conf(new_env)) : if (self.gen_conf(new_env)) :
old_env = new_env old_env.copy(new_env)
utils.log("[*] Successfully generated new configuration") utils.log("[*] Successfully generated new configuration")

View File

@ -1,16 +1,23 @@
from kubernetes import client, config, watch from kubernetes import client, config, watch
from threading import Thread, Lock from threading import Thread, Lock
from Controller import Controller from Controller import Controller, ControllerType
class IngressController : class IngressController :
def __init__(self) : def __init__(self) :
super().__init__() super().__init__(ControllerType.KUBERNETES)
config.load_incluster_config() config.load_incluster_config()
self.__api = client.CoreV1Api() self.__api = client.CoreV1Api()
self.__extensions_api = client.ExtensionsV1beta1Api() self.__extensions_api = client.ExtensionsV1beta1Api()
self.__lock = Lock() self.__lock = Lock()
self.__old_env = {}
def __get_ingresses(self) :
return self.__extensions_api.list_ingress_for_all_namespaces(watch=False).items
def __get_services(self) :
return self.__api.list_service_for_all_namespaces(watch=False).items
def __annotations_to_env(self, annotations, service=False) : def __annotations_to_env(self, annotations, service=False) :
env = {} env = {}
@ -53,48 +60,36 @@ class IngressController :
continue continue
if "bunkerized-nginx.AUTOCONF" in service.metadata.annotations : if "bunkerized-nginx.AUTOCONF" in service.metadata.annotations :
env.update(self.__annotations_to_env(service.metadata.annotations, service=True)) env.update(self.__annotations_to_env(service.metadata.annotations, service=True))
return env return self._fix_env(env)
def __get_ingresses(self) : def process_events(self, current_env) :
return self.__extensions_api.list_ingress_for_all_namespaces(watch=False).items self.__old_env = current_env
t_ingress = Thread(target=self.__watch_ingress)
t_service = Thread(target=self.__watch_service)
t_ingress.start()
t_service.start()
t_ingress.join()
t_service.join()
def __get_services(self) :
return self.__api.list_service_for_all_namespaces(watch=False).items
def watch_ingress(self) : def __watch_ingress(self) :
w = watch.Watch() w = watch.Watch()
for event in w.stream(self.__extensions_api.list_ingress_for_all_namespaces) : for event in w.stream(self.__extensions_api.list_ingress_for_all_namespaces) :
self.__lock.acquire() self.__lock.acquire()
# print("*** NEW INGRESS EVENT ***", flush=True) new_env = self.get_env()
# for k, v in event.items() : if new_env != self.__old_env() :
# print(k + " :", flush=True) if self.gen_conf(new_env) :
# print(v, flush=True) self.__old_env.copy(new_env)
self.gen_conf() utils.log("[*] Successfully generated new configuration")
self.__lock.release() self.__lock.release()
def watch_service(self) : def __watch_service(self) :
w = watch.Watch() w = watch.Watch()
for event in w.stream(self.__api.list_service_for_all_namespaces) : for event in w.stream(self.__api.list_service_for_all_namespaces) :
self.__lock.acquire() self.__lock.acquire()
self.gen_conf() new_env = self.get_env()
# print("*** NEW SERVICE EVENT ***", flush=True) if new_env != self.__old_env() :
# for k, v in event.items() : if self.gen_conf(new_env) :
# print(k + " :", flush=True) self.__old_env.copy(new_env)
# print(v, flush=True) utils.log("[*] Successfully generated new configuration")
self.__lock.release() self.__lock.release()
ic = IngressController()
print("*** INGRESSES ***")
print(ic.get_ingresses())
print("*** SERVICES ***")
print(ic.get_services())
print("*** LISTENING FOR EVENTS ***")
t_ingress = Thread(target=ic.watch_service)
t_service = Thread(target=ic.watch_service)
t_ingress.start()
t_service.start()
t_ingress.join()
t_service.join()

View File

@ -0,0 +1,42 @@
import docker
from Controller import Controller, ControllerType
import utils
class SwarmController(Controller) :
def __init__(self) :
super().__init__(ControllerType.SWARM)
# TODO : honor env vars like DOCKER_HOST
self.__client = docker.DockerClient(base_url='unix:///var/run/docker.sock')
def __get_instances(self) :
return self.__client.services.list(filters={"label" : "bunkerized-nginx.AUTOCONF"})
def __get_services(self) :
return self.__client.services.list(filters={"label" : "bunkerized-nginx.SERVER_NAME"})
def get_env(self) :
env = {}
for instance in self.__get_instances() :
for variable in instance.attrs["Spec"]["TaskTemplate"]["ContainerSpec"]["Env"] :
env[variable.split("=")[0]] = variable.replace(variable.split("=")[0] + "=", "", 1)
first_servers = []
if "SERVER_NAME" in env :
first_servers = env["SERVER_NAME"].split(" ")
for service in self.__get_services() :
first_server = service.attrs["Spec"]["Labels"]["bunkerized-nginx.SERVER_NAME"].split(" ")[0]
first_servers.append(first_server)
for variable, value in service.attrs["Spec"]["Labels"].items() :
if variable.startswith("bunkerized-nginx.") :
env[first_server + "_" + variable.replace("bunkerized-nginx.", "", 1)] = value
env["SERVER_NAME"] = " ".join(first_servers)
return self._fix_env(env)
def process_events(self, current_env) :
old_env = current_env
for event in client.events(decode=True, filter={"type": "service", "label": ["bunkerized-nginx.AUTOCONF", "bunkerized-nginx.SERVER_NAME"]}) :
new_env = self.get_env()
if new_env != old_env :
if (self.gen_conf(new_env)) :
old_env.copy(new_env)
utils.log("[*] Successfully generated new configuration")