diff --git a/autoconf/Dockerfile b/autoconf/Dockerfile index 13fdddf..ae38592 100644 --- a/autoconf/Dockerfile +++ b/autoconf/Dockerfile @@ -7,7 +7,8 @@ COPY confs/site/ /opt/bunkerized-nginx/confs/site COPY jobs/ /opt/bunkerized-nginx/jobs COPY settings.json /opt/bunkerized-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 && \ pip3 install -r /opt/bunkerized-nginx/gen/requirements.txt && \ diff --git a/autoconf/src/Controller.py b/autoconf/src/Controller.py index 1b896eb..10c6202 100644 --- a/autoconf/src/Controller.py +++ b/autoconf/src/Controller.py @@ -15,6 +15,14 @@ class Controller(ABC) : def get_env(self) : 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) : return self.__config.gen(env) diff --git a/autoconf/src/DockerController.py b/autoconf/src/DockerController.py index 14c9de3..b5575ac 100644 --- a/autoconf/src/DockerController.py +++ b/autoconf/src/DockerController.py @@ -17,10 +17,20 @@ class DockerController(Controller) : def get_env(self) : env = {} - for instance in self._get_instances() : + for instance in self.__get_instances() : for variable in instance.attrs["Config"]["Env"] : 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) : old_env = current_env @@ -28,5 +38,5 @@ class DockerController(Controller) : new_env = self.get_env() if new_env != old_env : if (self.gen_conf(new_env)) : - old_env = new_env + old_env.copy(new_env) utils.log("[*] Successfully generated new configuration") diff --git a/autoconf/src/IngressController.py b/autoconf/src/IngressController.py index 173eb3b..b82a76a 100644 --- a/autoconf/src/IngressController.py +++ b/autoconf/src/IngressController.py @@ -1,16 +1,23 @@ from kubernetes import client, config, watch from threading import Thread, Lock -from Controller import Controller +from Controller import Controller, ControllerType class IngressController : def __init__(self) : - super().__init__() + super().__init__(ControllerType.KUBERNETES) config.load_incluster_config() self.__api = client.CoreV1Api() self.__extensions_api = client.ExtensionsV1beta1Api() 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) : env = {} @@ -53,48 +60,36 @@ class IngressController : continue if "bunkerized-nginx.AUTOCONF" in service.metadata.annotations : env.update(self.__annotations_to_env(service.metadata.annotations, service=True)) - return env + return self._fix_env(env) - def __get_ingresses(self) : - return self.__extensions_api.list_ingress_for_all_namespaces(watch=False).items + def process_events(self, current_env) : + 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() for event in w.stream(self.__extensions_api.list_ingress_for_all_namespaces) : self.__lock.acquire() -# print("*** NEW INGRESS EVENT ***", flush=True) -# for k, v in event.items() : -# print(k + " :", flush=True) -# print(v, flush=True) - self.gen_conf() + new_env = self.get_env() + if new_env != self.__old_env() : + if self.gen_conf(new_env) : + self.__old_env.copy(new_env) + utils.log("[*] Successfully generated new configuration") self.__lock.release() - def watch_service(self) : + def __watch_service(self) : w = watch.Watch() for event in w.stream(self.__api.list_service_for_all_namespaces) : self.__lock.acquire() - self.gen_conf() -# print("*** NEW SERVICE EVENT ***", flush=True) -# for k, v in event.items() : -# print(k + " :", flush=True) -# print(v, flush=True) + new_env = self.get_env() + if new_env != self.__old_env() : + if self.gen_conf(new_env) : + self.__old_env.copy(new_env) + utils.log("[*] Successfully generated new configuration") 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() diff --git a/autoconf/src/SwarmController.py b/autoconf/src/SwarmController.py new file mode 100644 index 0000000..597dafc --- /dev/null +++ b/autoconf/src/SwarmController.py @@ -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")