#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Скрипт подстановки переменных окружения из .env/env.example в файл шаблона. Автор: Сергей Антропов Сайт: https://devops.org.ru Использование: python3 app/scripts/substitute_env.py PATH_TO_ENV PATH_TO_COMPOSE_FILE Логика: - Читает пары KEY=VALUE из указанного env-файла (игнорирует комментарии и пустые строки) - Не выполняет файл как shell (безопасно парсит) - Заменяет плейсхолдеры вида ${KEY} в целевом файле """ from __future__ import annotations import io import os import re import sys from typing import Dict def parse_env_file(env_path: str) -> Dict[str, str]: """Простой парсер .env файла: KEY=VALUE, без исполнения shell.""" variables: Dict[str, str] = {} with io.open(env_path, "r", encoding="utf-8") as fh: for raw in fh: line = raw.strip() if not line or line.startswith("#"): continue if "=" not in line: continue key, val = line.split("=", 1) key = key.strip() val = val.strip() # Снимаем внешние кавычки, если присутствуют if (val.startswith('"') and val.endswith('"')) or ( val.startswith("'") and val.endswith("'") ): val = val[1:-1] variables[key] = val return variables def substitute_placeholders(text: str, env: Dict[str, str]) -> str: """Заменяет ${VAR} из словаря env, оставляет плейсхолдер, если VAR не найден.""" pattern = re.compile(r"\$\{([A-Za-z_][A-Za-z0-9_]*)\}") return pattern.sub(lambda m: env.get(m.group(1), m.group(0)), text) def main() -> int: if len(sys.argv) != 3: sys.stderr.write( "Usage: substitute_env.py \n" ) return 2 env_path, compose_path = sys.argv[1], sys.argv[2] if not os.path.exists(env_path): sys.stderr.write(f"Env file not found: {env_path}\n") return 3 if not os.path.exists(compose_path): sys.stderr.write(f"Compose file not found: {compose_path}\n") return 4 env = parse_env_file(env_path) with io.open(compose_path, "r", encoding="utf-8") as fh: content = fh.read() new_content = substitute_placeholders(content, env) with io.open(compose_path, "w", encoding="utf-8") as fh: fh.write(new_content) return 0 if __name__ == "__main__": raise SystemExit(main())