Загрузка данных


#!/usr/bin/env python3

import argparse
import base64
import os
import re
import tomllib
from pathlib import Path

import hvac
from jinja2 import Environment, FileSystemLoader

# ============================================================
# PATH
# ============================================================

APP_PATH = os.environ.get("APP_PATH")
if not APP_PATH:
    raise RuntimeError("APP_PATH не задан")

ROOT = Path(APP_PATH).resolve()

PYPROJECT = ROOT / "django-ma/src/pyproject.toml"
TEMPLATES_DIR = ROOT / "templates"

# ============================================================
# LOG
# ============================================================

def log(msg: str):
    print(f"[ОК] {msg}")

# ============================================================
# VAULT
# ============================================================

def vault_login():
    client = hvac.Client(url=os.environ["VAULT_ADDR"])

    login = client.auth.ldap.login(
        username=os.environ["VAULT_USERNAME"],
        password=os.environ["VAULT_PASSWORD"]
    )

    client.token = login["auth"]["client_token"]

    if not client.is_authenticated():
        raise RuntimeError("Vault auth failed")

    return client


def read_secret(client, path):
    response = client.secrets.kv.v2.read_secret_version(
        mount_point=os.environ["VAULT_MOUNT"],
        path=path,
        raise_on_deleted_version=True
    )
    return response["data"]["data"]

# ============================================================
# VERSIONING
# ============================================================

branch = (
    os.getenv("BUILD_SOURCEBRANCHNAME")
    or os.getenv("BRANCH")
    or "dev"
).lower()

branch = branch.replace("refs/heads/", "")

print(f"Текущая ветка: {branch}")

data = tomllib.loads(PYPROJECT.read_text(encoding="utf-8"))
current_version = data["project"]["version"]

# убираем PEP440 суффиксы
base_version = re.sub(
    r"(a\d*|b\d*|rc\d*)$",
    "",
    current_version
)

major, minor, patch = map(int, base_version.split("."))
patch += 1

suffix_map = {
    "dev": "a1",
    "test": "b1",
    "stage": "rc1",
    "prod": "",
}

suffix = suffix_map.get(branch, "a1")

if suffix:
    new_version = f"{major}.{minor}.{patch}{suffix}"
else:
    new_version = f"{major}.{minor}.{patch}"

text = PYPROJECT.read_text(encoding="utf-8")

text = re.sub(
    r'version\s*=\s*"[^"]+"',
    f'version = "{new_version}"',
    text,
    count=1
)

PYPROJECT.write_text(text, encoding="utf-8")

print(f"[ОК] Версия обновлена: {current_version} → {new_version}")

# ============================================================
# JINJA
# ============================================================

def write_text(path: Path, content: str):
    path.parent.mkdir(parents=True, exist_ok=True)
    path.write_text(content, encoding="utf-8")


def render_template(root: Path, template_name: str, output_path: Path, **context):
    templates_dir = root / "templates"

    if not templates_dir.exists():
        raise RuntimeError(f"templates not found: {templates_dir}")

    jinja = Environment(
        loader=FileSystemLoader(str(templates_dir)),
        autoescape=False
    )

    template = jinja.get_template(template_name)
    rendered = template.render(**context)

    write_text(output_path, rendered)
    log(f"{template_name} rendered")

# ============================================================
# KERBEROS
# ============================================================

def build_kerberos(root: Path, k5: dict):
    keytab_b64 = k5.get("mailarchive.keytab")
    if not keytab_b64:
        raise RuntimeError("No keytab in Vault")

    keytab_path = root / "kerberos-ma" / "mailarchive.keytab"
    keytab_path.parent.mkdir(parents=True, exist_ok=True)
    keytab_path.write_bytes(base64.b64decode(keytab_b64))

    log("Kerberos keytab saved")

    principal = k5.get("KRB_PRINCIPAL")
    if not principal:
        raise RuntimeError("No KRB_PRINCIPAL")

    render_template(
        root,
        "entrypoint.sh.j2",
        root / "kerberos-ma" / "entrypoint.sh",
        KRB_PRINCIPAL=principal
    )

# ============================================================
# MAIN
# ============================================================

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument("--env", choices=["dev", "stage", "prod"], required=True)
    args = parser.parse_args()

    env = args.env

    print("=== DEBUG ===")
    print("APP_PATH:", APP_PATH)
    print("ROOT:", ROOT)

    client = vault_login()

    base = f"projects/mailarchive/{env}"

    secrets = read_secret(client, base)

    build_kerberos(ROOT, secrets)

    print("=== DONE ===")


if __name__ == "__main__":
    main()