# common.py import subprocess import sys import os import platform import json from pathlib import Path def get_host_ip(): """Получает IP-адрес хоста в локальной сети""" try: # Для WSL2 получаем IP хоста (Windows) if 'microsoft' in platform.uname().release.lower(): # В WSL2 получаем IP хоста из файла resolv.conf with open('/etc/resolv.conf', 'r') as f: for line in f: if line.startswith('nameserver'): # Возвращаем первый найденный nameserver как IP хоста # (Это может быть не всегда точно, но подходит для базового сценария) return line.split()[1] # Для других систем используем подключение к внешнему серверу else: import socket s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s.connect(("8.8.8.8", 80)) ip = s.getsockname()[0] s.close() return ip except Exception as e: print(f"Не удалось получить IP-адрес хоста: {e}") # Возвращаем IP по умолчанию, если не удалось получить # Используем IP из памяти, если доступен return "192.168.31.60" def get_project_root(): """Определяет корневую директорию проекта 'local-dns'.""" # Начинаем с домашней директории current_path = Path.home() / "projects" / "docker" project_name = "local-dns" # Используем фиксированное имя для этого репозитория project_path = current_path / project_name if not project_path.exists() or not (project_path / "docker-compose.yml").exists(): print(f"Директория проекта '{project_name}' или 'docker-compose.yml' не найдена в {current_path}") sys.exit(1) return project_path def read_services_config(project_root): """Читает конфигурацию сервисов из файла в корне проекта.""" config_path = project_root / "services.json" default_config = { "services": [ {"name": "gitea", "port": 3000}, {"name": "youtrack", "port": 8080}, {"name": "n8n", "port": 5678} ] } if config_path.exists(): try: with open(config_path, 'r', encoding='utf-8') as f: return json.load(f) except json.JSONDecodeError as e: print(f"Ошибка чтения JSON из {config_path}: {e}") print("Используем конфигурацию по умолчанию.") return default_config except Exception as e: print(f"Не удалось открыть файл конфигурации: {e}") sys.exit(1) else: # Создаем файл конфигурации по умолчанию в корне проекта try: with open(config_path, 'w', encoding='utf-8') as f: json.dump(default_config, f, indent=2, ensure_ascii=False) print(f"Файл конфигурации создан по умолчанию: {config_path}") except Exception as e: print(f"Не удалось создать файл конфигурации: {e}") sys.exit(1) return default_config def generate_dnsmasq_config(project_root): """Генерирует конфигурационный файл dnsmasq в директории проекта.""" host_ip = get_host_ip() config_path = project_root / "dnsmasq.conf" services = read_services_config(project_root) config_content = f"""# Локальные домены → твой ПК """ for service in services['services']: config_content += f"address=/{service['name']}.local/{host_ip}\n" config_content += f"""address=/.local/{host_ip} # Кэш DNS cache-size=500 # Лог (опционально) log-queries log-facility=/var/log/dnsmasq.log # Не перехватывать внешние запросы — делегируем no-resolv server=8.8.8.8 server=1.1.1.1 """ try: with open(config_path, 'w', encoding='utf-8') as f: f.write(config_content.strip()) print(f"Конфигурационный файл dnsmasq обновлен: {config_path}") except Exception as e: print(f"Не удалось записать файл конфигурации dnsmasq: {e}") sys.exit(1) def run_docker_command(cmd): """Выполняет команду Docker и возвращает результат""" try: print(f"Выполняю команду: {cmd}") result = subprocess.run(cmd, shell=True, capture_output=True, text=True) if result.returncode != 0: print(f"Ошибка выполнения команды: {cmd}") print(f"stderr: {result.stderr}") print(f"stdout: {result.stdout}") return False print(f"Команда выполнена успешно: {cmd}") return True except Exception as e: print(f"Ошибка выполнения команды: {e}") return False def setup_project(): """Настройка проекта: генерация конфигов и переход в директорию проекта.""" project_path = get_project_root() print(f"Работаем в директории проекта: {project_path}") # Генерируем конфигурационный файл dnsmasq generate_dnsmasq_config(project_path) # Переходим в директорию проекта os.chdir(project_path) print(f"Текущая директория изменена на: {os.getcwd()}") return project_path