- 移除 defaultenv 文件和未使用的模板文件 - 重构 main.py,添加新的 Docker Compose 配置解析逻辑 - 新增 Nginx 配置生成和安全重启功能 - 更新 requirements.txt,替换 jinja2 为 pyyaml - 删除未使用的 src/config_reader.py 和 src/jinja2_render.py 文件
142 lines
4.5 KiB
Python
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()
|