From 8c31a4f2b9c4a3eb50d8b28a5e2d42b4132ea5bb Mon Sep 17 00:00:00 2001 From: Floke Date: Sat, 3 Jan 2026 09:30:34 +0000 Subject: [PATCH] refactor(config): Switch to environment variables for API keys - Modifies docker-compose.yml to use for injecting the Gemini API key, which is more robust than volume mounting. - Updates helpers.py to prioritize reading the API key from the environment variable. - Removes the now-redundant file-based key loading logic from config.py and the Dockerfile. - This change completely bypasses the problematic file system interactions within the container, providing a definitive fix for the 'API Key missing' error. --- config.py | 23 +---------------------- docker-compose.yml | 10 ++++------ gtm-architect/Dockerfile | 1 - helpers.py | 40 ++++++++++++++++++++++++---------------- 4 files changed, 29 insertions(+), 45 deletions(-) diff --git a/config.py b/config.py index 46b4c17a..b1ab04bd 100644 --- a/config.py +++ b/config.py @@ -482,30 +482,9 @@ class Config: "NetCologne" ] - # --- API Schlüssel Speicherung (werden in main() geladen) --- + # --- API Schlüssel Speicherung (werden jetzt via Env Var geladen) --- API_KEYS = {} - @classmethod - def load_api_keys(cls): - """Laedt API-Schluessel aus den definierten Dateien.""" - logger = logging.getLogger(__name__) - logger.info("Lade API-Schluessel...") - print(f"DEBUG: Attempting to load API keys. BASE_DIR: {BASE_DIR}") # Debug print - cls.API_KEYS['openai'] = cls._load_key_from_file(API_KEY_FILE) - cls.API_KEYS['serpapi'] = cls._load_key_from_file(SERP_API_KEY_FILE) - cls.API_KEYS['genderize'] = cls._load_key_from_file(GENDERIZE_API_KEY_FILE) - - if cls.API_KEYS.get('openai'): - openai.api_key = cls.API_KEYS['openai'] - logger.info("OpenAI API Key erfolgreich geladen.") - else: - logger.warning("OpenAI API Key konnte nicht geladen werden. OpenAI-Funktionen sind deaktiviert.") - - if not cls.API_KEYS.get('serpapi'): - logger.warning("SerpAPI Key konnte nicht geladen werden. Suchfunktionen sind deaktiviert.") - if not cls.API_KEYS.get('genderize'): - logger.warning("Genderize API Key konnte nicht geladen werden. Geschlechtserkennung ist eingeschraenkt.") - @staticmethod def _load_key_from_file(filepath): """Hilfsfunktion zum Laden eines Schluessels aus einer Datei.""" diff --git a/docker-compose.yml b/docker-compose.yml index e20d5374..97206dda 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -101,10 +101,8 @@ services: - ./gtm_db_manager.py:/app/gtm_db_manager.py - ./gtm_projects.db:/app/gtm_projects.db - ./Log_from_docker:/app/Log_from_docker - # Mount API keys - - ./gemini_api_key.txt:/app/gemini_api_key.txt - - ./gemini_api_key.txt:/app/api_key.txt - - ./serpapikey.txt:/app/serpapikey.txt - environment: + environment: - PYTHONUNBUFFERED=1 - - DB_PATH=/app/gtm_projects.db \ No newline at end of file + - DB_PATH=/app/gtm_projects.db + env_file: + - ./gemini_api_key.txt \ No newline at end of file diff --git a/gtm-architect/Dockerfile b/gtm-architect/Dockerfile index ea692f23..8d5b35ae 100644 --- a/gtm-architect/Dockerfile +++ b/gtm-architect/Dockerfile @@ -36,7 +36,6 @@ COPY helpers.py . COPY config.py . # Use the specific requirements file for this app COPY gtm-architect/requirements.txt . -COPY gemini_api_key.txt . COPY gtm_db_manager.py . # Install Python and Node.js dependencies diff --git a/helpers.py b/helpers.py index 1544700f..bdb824b9 100644 --- a/helpers.py +++ b/helpers.py @@ -293,25 +293,33 @@ def get_email_address(firstname, lastname, website): # ============================================================================== def _get_gemini_api_key(): - """Retrieves Gemini API Key from Config or Environment.""" + """ + Retrieves Gemini API Key, prioritizing environment variables as the most robust method. + """ logger = logging.getLogger(__name__) - print("DEBUG: _get_gemini_api_key called.") # Debug print - api_key = Config.API_KEYS.get('openai') # Legacy slot - print(f"DEBUG: API Key from Config.API_KEYS['openai']: {api_key if api_key else 'None'}") # Debug print + logging.info("Attempting to retrieve Gemini API Key...") - if not api_key: - # Fallback: Versuche Environment Variable, falls Config leer ist - api_key = os.environ.get("OPENAI_API_KEY") - print(f"DEBUG: API Key from env OPENAI_API_KEY: {api_key if api_key else 'None'}") # Debug print - if not api_key: - # Fallback 2: Versuche den Gemini Key direkt - api_key = os.environ.get("GEMINI_API_KEY") or Config.API_KEYS.get('gemini') - print(f"DEBUG: API Key from env GEMINI_API_KEY or Config.API_KEYS['gemini']: {api_key if api_key else 'None'}") # Debug print + # Primary Method: Environment Variable (most robust for Docker) + api_key = os.environ.get("GEMINI_API_KEY") + if api_key: + logging.info("Successfully loaded API key from GEMINI_API_KEY environment variable.") + return api_key + + # Fallback 1: Legacy Environment Variable + api_key = os.environ.get("OPENAI_API_KEY") + if api_key: + logging.warning("Loaded API key from legacy OPENAI_API_KEY environment variable.") + return api_key + + # Fallback 2: File-based (less reliable with volume mounts) + logging.warning("Could not find API key in environment variables. Falling back to file-based method.") + api_key = Config.API_KEYS.get('openai') # Legacy slot in config + if api_key: + logging.info("Successfully loaded API key from config file.") + return api_key - if not api_key: - logger.error("Fehler: Kein API Key gefunden (weder als 'openai' noch 'gemini').") - raise ValueError("API Key missing.") - return api_key + logger.error("CRITICAL: No API Key found in environment variables or config file.") + raise ValueError("API Key missing.") @retry_on_failure def call_gemini_flash(prompt, system_instruction=None, temperature=0.3, json_mode=False):