From 5a26d06c878cef0f37a388f24617cf2550a08107 Mon Sep 17 00:00:00 2001 From: bunkerity Date: Mon, 2 Aug 2021 11:52:00 +0200 Subject: [PATCH] autoconf - fix infinite lock and honor DOCKER_HOST env var --- autoconf/src/Config.py | 21 +++++++++++++++++++-- autoconf/src/Controller.py | 2 +- autoconf/src/DockerController.py | 5 ++--- autoconf/src/IngressController.py | 4 ---- autoconf/src/SwarmController.py | 7 ++----- autoconf/src/app.py | 11 ++++++----- 6 files changed, 30 insertions(+), 20 deletions(-) diff --git a/autoconf/src/Config.py b/autoconf/src/Config.py index bf9025b..2add63f 100644 --- a/autoconf/src/Config.py +++ b/autoconf/src/Config.py @@ -8,10 +8,10 @@ from logger import log class Config : - def __init__(self, type, api_uri) : + def __init__(self, type, api_uri, lock=None) : self.__type = type self.__api_uri = api_uri - + self.__lock = lock def __jobs(self) : log("config", "INFO", "starting jobs ...") @@ -28,7 +28,13 @@ class Config : return True def gen(self, env) : + locked = False try : + # Lock + if self.__lock : + self.__lock.acquire() + locked = True + # Write environment variables to a file with open("/tmp/variables.env", "w") as f : for k, v in env.items() : @@ -37,6 +43,11 @@ class Config : # Call the generator proc = subprocess.run(["/bin/su", "-c", "/opt/bunkerized-nginx/gen/main.py --settings /opt/bunkerized-nginx/settings.json --templates /opt/bunkerized-nginx/confs --output /etc/nginx --variables /tmp/variables.env", "nginx"], capture_output=True) + # Unlock + if self.__lock : + self.__lock.release() + locked = False + # Print stdout/stderr stdout = proc.stdout.decode("ascii") stderr = proc.stderr.decode("ascii") @@ -54,6 +65,8 @@ class Config : except Exception as e : log("config", "ERROR", "exception while generating site config : " + traceback.format_exc()) + if locked : + self.__lock.release() return False def reload(self, instances) : @@ -121,6 +134,8 @@ class Config : return False def __api_call(self, instances, path) : + if self.__lock : + self.__lock.acquire() ret = True urls = [] if self.__type == Controller.Type.SWARM : @@ -146,4 +161,6 @@ class Config : else : log("config", "INFO", "failed API order to " + url) ret = False + if self.__lock : + self.__lock.release() return ret diff --git a/autoconf/src/Controller.py b/autoconf/src/Controller.py index ea2cba2..a454599 100644 --- a/autoconf/src/Controller.py +++ b/autoconf/src/Controller.py @@ -11,7 +11,7 @@ class Type(Enum) : class Controller(ABC) : def __init__(self, type, api_uri=None, lock=None) : - self._config = Config(type, api_uri) + self._config = Config(type, api_uri, lock) self.lock = lock @abstractmethod diff --git a/autoconf/src/DockerController.py b/autoconf/src/DockerController.py index 69ea32f..a818fd9 100644 --- a/autoconf/src/DockerController.py +++ b/autoconf/src/DockerController.py @@ -5,10 +5,9 @@ from logger import log class DockerController(Controller.Controller) : - def __init__(self) : + def __init__(self, docker_host) : super().__init__(Controller.Type.DOCKER) - # TODO : honor env vars like DOCKER_HOST - self.__client = docker.DockerClient(base_url='unix:///var/run/docker.sock') + self.__client = docker.DockerClient(base_url=docker_host) def __get_instances(self) : return self.__client.containers.list(filters={"label" : "bunkerized-nginx.AUTOCONF"}) diff --git a/autoconf/src/IngressController.py b/autoconf/src/IngressController.py index cb2582c..9b63818 100644 --- a/autoconf/src/IngressController.py +++ b/autoconf/src/IngressController.py @@ -75,24 +75,20 @@ class IngressController(Controller.Controller) : def __watch_ingress(self) : w = watch.Watch() for event in w.stream(self.__extensions_api.list_ingress_for_all_namespaces) : - self.lock.acquire() new_env = self.get_env() if new_env != self.__old_env() : if self.gen_conf(new_env, lock=False) : self.__old_env = new_env.copy() log("CONTROLLER", "INFO", "successfully generated new configuration") - self.lock.release() def __watch_service(self) : w = watch.Watch() for event in w.stream(self.__api.list_service_for_all_namespaces) : - self.lock.acquire() new_env = self.get_env() if new_env != self.__old_env() : if self.gen_conf(new_env, lock=False) : self.__old_env = new_env.copy() log("CONTROLLER", "INFO", "successfully generated new configuration") - self.lock.release() def reload(self) : return self._reload(self.__get_ingresses()) diff --git a/autoconf/src/SwarmController.py b/autoconf/src/SwarmController.py index 0b66c1f..e3d5687 100644 --- a/autoconf/src/SwarmController.py +++ b/autoconf/src/SwarmController.py @@ -7,10 +7,9 @@ import Controller class SwarmController(Controller.Controller) : - def __init__(self, api_uri) : + def __init__(self, docker_host, api_uri) : super().__init__(Controller.Type.SWARM, api_uri=api_uri, lock=Lock()) - # TODO : honor env vars like DOCKER_HOST - self.__client = docker.DockerClient(base_url='unix:///var/run/docker.sock') + self.__client = docker.DockerClient(base_url=docker_host) def __get_instances(self) : return self.__client.services.list(filters={"label" : "bunkerized-nginx.AUTOCONF"}) @@ -45,7 +44,6 @@ class SwarmController(Controller.Controller) : for event in self.__client.events(decode=True, filters={"type": "service"}) : new_env = self.get_env() if new_env != old_env : - self.lock.acquire() log("controller", "INFO", "generating new configuration") if self.gen_conf(new_env) : old_env = new_env.copy() @@ -56,7 +54,6 @@ class SwarmController(Controller.Controller) : log("controller", "ERROR", "failed reload") else : log("controller", "ERROR", "can't generate new configuration") - self.lock.release() def reload(self) : return self._reload(self.__get_instances()) diff --git a/autoconf/src/app.py b/autoconf/src/app.py index 5bf9387..79cbcda 100644 --- a/autoconf/src/app.py +++ b/autoconf/src/app.py @@ -11,20 +11,21 @@ from IngressController import IngressController from logger import log # Get variables -swarm = os.getenv("SWARM_MODE", "no") == "yes" -kubernetes = os.getenv("KUBERNETES_MODE", "no") == "yes" -api_uri = os.getenv("API_URI", "") +swarm = os.getenv("SWARM_MODE", "no") == "yes" +kubernetes = os.getenv("KUBERNETES_MODE", "no") == "yes" +api_uri = os.getenv("API_URI", "") +docker_host = os.getenv("DOCKER_HOST", "unix:///var/run/docker.sock") # Instantiate the controller if swarm : log("autoconf", "INFO", "swarm mode detected") - controller = SwarmController(api_uri) + controller = SwarmController(docker_host, api_uri) elif kubernetes : log("autoconf", "INFO", "kubernetes mode detected") controller = IngressController(api_uri) else : log("autoconf", "INFO", "docker mode detected") - controller = DockerController() + controller = DockerController(docker_host) # Run the reload server in background if needed if swarm or kubernetes :