feat(client): 添加 Python 客户端及示例应用

- 新增 python-client 模块,提供 ConfigClient 配置拉取、定时同步、变更监听
- 使用 pyaes 替代 cryptography 实现 AES 解密,避免编译问题
- 新增 python-client-demo Flask 示例应用
- .gitignore 添加 Python 相关忽略规则
This commit is contained in:
2026-02-05 21:05:19 +08:00
parent 6653c752e7
commit c31746d7d1
11 changed files with 431 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
import json
import logging
import os
from flask import Flask
from kenaito_conf import Config, ConfigClient
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(name)s] %(message)s")
logger = logging.getLogger("demo")
app = Flask(__name__)
# Config defaults (overridden by remote config center)
config_values = {
"database.host": os.getenv("DATABASE_HOST", "192.168.1.1"),
"database.port": os.getenv("DATABASE_PORT", "8888"),
"database.name": os.getenv("DATABASE_NAME", "xxxx"),
"database.user": os.getenv("DATABASE_USER", "xxxx"),
"database.password": os.getenv("DATABASE_PASSWORD", "xxxxxxxx"),
}
client: ConfigClient | None = None
def on_config_changed(changed: dict[str, str]) -> None:
for k, v in changed.items():
if k in config_values:
config_values[k] = v
logger.info("config updated: %s = %s", k, v)
def create_client() -> ConfigClient:
cfg = Config(
base_url=os.getenv("KENAITO_BASE_URL", "http://localhost:8080"),
app_name=os.getenv("KENAITO_APP_NAME", "kenaito-springboot-demo"),
env=os.getenv("KENAITO_PROFILE", "daily"),
version=os.getenv("KENAITO_VERSION", "latest"),
token=os.getenv("KENAITO_TOKEN", ""),
sync_interval=int(os.getenv("KENAITO_SYNC_INTERVAL", "30")),
cache_dir=os.getenv("KENAITO_CACHE_DIR", "."),
)
c = ConfigClient(cfg)
c.on_change(on_config_changed)
c.start()
return c
@app.route("/")
def index():
return json.dumps(config_values, ensure_ascii=False, indent=2), 200, {
"Content-Type": "application/json; charset=utf-8",
}
@app.route("/health")
def health():
return "OK"
if __name__ == "__main__":
try:
client = create_client()
remote = client.get_all()
for k in config_values:
if k in remote:
config_values[k] = remote[k]
logger.info("loaded %d configs from remote", len(remote))
except Exception:
logger.exception("failed to init config client, using local defaults")
port = int(os.getenv("SERVER_PORT", "8082"))
app.run(host="0.0.0.0", port=port)