logboard/app/scripts/substitute_env.py

85 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/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 <env_path> <compose_path>\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())