autoconf - fixed infinite lock

This commit is contained in:
bunkerity 2021-08-13 10:02:14 +02:00
parent b199464a73
commit c9a6b6c27d
No known key found for this signature in database
GPG Key ID: 3D80806F12602A7C
7 changed files with 127 additions and 109 deletions

View File

@ -8,10 +8,9 @@ from logger import log
class Config :
def __init__(self, type, api_uri, lock=None, http_port="8080") :
def __init__(self, type, api_uri, http_port="8080") :
self.__type = type
self.__api_uri = api_uri
self.__lock = lock
self.__http_port = http_port
def __jobs(self) :
@ -29,14 +28,7 @@ class Config :
return True
def gen(self, env) :
locked = False
try :
# Lock
if self.__lock :
log("config", "ERROR", "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() :
@ -45,12 +37,6 @@ 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 :
log("config", "ERROR", "release")
self.__lock.release()
locked = False
# Print stdout/stderr
stdout = proc.stdout.decode("ascii")
stderr = proc.stderr.decode("ascii")
@ -68,8 +54,6 @@ 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) :
@ -137,9 +121,6 @@ class Config :
return False
def __api_call(self, instances, path) :
if self.__lock :
log("config", "ERROR", "lock")
self.__lock.acquire()
ret = True
nb = 0
urls = []
@ -174,7 +155,4 @@ class Config :
else :
log("config", "INFO", "failed API order to " + url)
ret = False
if self.__lock :
log("config", "ERROR", "release")
self.__lock.release()
return ret and nb > 0

View File

@ -11,7 +11,7 @@ class Type(Enum) :
class Controller(ABC) :
def __init__(self, type, api_uri=None, lock=None, http_port="8080") :
self._config = Config(type, api_uri, lock=lock, http_port=http_port)
self._config = Config(type, api_uri, http_port=http_port)
self.lock = lock
@abstractmethod
@ -27,7 +27,11 @@ class Controller(ABC) :
return fixed_env
def gen_conf(self, env) :
return self._config.gen(env)
try :
ret = self._config.gen(env)
except :
ret = False
return ret
@abstractmethod
def wait(self) :
@ -42,4 +46,8 @@ class Controller(ABC) :
pass
def _reload(self, instances) :
return self._config.reload(instances)
try :
ret = self._config.reload(instances)
except :
ret = False
return ret

View File

@ -42,30 +42,39 @@ class DockerController(Controller.Controller) :
for event in self.__client.events(decode=True, filters={"type": "container"}) :
new_env = self.get_env()
if new_env != old_env :
log("controller", "INFO", "generating new configuration")
if self.gen_conf(new_env) :
old_env = new_env.copy()
log("controller", "INFO", "successfully generated new configuration")
if self.reload() :
log("controller", "INFO", "successful reload")
try :
log("controller", "INFO", "generating new configuration")
if self.gen_conf(new_env) :
old_env = new_env.copy()
log("controller", "INFO", "successfully generated new configuration")
if self.reload() :
log("controller", "INFO", "successful reload")
else :
log("controller", "ERROR", "failed reload")
else :
log("controller", "ERROR", "failed reload")
else :
log("controller", "ERROR", "can't generate new configuration")
log("controller", "ERROR", "can't generate new configuration")
except :
log("controller", "ERROR", "exception while receiving event")
def reload(self) :
return self._reload(self.__get_instances())
def wait(self) :
# Wait for a container
instances = self.__get_instances()
while len(instances) == 0 :
time.sleep(1)
try :
# Wait for a container
instances = self.__get_instances()
# Generate first config
env = self.get_env()
if not self.gen_conf(env) :
return False, env
# Wait for nginx
return self._config.wait(instances), env
while len(instances) == 0 :
time.sleep(1)
instances = self.__get_instances()
# Generate first config
env = self.get_env()
if not self.gen_conf(env) :
self.lock.release()
return False, env
# Wait for nginx
self.lock.release()
return self._config.wait(instances), env
except :
pass
return False, {}

View File

