autoconf - fixed infinite lock
This commit is contained in:
parent
b199464a73
commit
c9a6b6c27d
@ -8,10 +8,9 @@ from logger import log
|
|||||||
|
|
||||||
class Config :
|
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.__type = type
|
||||||
self.__api_uri = api_uri
|
self.__api_uri = api_uri
|
||||||
self.__lock = lock
|
|
||||||
self.__http_port = http_port
|
self.__http_port = http_port
|
||||||
|
|
||||||
def __jobs(self) :
|
def __jobs(self) :
|
||||||
@ -29,14 +28,7 @@ class Config :
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def gen(self, env) :
|
def gen(self, env) :
|
||||||
locked = False
|
|
||||||
try :
|
try :
|
||||||
# Lock
|
|
||||||
if self.__lock :
|
|
||||||
log("config", "ERROR", "lock")
|
|
||||||
self.__lock.acquire()
|
|
||||||
locked = True
|
|
||||||
|
|
||||||
# Write environment variables to a file
|
# Write environment variables to a file
|
||||||
with open("/tmp/variables.env", "w") as f :
|
with open("/tmp/variables.env", "w") as f :
|
||||||
for k, v in env.items() :
|
for k, v in env.items() :
|
||||||
@ -45,12 +37,6 @@ class Config :
|
|||||||
# Call the generator
|
# 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)
|
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
|
# Print stdout/stderr
|
||||||
stdout = proc.stdout.decode("ascii")
|
stdout = proc.stdout.decode("ascii")
|
||||||
stderr = proc.stderr.decode("ascii")
|
stderr = proc.stderr.decode("ascii")
|
||||||
@ -68,8 +54,6 @@ class Config :
|
|||||||
|
|
||||||
except Exception as e :
|
except Exception as e :
|
||||||
log("config", "ERROR", "exception while generating site config : " + traceback.format_exc())
|
log("config", "ERROR", "exception while generating site config : " + traceback.format_exc())
|
||||||
if locked :
|
|
||||||
self.__lock.release()
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def reload(self, instances) :
|
def reload(self, instances) :
|
||||||
@ -137,9 +121,6 @@ class Config :
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def __api_call(self, instances, path) :
|
def __api_call(self, instances, path) :
|
||||||
if self.__lock :
|
|
||||||
log("config", "ERROR", "lock")
|
|
||||||
self.__lock.acquire()
|
|
||||||
ret = True
|
ret = True
|
||||||
nb = 0
|
nb = 0
|
||||||
urls = []
|
urls = []
|
||||||
@ -174,7 +155,4 @@ class Config :
|
|||||||
else :
|
else :
|
||||||
log("config", "INFO", "failed API order to " + url)
|
log("config", "INFO", "failed API order to " + url)
|
||||||
ret = False
|
ret = False
|
||||||
if self.__lock :
|
|
||||||
log("config", "ERROR", "release")
|
|
||||||
self.__lock.release()
|
|
||||||
return ret and nb > 0
|
return ret and nb > 0
|
||||||
|
|||||||
@ -11,7 +11,7 @@ class Type(Enum) :
|
|||||||
class Controller(ABC) :
|
class Controller(ABC) :
|
||||||
|
|
||||||
def __init__(self, type, api_uri=None, lock=None, http_port="8080") :
|
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
|
self.lock = lock
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
@ -27,7 +27,11 @@ class Controller(ABC) :
|
|||||||
return fixed_env
|
return fixed_env
|
||||||
|
|
||||||
def gen_conf(self, env) :
|
def gen_conf(self, env) :
|
||||||
return self._config.gen(env)
|
try :
|
||||||
|
ret = self._config.gen(env)
|
||||||
|
except :
|
||||||
|
ret = False
|
||||||
|
return ret
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def wait(self) :
|
def wait(self) :
|
||||||
@ -42,4 +46,8 @@ class Controller(ABC) :
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def _reload(self, instances) :
|
def _reload(self, instances) :
|
||||||
return self._config.reload(instances)
|
try :
|
||||||
|
ret = self._config.reload(instances)
|
||||||
|
except :
|
||||||
|
ret = False
|
||||||
|
return ret
|
||||||
|
|||||||
@ -42,6 +42,7 @@ class DockerController(Controller.Controller) :
|
|||||||
for event in self.__client.events(decode=True, filters={"type": "container"}) :
|
for event in self.__client.events(decode=True, filters={"type": "container"}) :
|
||||||
new_env = self.get_env()
|
new_env = self.get_env()
|
||||||
if new_env != old_env :
|
if new_env != old_env :
|
||||||
|
try :
|
||||||
log("controller", "INFO", "generating new configuration")
|
log("controller", "INFO", "generating new configuration")
|
||||||
if self.gen_conf(new_env) :
|
if self.gen_conf(new_env) :
|
||||||
old_env = new_env.copy()
|
old_env = new_env.copy()
|
||||||
@ -52,12 +53,15 @@ class DockerController(Controller.Controller) :
|
|||||||
log("controller", "ERROR", "failed reload")
|
log("controller", "ERROR", "failed reload")
|
||||||
else :
|
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) :
|
def reload(self) :
|
||||||
return self._reload(self.__get_instances())
|
return self._reload(self.__get_instances())
|
||||||
|
|
||||||
|
|
||||||
def wait(self) :
|
def wait(self) :
|
||||||
|
try :
|
||||||
# Wait for a container
|
# Wait for a container
|
||||||
instances = self.__get_instances()
|
instances = self.__get_instances()
|
||||||
while len(instances) == 0 :
|
while len(instances) == 0 :
|
||||||
@ -66,6 +70,11 @@ class DockerController(Controller.Controller) :
|
|||||||
# Generate first config
|
# Generate first config
|
||||||
env = self.get_env()
|
env = self.get_env()
|
||||||
if not self.gen_conf(env) :
|
if not self.gen_conf(env) :
|
||||||
|
self.lock.release()
|
||||||
return False, env
|
return False, env
|
||||||
# Wait for nginx
|
# Wait for nginx
|
||||||
|
self.lock.release()
|
||||||
return self._config.wait(instances), env
|
return self._config.wait(instances), env
|
||||||
|
except :
|
||||||
|
pass
|
||||||
|
return False, {}
|
||||||
|
|||||||
@ -14,7 +14,6 @@ class IngressController(Controller.Controller) :
|
|||||||
self.__api = client.CoreV1Api()
|
self.__api = client.CoreV1Api()
|
||||||
self.__extensions_api = client.ExtensionsV1beta1Api()
|
self.__extensions_api = client.ExtensionsV1beta1Api()
|
||||||
self.__old_env = {}
|
self.__old_env = {}
|
||||||
self.__internal_lock = Lock()
|
|
||||||
|
|
||||||
def __get_pods(self) :
|
def __get_pods(self) :
|
||||||
return self.__api.list_pod_for_all_namespaces(watch=False, label_selector="bunkerized-nginx").items
|
return self.__api.list_pod_for_all_namespaces(watch=False, label_selector="bunkerized-nginx").items
|
||||||
@ -110,9 +109,10 @@ class IngressController(Controller.Controller) :
|
|||||||
def __watch_pod(self) :
|
def __watch_pod(self) :
|
||||||
w = watch.Watch()
|
w = watch.Watch()
|
||||||
for event in w.stream(self.__api.list_pod_for_all_namespaces, label_selector="bunkerized-nginx") :
|
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()
|
new_env = self.get_env()
|
||||||
if new_env != self.__old_env :
|
if new_env != self.__old_env :
|
||||||
|
try :
|
||||||
if self.gen_conf(new_env) :
|
if self.gen_conf(new_env) :
|
||||||
self.__old_env = new_env.copy()
|
self.__old_env = new_env.copy()
|
||||||
log("CONTROLLER", "INFO", "successfully generated new configuration")
|
log("CONTROLLER", "INFO", "successfully generated new configuration")
|
||||||
@ -120,14 +120,17 @@ class IngressController(Controller.Controller) :
|
|||||||
log("controller", "INFO", "successful reload")
|
log("controller", "INFO", "successful reload")
|
||||||
else :
|
else :
|
||||||
log("controller", "ERROR", "failed reload")
|
log("controller", "ERROR", "failed reload")
|
||||||
self.__internal_lock.release()
|
except :
|
||||||
|
log("controller", "ERROR", "exception while receiving event")
|
||||||
|
self.lock.release()
|
||||||
|
|
||||||
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, label_selector="bunkerized-nginx") :
|
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()
|
new_env = self.get_env()
|
||||||
if new_env != self.__old_env :
|
if new_env != self.__old_env :
|
||||||
|
try :
|
||||||
if self.gen_conf(new_env) :
|
if self.gen_conf(new_env) :
|
||||||
self.__old_env = new_env.copy()
|
self.__old_env = new_env.copy()
|
||||||
log("CONTROLLER", "INFO", "successfully generated new configuration")
|
log("CONTROLLER", "INFO", "successfully generated new configuration")
|
||||||
@ -135,14 +138,17 @@ class IngressController(Controller.Controller) :
|
|||||||
log("controller", "INFO", "successful reload")
|
log("controller", "INFO", "successful reload")
|
||||||
else :
|
else :
|
||||||
log("controller", "ERROR", "failed reload")
|
log("controller", "ERROR", "failed reload")
|
||||||
self.__internal_lock.release()
|
except :
|
||||||
|
log("controller", "ERROR", "exception while receiving event")
|
||||||
|
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, label_selector="bunkerized-nginx") :
|
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()
|
new_env = self.get_env()
|
||||||
if new_env != self.__old_env :
|
if new_env != self.__old_env :
|
||||||
|
try :
|
||||||
if self.gen_conf(new_env) :
|
if self.gen_conf(new_env) :
|
||||||
self.__old_env = new_env.copy()
|
self.__old_env = new_env.copy()
|
||||||
log("CONTROLLER", "INFO", "successfully generated new configuration")
|
log("CONTROLLER", "INFO", "successfully generated new configuration")
|
||||||
@ -150,12 +156,16 @@ class IngressController(Controller.Controller) :
|
|||||||
log("controller", "INFO", "successful reload")
|
log("controller", "INFO", "successful reload")
|
||||||
else :
|
else :
|
||||||
log("controller", "ERROR", "failed reload")
|
log("controller", "ERROR", "failed reload")
|
||||||
self.__internal_lock.release()
|
except :
|
||||||
|
log("controller", "ERROR", "exception while receiving event")
|
||||||
|
self.lock.release()
|
||||||
|
|
||||||
def reload(self) :
|
def reload(self) :
|
||||||
return self._reload(self.__get_services(autoconf=True))
|
return self._reload(self.__get_services(autoconf=True))
|
||||||
|
|
||||||
def wait(self) :
|
def wait(self) :
|
||||||
|
self.lock.acquire()
|
||||||
|
try :
|
||||||
# Wait for at least one bunkerized-nginx pod
|
# Wait for at least one bunkerized-nginx pod
|
||||||
pods = self.__get_pods()
|
pods = self.__get_pods()
|
||||||
while len(pods) == 0 :
|
while len(pods) == 0 :
|
||||||
@ -175,3 +185,7 @@ class IngressController(Controller.Controller) :
|
|||||||
|
|
||||||
# Wait for bunkerized-nginx
|
# Wait for bunkerized-nginx
|
||||||
return self._config.wait(services), env
|
return self._config.wait(services), env
|
||||||
|
except :
|
||||||
|
pass
|
||||||
|
self.lock.release()
|
||||||
|
return False, {}
|
||||||
|
|||||||
@ -13,12 +13,10 @@ class ReloadServerHandler(socketserver.StreamRequestHandler):
|
|||||||
if not data or not data in [b"lock", b"reload", b"unlock"] :
|
if not data or not data in [b"lock", b"reload", b"unlock"] :
|
||||||
break
|
break
|
||||||
if data == b"lock" :
|
if data == b"lock" :
|
||||||
log("RELOADSERVER", "ERROR", "lock")
|
|
||||||
self.server.controller.lock.acquire()
|
self.server.controller.lock.acquire()
|
||||||
locked = True
|
locked = True
|
||||||
self.request.sendall(b"ok")
|
self.request.sendall(b"ok")
|
||||||
elif data == b"unlock" :
|
elif data == b"unlock" :
|
||||||
log("RELOADSERVER", "ERROR", "unlock")
|
|
||||||
self.server.controller.lock.release()
|
self.server.controller.lock.release()
|
||||||
locked = False
|
locked = False
|
||||||
self.request.sendall(b"ok")
|
self.request.sendall(b"ok")
|
||||||
|
|||||||
@ -44,6 +44,8 @@ class SwarmController(Controller.Controller) :
|
|||||||
for event in self.__client.events(decode=True, filters={"type": "service"}) :
|
for event in self.__client.events(decode=True, filters={"type": "service"}) :
|
||||||
new_env = self.get_env()
|
new_env = self.get_env()
|
||||||
if new_env != old_env :
|
if new_env != old_env :
|
||||||
|
self.lock.acquire()
|
||||||
|
try :
|
||||||
log("controller", "INFO", "generating new configuration")
|
log("controller", "INFO", "generating new configuration")
|
||||||
if self.gen_conf(new_env) :
|
if self.gen_conf(new_env) :
|
||||||
old_env = new_env.copy()
|
old_env = new_env.copy()
|
||||||
@ -54,11 +56,16 @@ class SwarmController(Controller.Controller) :
|
|||||||
log("controller", "ERROR", "failed reload")
|
log("controller", "ERROR", "failed reload")
|
||||||
else :
|
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) :
|
def reload(self) :
|
||||||
return self._reload(self.__get_instances())
|
return self._reload(self.__get_instances())
|
||||||
|
|
||||||
def wait(self) :
|
def wait(self) :
|
||||||
|
self.lock.acquire()
|
||||||
|
try :
|
||||||
# Wait for a service
|
# Wait for a service
|
||||||
instances = self.__get_instances()
|
instances = self.__get_instances()
|
||||||
while len(instances) == 0 :
|
while len(instances) == 0 :
|
||||||
@ -70,3 +77,7 @@ class SwarmController(Controller.Controller) :
|
|||||||
return False, env
|
return False, env
|
||||||
# Wait for nginx
|
# Wait for nginx
|
||||||
return self._config.wait(instances), env
|
return self._config.wait(instances), env
|
||||||
|
except :
|
||||||
|
pass
|
||||||
|
self.lock.release()
|
||||||
|
return False, {}
|
||||||
|
|||||||
@ -319,7 +319,7 @@ $ docker service create \
|
|||||||
|
|
||||||
Or do the same with docker-compose if you wish :
|
Or do the same with docker-compose if you wish :
|
||||||
```yaml
|
```yaml
|
||||||
version: '3'
|
version: '3.8'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user