|
75 | 75 | } |
76 | 76 |
|
77 | 77 | CONFIG_FILE_NAME = 'configuration.yml' |
78 | | - |
| 78 | +CONFIG_FILE_PATH = os.path.join(os.path.dirname(__file__), CONFIG_FILE_NAME) |
| 79 | +last_config_mtime = 0 |
79 | 80 |
|
80 | 81 | def load_yaml_config(): |
81 | 82 | """Load user-provided configuration overrides from configuration.yml.""" |
@@ -176,14 +177,73 @@ def apply_env_overrides(base_config): |
176 | 177 |
|
177 | 178 |
|
178 | 179 | def load_effective_config(): |
| 180 | + """Load and merge configuration from file and environment, updating globals.""" |
| 181 | + global config, services_cfg, exclude_patterns, override_entries, manual_entries |
| 182 | + global display_cfg, STRIP_PROVIDER_SUFFIX, STRIP_SUFFIXES, label_filters |
| 183 | + global CATEGORY_LABEL_KEYS, compiled_exclude, last_config_mtime |
| 184 | + |
| 185 | + current_mtime = 0 |
| 186 | + if os.path.exists(CONFIG_FILE_PATH): |
| 187 | + current_mtime = os.path.getmtime(CONFIG_FILE_PATH) |
| 188 | + |
| 189 | + # If config file hasn't changed, no need to reload |
| 190 | + if current_mtime and current_mtime == last_config_mtime: |
| 191 | + return |
| 192 | + |
| 193 | + app.logger.info("Configuration file change detected, reloading...") |
| 194 | + last_config_mtime = current_mtime |
| 195 | + |
179 | 196 | base = copy.deepcopy(DEFAULT_CONFIG) |
180 | 197 | user_config = load_yaml_config() |
181 | 198 | if user_config: |
182 | 199 | merge_config(base, user_config) |
183 | | - return apply_env_overrides(base) |
| 200 | + |
| 201 | + config = apply_env_overrides(base) |
| 202 | + |
| 203 | + services_cfg = config.get('services', {}) if isinstance(config.get('services'), dict) else {} |
| 204 | + exclude_patterns = services_cfg.get('exclude', []) if isinstance(services_cfg.get('exclude'), list) else [] |
| 205 | + override_entries = services_cfg.get('overrides', []) if isinstance(services_cfg.get('overrides'), list) else [] |
| 206 | + manual_entries = services_cfg.get('manual', []) if isinstance(services_cfg.get('manual'), list) else [] |
| 207 | + |
| 208 | + display_cfg = services_cfg.get('display', {}) if isinstance(services_cfg.get('display'), dict) else {} |
| 209 | + STRIP_PROVIDER_SUFFIX = bool(display_cfg.get('strip_provider_suffix', True)) |
| 210 | + raw_suffixes = display_cfg.get('strip_suffixes', ['-http', '-https', '-tcp']) |
| 211 | + STRIP_SUFFIXES = [] |
| 212 | + if isinstance(raw_suffixes, str): |
| 213 | + STRIP_SUFFIXES = [raw_suffixes] |
| 214 | + elif isinstance(raw_suffixes, list): |
| 215 | + STRIP_SUFFIXES = [s for s in raw_suffixes if isinstance(s, str)] |
| 216 | + |
| 217 | + label_filters_raw = services_cfg.get('labels', []) if isinstance(services_cfg.get('labels'), list) else [] |
| 218 | + label_filters = [] |
| 219 | + for item in label_filters_raw: |
| 220 | + if not isinstance(item, str): |
| 221 | + continue |
| 222 | + text = item.strip() |
| 223 | + if not text: |
| 224 | + continue |
| 225 | + if '=' in text: |
| 226 | + key, value = text.split('=', 1) |
| 227 | + key = key.strip().lower() |
| 228 | + value = value.strip() |
| 229 | + if key: |
| 230 | + label_filters.append((key, value)) |
| 231 | + else: |
| 232 | + label_filters.append((text.lower(), None)) |
184 | 233 |
|
| 234 | + CATEGORY_LABEL_KEYS = build_category_label_keys() |
185 | 235 |
|
186 | | -config = load_effective_config() |
| 236 | + new_compiled_exclude = [] |
| 237 | + for pat in exclude_patterns: |
| 238 | + try: |
| 239 | + new_compiled_exclude.append(re.compile(pat)) |
| 240 | + except re.error: |
| 241 | + logging.getLogger(__name__).warning("Invalid exclude regex pattern skipped: %s", pat) |
| 242 | + compiled_exclude = new_compiled_exclude |
| 243 | + |
| 244 | + |
| 245 | +config = {} |
| 246 | +load_effective_config() |
187 | 247 |
|
188 | 248 | services_cfg = config.get('services', {}) if isinstance(config.get('services'), dict) else {} |
189 | 249 | exclude_patterns = services_cfg.get('exclude', []) if isinstance(services_cfg.get('exclude'), list) else [] |
@@ -800,6 +860,7 @@ def get_config(): |
800 | 860 | @app.route('/api/routes') |
801 | 861 | def get_routes(): |
802 | 862 | """Fetch routes from Traefik API""" |
| 863 | + load_effective_config() # Check for config changes on each request |
803 | 864 | try: |
804 | 865 | traefik_url = config['traefik']['api_url'] |
805 | 866 | request_timeout = config['traefik'].get('timeout', 5) |
@@ -875,7 +936,3 @@ def get_routes(): |
875 | 936 | 'routes': [], |
876 | 937 | 'count': 0 |
877 | 938 | }), 200 |
878 | | - |
879 | | -if __name__ == '__main__': |
880 | | - # Run the Flask app |
881 | | - app.run(host='0.0.0.0', port=APP_PORT, debug=False) |
|
0 commit comments