FreezeJ' Blog

使用jinja2渲染配置文件

2020-09-27

配置文件(json)和模版文件都从后台动态获取,渲染后使用,对于配置文件修改更加灵活和友好,对于格式、顺序、静态配置变更都可以通过修改配置文件和模版文件实现,可以尽量减少代码的修改。

举例:渲染nginx配置文件

配置文件

配置文件中保存一些经常变更的,或者公共的变量,如证书名称、key文件,有时候需要更换证书,需要修改。
当然这里只是配置文件的一部分,也可以糅合进其他的公共变量,便于管理,模版也不会渲染不需要的变量,只多不少是没问题的

{
    "ssl_crt": "test.crt",
    "ssl_key": "test.key"
}

模版文件

使用jinja2模版引擎,对于更复杂的配置文件还可以使用循环、判断等,可以通过平台集中管理配置文件。

server{
    listen {{ proxy_port }};
    server_name  {{ proxy_domain }};

    ssl on;
    ssl_certificate ssl/{{ ssl_crt }};
    ssl_certificate_key  ssl/{{ ssl_key }};
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers AESGCM:ALL:!DH:!EXPORT:!RC4:+HIGH:!MEDIUM:!LOW:!aNULL:!eNULL;
    ssl_prefer_server_ciphers on;

    location / {
            proxy_pass http://127.0.0.1:{{ game_port }};
            proxy_http_version 1.1;
            proxy_read_timeout 600s;
            proxy_connect_timeout 600s;
            proxy_send_timeout 600s;
            proxy_set_header Upgrade \$http_upgrade;
            proxy_set_header Connection "upgrade";
            proxy_set_header X-real-ip \$remote_addr;
            proxy_set_header X-Forwarded-For \$remote_addr;
      }
}

python代码

通过平台获取集中管理的配置和模版文件,结合本身代码逻辑产生的变量,渲染模版写入文件中。

#!/usr/bin/env python3
import jinja2
import requests
import json
def get_value():
    """
    这里只是代码片段,具体由实际代码生成
    """
    value_dict = {
        "proxy_port": "8001",
        "proxy_domain": "test.com",
        "game_port": "9001",

    }
    return value_dict


def nginx_reload():
    """
    重载nginx配置
    """
    pass


def render_config():
    test_url = 'http://127.0.0.1/'  # 后台地址
    config = request.get(test_url + 'config.json').content.decode('utf-8')  # 配置文件变量,一些静态的变量,可以通过后台动态修改
    template = request.get(test_url + 'template.j2').content.decode('utf-8')  # 模版文件,决定变量的排布和格式,可以通过后台动态修改
    config_dict = json.loads(config)  # 从后台读取的
    config_dict.update(get_value())  # 结合代码中生成的变量
    # undefined=jinja2.StrictUndefined 模版中需要,但是变量字典未定义的变量会抛出异常
    nginx_conf_content = jinja2.Template(template, undefined=jinja2.StrictUndefined).render(**config_dict)  # 使用变量字典渲染模版
    with open('/etc/nginx/conf.d/test_nginx.conf', 'w') as f:  # 写入nginx配置文件
        f.write(nginx_conf_content)
    nginx_reload()


if __name__ == "__main__":
    render_config()