@ -14,7 +14,6 @@ class IngressController(Controller.Controller) :
self.__api = client.CoreV1Api()
self.__extensions_api = client.ExtensionsV1beta1Api()
self.__old_env = {}
self.__internal_lock = Lock()
def __get_pods(self) :
return self.__api.list_pod_for_all_namespaces(watch=False, label_selector="bunkerized-nginx").items
@ -110,68 +109,83 @@ class IngressController(Controller.Controller) :
def __watch_pod(self) :
w = watch.Watch()
for event in w.stream(self.__api.list_pod_for_all_namespaces, label_selector="bunkerized-nginx") :
self.__internal_lock.acquire()
self.lock.acquire()
new_env = self.get_env()
if new_env != self.__old_env :
if self.gen_conf(new_env) :
self.__old_env = new_env.copy()
log("CONTROLLER", "INFO", "successfully generated new configuration")
if self.reload() :
log("controller", "INFO", "successful reload")
else :
log("controller", "ERROR", "failed reload")
self.__internal_lock.release()
try :
if self.gen_conf(new_env) :
self.__old_env = new_env.copy()
log("CONTROLLER", "INFO", "successfully generated new configuration")
if self.reload() :
log("controller", "INFO", "successful reload")
else :
log("controller", "ERROR", "failed reload")
except :
log("controller", "ERROR", "exception while receiving event")
self.lock.release()
def __watch_ingress(self) :
w = watch.Watch()
for event in w.stream(self.__extensions_api.list_ingress_for_all_namespaces, label_selector="bunkerized-nginx") :
self.__internal_lock.acquire()
self.lock.acquire()
new_env = self.get_env()
if new_env != self.__old_env :
if self.gen_conf(new_env) :
self.__old_env = new_env.copy()
log("CONTROLLER", "INFO", "successfully generated new configuration")
if self.reload() :
log("controller", "INFO", "successful reload")
else :
log("controller", "ERROR", "failed reload")
self.__internal_lock.release()
try :
if self.gen_conf(new_env) :
self.__old_env = new_env.copy()
log("CONTROLLER", "INFO", "successfully generated new configuration")
if self.reload() :
log("controller", "INFO", "successful reload")
else :
log("controller", "ERROR", "failed reload")
except :
log("controller", "ERROR", "exception while receiving event")
self.lock.release()
def __watch_service(self) :
w = watch.Watch()
for event in w.stream(self.__api.list_service_for_all_namespaces, label_selector="bunkerized-nginx") :
self.__internal_lock.acquire()
self.lock.acquire()
new_env = self.get_env()
if new_env != self.__old_env :
if self.gen_conf(new_env) :
self.__old_env = new_env.copy()
log("CONTROLLER", "INFO", "successfully generated new configuration")
if self.reload() :
log("controller", "INFO", "successful reload")
else :
log("controller", "ERROR", "failed reload")
self.__internal_lock.release()
try :
if self.gen_conf(new_env) :
self.__old_env = new_env.copy()
log("CONTROLLER", "INFO", "successfully generated new configuration")
if self.reload() :
log("controller", "INFO", "successful reload")
else :
log("controller", "ERROR", "failed reload")
except :
log("controller", "ERROR", "exception while receiving event")
self.lock.release()
def reload(self) :
return self._reload(self.__get_services(autoconf=True))
def wait(self) :
# Wait for at least one bunkerized-nginx pod
pods = self.__get_pods()
while len(pods) == 0 :
time.sleep(1)
self.lock.acquire()
try :
# Wait for at least one bunkerized-nginx pod
pods = self.__get_pods()
while len(pods) == 0 :
time.sleep(1)
pods = self.__get_pods()
# Wait for at least one bunkerized-nginx service
services = self.__get_services(autoconf=True)
while len(services) == 0 :
time.sleep(1)
# Wait for at least one bunkerized-nginx service
services = self.__get_services(autoconf=True)
while len(services) == 0 :
time.sleep(1)
services = self.__get_services(autoconf=True)
# Generate first config
env = self.get_env()
if not self.gen_conf(env) :
return False, env
# Generate first config
env = self.get_env()
if not self.gen_conf(env) :
return False, env
# Wait for bunkerized-nginx
return self._config.wait(services), env
# Wait for bunkerized-nginx
return self._config.wait(services), env
except :
pass
self.lock.release()
return False, {}

View File

@ -13,12 +13,10 @@ class ReloadServerHandler(socketserver.StreamRequestHandler):
if not data or not data in [b"lock", b"reload", b"unlock"] :
break
if data == b"lock" :
log("RELOADSERVER", "ERROR", "lock")
self.server.controller.lock.acquire()
locked = True
self.request.sendall(b"ok")
elif data == b"unlock" :
log("RELOADSERVER", "ERROR", "unlock")
self.server.controller.lock.release()
locked = False
self.request.sendall(b"ok")

View File

@ -44,29 +44,40 @@ 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 :
log("controller", "INFO", "generating new configuration")
if self.gen_conf(new_env) :
old_env = new_env.copy()
log("controller", "INFO", "successfully generated new configuration")
if self.reload() :
log("controller", "INFO", "successful reload")
self.lock.acquire()
try :
log("controller", "INFO", "generating new configuration")
if self.gen_conf(new_env) :
old_env = new_env.copy()
log("controller", "INFO", "successfully generated new configuration")
if self.reload() :
log("controller", "INFO", "successful reload")
else :
log("controller", "ERROR", "failed reload")
else :
log("controller", "ERROR", "failed reload")
else :
log("controller", "ERROR", "can't generate new configuration")
log("controller", "ERROR", "can't generate new configuration")
except :
log("controller", "ERROR", "exception while receiving event")
self.lock.release()
def reload(self) :
return self._reload(self.__get_instances())
def wait(self) :
# Wait for a service
instances = self.__get_instances()
while len(instances) == 0 :
time.sleep(1)
self.lock.acquire()
try :
# Wait for a service
instances = self.__get_instances()
# Generate first config
env = self.get_env()
if not self.gen_conf(env) :
return False, env
# Wait for nginx
return self._config.wait(instances), env
while len(instances) == 0 :
time.sleep(1)
instances = self.__get_instances()
# Generate first config
env = self.get_env()
if not self.gen_conf(env) :
return False, env
# Wait for nginx
return self._config.wait(instances), env
except :
pass
self.lock.release()
return False, {}

View File

@ -319,7 +319,7 @@ $ docker service create \
Or do the same with docker-compose if you wish :
```yaml
version: '3'
version: '3.8'
services: