From 43c05d816df73a9a4268543aa5691432379cd91a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20M=C3=A4der?= Date: Sun, 18 Oct 2020 02:34:45 +0200 Subject: [PATCH] Dynamically load configuration files --- Dockerfile | 7 +-- configuration/{ => ldap}/ldap_config.py | 0 docker/configuration.docker.py | 62 ++++++++++++++++++-- {configuration => docker}/gunicorn_config.py | 0 docker/ldap_config.docker.py | 62 ++++++++++++++++++-- 5 files changed, 117 insertions(+), 14 deletions(-) rename configuration/{ => ldap}/ldap_config.py (100%) rename {configuration => docker}/gunicorn_config.py (100%) diff --git a/Dockerfile b/Dockerfile index 4347aa8..8db4cac 100644 --- a/Dockerfile +++ b/Dockerfile @@ -61,12 +61,12 @@ ARG NETBOX_PATH COPY ${NETBOX_PATH} /opt/netbox COPY docker/configuration.docker.py /opt/netbox/netbox/netbox/configuration.py -COPY configuration/gunicorn_config.py /etc/netbox/config/ +COPY docker/gunicorn_config.py /etc/netbox/ COPY docker/nginx.conf /etc/netbox-nginx/nginx.conf COPY docker/docker-entrypoint.sh /opt/netbox/docker-entrypoint.sh COPY startup_scripts/ /opt/netbox/startup_scripts/ COPY initializers/ /opt/netbox/initializers/ -COPY configuration/configuration.py /etc/netbox/config/configuration.py +COPY configuration/ /etc/netbox/config/ WORKDIR /opt/netbox/netbox @@ -79,7 +79,7 @@ RUN mkdir static && chmod -R g+w static media ENTRYPOINT [ "/opt/netbox/docker-entrypoint.sh" ] -CMD ["gunicorn", "-c /etc/netbox/config/gunicorn_config.py", "netbox.wsgi"] +CMD ["gunicorn", "-c /etc/netbox/gunicorn_config.py", "netbox.wsgi"] LABEL ORIGINAL_TAG="" \ NETBOX_GIT_BRANCH="" \ @@ -122,4 +122,3 @@ RUN apk add --no-cache \ util-linux COPY docker/ldap_config.docker.py /opt/netbox/netbox/netbox/ldap_config.py -COPY configuration/ldap_config.py /etc/netbox/config/ldap_config.py diff --git a/configuration/ldap_config.py b/configuration/ldap/ldap_config.py similarity index 100% rename from configuration/ldap_config.py rename to configuration/ldap/ldap_config.py diff --git a/docker/configuration.docker.py b/docker/configuration.docker.py index 733887f..3a4d2a2 100644 --- a/docker/configuration.docker.py +++ b/docker/configuration.docker.py @@ -1,10 +1,62 @@ +from os.path import abspath, isfile +from os import scandir import importlib.util import sys -try: - spec = importlib.util.spec_from_file_location('configuration', '/etc/netbox/config/configuration.py') +_CONFIG_DIR = '/etc/netbox/config/' +_MAIN_CONFIG = 'configuration' +_MODULE = 'netbox.configuration' +_loaded_configurations = [] + + +def __getattr__(name): + for config in _loaded_configurations: + try: + return getattr(config, name) + except: + pass + raise AttributeError + + +def _filename(f): + return f.name + + +def _import(module_name, path): + spec = importlib.util.spec_from_file_location('', path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) - sys.modules['netbox.configuration'] = module -except: - raise ImportError('') + sys.modules[module_name] = module + + _loaded_configurations.insert(0, module) + + print(f"🧬 loaded config '{path}'") + + +_main_config_path = abspath(f'{_CONFIG_DIR}/{_MAIN_CONFIG}.py') +if isfile(_main_config_path): + _import(f'{_MODULE}.configuration', _main_config_path) +else: + print(f"⚠️ Main configuration '{_main_config_path}' not found.") + +with scandir(_CONFIG_DIR) as it: + for f in sorted(it, key=_filename): + if not f.is_file(): + continue + + if f.name.startswith('__'): + continue + + if not f.name.endswith('.py'): + continue + + if f.name == f'{_MAIN_CONFIG}.py': + continue + + module_name = f"{_MODULE}.{f.name[:-len('.py')]}" + + _import(module_name, f.path) + +if len(_loaded_configurations) == 0: + print(f"‼️ No configuration files found in '{_CONFIG_DIR}'.") + raise ImportError(f"No configuration files found in '{_CONFIG_DIR}'.") diff --git a/configuration/gunicorn_config.py b/docker/gunicorn_config.py similarity index 100% rename from configuration/gunicorn_config.py rename to docker/gunicorn_config.py diff --git a/docker/ldap_config.docker.py b/docker/ldap_config.docker.py index 8d82173..601ba71 100644 --- a/docker/ldap_config.docker.py +++ b/docker/ldap_config.docker.py @@ -1,10 +1,62 @@ +from os.path import abspath, isfile +from os import scandir import importlib.util import sys -try: - spec = importlib.util.spec_from_file_location('ldap_config', '/etc/netbox/config/ldap_config.py') +_CONFIG_DIR = '/etc/netbox/config/ldap/' +_MAIN_CONFIG = 'ldap_config' +_MODULE = 'netbox.configuration.ldap' +_loaded_configurations = [] + + +def __getattr__(name): + for config in _loaded_configurations: + try: + return getattr(config, name) + except: + pass + raise AttributeError + + +def _filename(f): + return f.name + + +def _import(module_name, path): + spec = importlib.util.spec_from_file_location('', path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) - sys.modules['netbox.ldap_config'] = module -except: - raise ImportError('') + sys.modules[module_name] = module + + _loaded_configurations.insert(0, module) + + print(f"🧬 loaded config '{path}'") + + +_main_config_path = abspath(f'{_CONFIG_DIR}/{_MAIN_CONFIG}.py') +if isfile(_main_config_path): + _import(f'{_MODULE}.configuration', _main_config_path) +else: + print(f"⚠️ Main configuration '{_main_config_path}' not found.") + +with scandir(_CONFIG_DIR) as it: + for f in sorted(it, key=_filename): + if not f.is_file(): + continue + + if f.name.startswith('__'): + continue + + if not f.name.endswith('.py'): + continue + + if f.name == f'{_MAIN_CONFIG}.py': + continue + + module_name = f"{_MODULE}.{f.name[:-len('.py')]}" + + _import(module_name, f.path) + +if len(_loaded_configurations) == 0: + print(f"‼️ No configuration files found in '{_CONFIG_DIR}'.") + raise ImportError(f"No configuration files found in '{_CONFIG_DIR}'.")