remote_service/main.py
ZZY 9297f9170a feat: 重构项目并添加新功能
- 移除 defaultenv 文件和未使用的模板文件
- 重构 main.py,添加新的 Docker Compose 配置解析逻辑
- 新增 Nginx 配置生成和安全重启功能
- 更新 requirements.txt,替换 jinja2 为 pyyaml
- 删除未使用的 src/config_reader.py 和 src/jinja2_render.py 文件
2025-04-26 16:56:38 +08:00

142 lines
4.5 KiB
Python

"""
main
"""
import subprocess
import logging
import argparse
from pathlib import Path
import yaml
from src.logger import get_logger
from src.nginx import NginxConfig, NginxConfigurator
logger = get_logger(__name__)
# 配置常量
FILE_PATH = Path(__file__).parent
DOCKER_COMPOSE_FILE = Path(FILE_PATH, "docker-compose.yml")
NETWORK_NAME = "nginx-net"
def validate_docker_network():
"""检查Docker网络是否存在"""
try:
result = subprocess.run(
["docker", "network", "inspect", NETWORK_NAME],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=True
)
return result.returncode == 0
except subprocess.CalledProcessError:
logger.error("Docker网络 %s 不存在", NETWORK_NAME)
return False
except Exception as e:
logger.error("网络检查异常: %s", str(e), exc_info=True)
return False
def parse_compose_config(file_path: Path) -> list[NginxConfig]:
"""解析Docker Compose文件"""
try:
with open(file_path, 'r', encoding='utf-8') as f:
config = yaml.safe_load(f)
services:dict = config['services']
# networks = config['networks'][NETWORK_NAME]
# if not networks['external']:
# raise ValueError("network 必须为external")
nginx_configs:list[NginxConfig] = []
for name, service in services.items():
try:
labels = service.get('labels')
if labels is not None:
n = labels.get('nginx_prefix_name')
if n is not None:
name = n
conf = NginxConfig(
name = f"{name}.zzyxyz.com",
host = service['container_name'],
port = service['expose'][0]
)
if len(service['expose']) != 1:
raise ValueError("expose 必须为一项")
networks = service.get('networks')
# TODO
if networks is None or networks[0] != NETWORK_NAME:
raise ValueError(f"networks 需要设置为{NETWORK_NAME}")
# required_fields = ['com.lingma.nginx.domain', 'com.lingma.nginx.port']
# for field in required_fields:
# if field not in labels:
# raise ValueError(f"服务 {name} 缺少必要标签: {field}")
nginx_configs.append(conf)
except Exception as e:
logger.error("解析服务 %s 配置失败: %s{str(e)}", name, str(e))
continue
return nginx_configs
except FileNotFoundError:
logger.error("文件不存在: %s", file_path)
return False
except PermissionError:
logger.error("无权限访问文件: %s", file_path)
return False
except yaml.YAMLError as e:
logger.error("YAML解析错误: %s", str(e))
return False
except Exception as e:
logger.error("未知错误: %s", str(e), exc_info=True)
return False
def main():
"""main"""
parser = argparse.ArgumentParser(description="Nginx自动化配置工具")
parser.add_argument('--compose-file', type=str, default=DOCKER_COMPOSE_FILE,
help="Docker Compose文件路径")
parser.add_argument('--debug', action='store_true',
help="启用调试模式")
args = parser.parse_args()
if args.debug:
logger.setLevel(logging.DEBUG)
logger.debug("调试模式已启用")
# 前置检查
if not validate_docker_network():
logger.error("请先创建Docker网络: docker network create %s", NETWORK_NAME)
return
# 配置生成
try:
logger.info("开始解析Docker Compose配置...")
compose_files:str = args.compose_file
configs = []
for file in compose_files.split(','):
logger.info("parse %s", file)
config = parse_compose_config(file)
configs.extend(config)
logger.info("发现 %d 个需要代理的服务", len(configs))
conf = NginxConfigurator()
conf.backup_config()
ret = conf.gen_and_save_config(configs)
if not ret:
return
ret = conf.safe_reload()
if ret:
logger.info("全流程完成")
else:
logger.error("流程未完成,请检查错误日志")
except Exception as e:
logger.critical("主流程异常终止: %s", str(e), exc_info=args.debug)
if __name__ == "__main__":
main()