diff --git a/scripts/cert_renew_restart.py b/scripts/cert_renew_restart.py index d91fb84..754c828 100644 --- a/scripts/cert_renew_restart.py +++ b/scripts/cert_renew_restart.py @@ -6,86 +6,120 @@ from common import * def generate_mkcert_command(): """Генерирует команду для mkcert с указанием всех доменов""" - services = read_services_config() + project_path = get_project_root() + services = read_services_config(project_path) domains = [f"{service['name']}.local" for service in services['services']] domains.append("*.local") - + # Создаем PowerShell команду domains_str = " ".join([f'"{domain}"' for domain in domains]) powershell_cmd = f'mkcert {domains_str}' return powershell_cmd -def copy_and_rename_certificates(): - """Копирует и переименовывает сертификаты из Windows в WSL""" +def copy_and_rename_certificates(project_path): + """Копирует и переименовывает сертификаты из Windows в WSL в директорию проекта.""" # Определяем пути windows_certs_path = Path("C:/store/certs") - wsl_certs_path = Path.home() / "projects" / "docker" / "network" / "certs" - - # Создаем директорию для сертификатов в WSL + # Путь к директории certs внутри проекта local-dns + wsl_certs_path = project_path / "certs" + + # Создаем директорию для сертификатов в WSL в корне проекта wsl_certs_path.mkdir(parents=True, exist_ok=True) - - # Находим сгенерированные mkcert файлы - cert_files = list(windows_certs_path.glob("_wildcard.local+*.pem")) + + # Находим сгенерированные mkcert файлы (обычно именуются как _wildcard.local+*.pem) + # Предполагаем, что первый найденный файл - это сертификат + cert_files = list(windows_certs_path.glob("_wildcard.local*.pem")) if not cert_files: - print("Сертификаты не найдены в C:/store/certs") + print(f"Сертификаты не найдены в {windows_certs_path} по шаблону _wildcard.local*.pem") return False - - # Предполагаем, что mkcert генерирует файлы в формате _wildcard.domain+N.pem + + # Сортируем, чтобы упростить выбор (хотя mkcert обычно создает пару) + cert_files.sort() cert_file = cert_files[0] - key_file = cert_files[0].with_name(cert_file.name.replace(".pem", "-key.pem")) - - if not key_file.exists(): - print(f"Файл ключа не найден: {key_file}") - return False - - # Копируем и переименовываем + + # Пытаемся найти соответствующий ключ (обычно имя файла сертификата с -key.pem) + # Например, если сертификат _wildcard.local+2.pem, ключ будет _wildcard.local+2-key.pem + expected_key_name = cert_file.with_name(cert_file.name.replace('.pem', '-key.pem')) + if expected_key_name.exists(): + key_file = expected_key_name + else: + print(f"Файл ключа не найден по ожидаемому пути: {expected_key_name}") + # Альтернатива: ищем файл с -key.pem в имени среди найденных + key_candidates = [f for f in cert_files if '-key.pem' in f.name] + if key_candidates: + key_file = key_candidates[0] # Берем первый найденный ключ + print(f"Найден ключ по альтернативному поиску: {key_file}") + else: + print(f"Файл ключа не найден в {windows_certs_path}") + return False + + + # Копируем и переименовываем в директорию проекта target_cert = wsl_certs_path / "wildcard.local.pem" target_key = wsl_certs_path / "wildcard.local.key" - - shutil.copy2(cert_file, target_cert) - shutil.copy2(key_file, target_key) - - # Создаем копии для default + + try: + shutil.copy2(cert_file, target_cert) + shutil.copy2(key_file, target_key) + print(f"Сертификат скопирован в: {target_cert}") + print(f"Ключ скопирован в: {target_key}") + except Exception as e: + print(f"Ошибка копирования сертификатов: {e}") + return False + + # Создаем копии для default (если требуются контейнером) default_cert = wsl_certs_path / "default.crt" default_key = wsl_certs_path / "default.key" - - shutil.copy2(target_cert, default_cert) - shutil.copy2(target_key, default_key) - + + try: + shutil.copy2(target_cert, default_cert) + shutil.copy2(target_key, default_key) + print(f"Копии сертификатов созданы как default.crt и default.key") + except Exception as e: + print(f"Ошибка создания копий сертификатов по умолчанию: {e}") + # Это может быть не критичной ошибкой, в зависимости от настройки контейнера + print(f"Сертификаты скопированы в {wsl_certs_path}") return True def main(): print("Обновление сертификатов и перезапуск сервисов...") - - # Настройка проекта - setup_project() - + + # Получаем путь к проекту + project_path = get_project_root() + + # Генерируем конфигурацию dnsmasq перед обновлением + generate_dnsmasq_config(project_path) + # Выводим команду для генерации сертификатов mkcert_cmd = generate_mkcert_command() print("\nДля генерации сертификатов выполните в PowerShell (от администратора):") print(f"cd C:\\store\\certs") print(mkcert_cmd) print() - + # Ждем подтверждения пользователя input("Нажмите Enter после генерации сертификатов в PowerShell...") - + # Копируем сертификаты - if not copy_and_rename_certificates(): + if not copy_and_rename_certificates(project_path): print("Не удалось скопировать сертификаты") sys.exit(1) - - # Перезапускаем nginx-proxy для загрузки новых сертификатов - print("Перезапуск nginx-proxy...") - if not run_docker_command("docker-compose restart nginx-proxy"): - print("Не удалось перезапустить nginx-proxy") - # Если restart не сработал, пробуем поднять контейнеры - if not run_docker_command("docker-compose up -d"): - print("Не удалось поднять контейнеры") + + # Перезапускаем контейнеры Docker Compose + print("Перезапуск контейнеров Docker Compose...") + if not run_docker_command("docker-compose restart"): + print("Команда 'docker-compose restart' не удалась.") + print("Попытка поднять контейнеры с помощью 'docker-compose up -d'...") + if not run_docker_command("docker-compose up -d --force-recreate"): + print("Не удалось поднять контейнеры с помощью 'docker-compose up -d'.") sys.exit(1) - + else: + print("Контейнеры подняты с помощью 'docker-compose up -d'.") + else: + print("Контейнеры успешно перезапущены!") + print("Сертификаты обновлены и сервисы перезапущены!") if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/scripts/common.py b/scripts/common.py index 19b6b58..811576c 100644 --- a/scripts/common.py +++ b/scripts/common.py @@ -15,6 +15,8 @@ def get_host_ip(): with open('/etc/resolv.conf', 'r') as f: for line in f: if line.startswith('nameserver'): + # Возвращаем первый найденный nameserver как IP хоста + # (Это может быть не всегда точно, но подходит для базового сценария) return line.split()[1] # Для других систем используем подключение к внешнему серверу else: @@ -27,11 +29,25 @@ def get_host_ip(): except Exception as e: print(f"Не удалось получить IP-адрес хоста: {e}") # Возвращаем IP по умолчанию, если не удалось получить + # Используем IP из памяти, если доступен return "192.168.31.60" -def read_services_config(): - """Читает конфигурацию сервисов из файла""" - config_path = Path("../services.json") +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}, @@ -39,27 +55,40 @@ def read_services_config(): {"name": "n8n", "port": 5678} ] } - + if config_path.exists(): - with open(config_path, 'r', encoding='utf-8') as f: - return json.load(f) + 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: - # Создаем файл конфигурации по умолчанию - config_path.parent.mkdir(parents=True, exist_ok=True) - with open(config_path, 'w', encoding='utf-8') as f: - json.dump(default_config, f, indent=2, ensure_ascii=False) + # Создаем файл конфигурации по умолчанию в корне проекта + 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(): - """Генерирует конфигурационный файл dnsmasq""" +def generate_dnsmasq_config(project_root): + """Генерирует конфигурационный файл dnsmasq в директории проекта.""" host_ip = get_host_ip() - services = read_services_config() - + 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 @@ -74,39 +103,40 @@ no-resolv server=8.8.8.8 server=1.1.1.1 """ - - # Путь к конфигурационному файлу - config_path = Path("../dnsmasq.conf") - config_path.parent.mkdir(parents=True, exist_ok=True) - - with open(config_path, 'w', encoding='utf-8') as f: - f.write(config_content.strip()) - - print(f"Конфигурационный файл dnsmasq обновлен: {config_path}") + + 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"Ошибка: {result.stderr}") + 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() - + generate_dnsmasq_config(project_path) + # Переходим в директорию проекта - project_path = Path("../") - if not project_path.exists(): - print(f"Директория проекта не найдена: {project_path}") - sys.exit(1) - os.chdir(project_path) - return project_path \ No newline at end of file + print(f"Текущая директория изменена на: {os.getcwd()}") + return project_path diff --git a/scripts/restart_services.py b/scripts/restart_services.py index 076b849..0f2ace5 100644 --- a/scripts/restart_services.py +++ b/scripts/restart_services.py @@ -2,21 +2,25 @@ from common import * def main(): - print("Перезапуск сервисов...") - - # Настройка проекта - setup_project() - + print("Перезапуск сервисов Docker Compose...") + + # Настройка проекта (включает генерацию конфига dnsmasq) + project_path = setup_project() # Вызывает setup_project, который включает generate_dnsmasq_config + # Перезапускаем контейнеры - print("Перезапуск контейнеров...") + print("Перезапуск контейнеров Docker Compose...") if not run_docker_command("docker-compose restart"): - print("Не удалось перезапустить контейнеры") - # Если restart не сработал, пробуем поднять контейнеры + print("Команда 'docker-compose restart' не удалась.") + print("Попытка поднять контейнеры с помощью 'docker-compose up -d'...") if not run_docker_command("docker-compose up -d"): - print("Не удалось поднять контейнеры") + print("Не удалось поднять контейнеры с помощью 'docker-compose up -d'.") sys.exit(1) - + else: + print("Контейнеры подняты с помощью 'docker-compose up -d'.") + else: + print("Контейнеры успешно перезапущены!") + print("Сервисы перезапущены!") if __name__ == "__main__": - main() \ No newline at end of file + main()