mirror of
https://github.com/This-weiyuqing/mi-fitness-health.git
synced 2026-10-18 11:13:48 +08:00
91 lines
5.1 KiB
Python
91 lines
5.1 KiB
Python
"""显式运行的本机真实容器演练,全部使用合成配置,不连接 NAS。"""
|
|
import ast
|
|
import json
|
|
from pathlib import Path
|
|
import subprocess
|
|
import sys
|
|
import tempfile
|
|
import time
|
|
|
|
HERE = Path(__file__).resolve().parent
|
|
DOCKER = 'C:/Users/35861/AppData/Local/Programs/DockerDesktop/resources/bin/docker.exe'
|
|
PROJECT = 'health-directory-local-rebuild'
|
|
|
|
|
|
def main():
|
|
if sys.argv[1:] != ['--run']:
|
|
raise SystemExit('仅在本机运行时显式指定 --run')
|
|
with tempfile.TemporaryDirectory(prefix='health-directory-local-') as directory:
|
|
root = Path(directory)
|
|
for name in ['state', 'secrets', 'calendar']:
|
|
(root/name).mkdir()
|
|
(root/'secrets/keyring_master').write_text('synthetic-local-master-value-1234567890123456789', encoding='utf-8')
|
|
(root/'.env').write_text('MI_FITNESS_ADMIN_KEY=synthetic-local-admin\nMI_FITNESS_WEB_PASSWORD=synthetic-local-password\n', encoding='utf-8')
|
|
base = (HERE.parent/'compose.yml').read_text(encoding='utf-8').replace('name: mi-fitness-health', 'name: '+PROJECT)
|
|
over = (HERE.parent/'compose.override.yml').read_text(encoding='utf-8')
|
|
base = base.replace('./shared/state:', './state:').replace('./shared/state/data:', './state/data:').replace('./backend/secrets/', './secrets/')
|
|
over = over.replace('./web/calendar:', './calendar:')
|
|
over = over.replace(" - '127.0.0.1:18322:8322'\n - '192.168.31.201:18322:8322'", " - '127.0.0.1:0:8322'")
|
|
over += '\nnetworks:\n default:\n internal: true\n'
|
|
def save():
|
|
(root/'compose.yml').write_text(base, encoding='utf-8')
|
|
(root/'compose.override.yml').write_text(over, encoding='utf-8')
|
|
save()
|
|
command = [DOCKER, '--context', 'desktop-linux', 'compose', '--project-directory', str(root),
|
|
'-p', PROJECT, '-f', str(root/'compose.yml'), '-f', str(root/'compose.override.yml')]
|
|
def compose(*args):
|
|
return subprocess.check_output([*command, *args], stderr=subprocess.STDOUT)
|
|
def inspect():
|
|
ids = compose('ps', '-aq').decode().split()
|
|
return json.loads(subprocess.check_output([DOCKER, '--context', 'desktop-linux', 'inspect', *ids]))
|
|
def ready():
|
|
deadline = time.monotonic()+90
|
|
while time.monotonic() < deadline:
|
|
items = inspect()
|
|
if len(items)==3 and all(i['State']['Running'] and i['State'].get('Health',{}).get('Status','healthy')=='healthy' for i in items):
|
|
return
|
|
time.sleep(1)
|
|
raise RuntimeError('本机容器就绪超时')
|
|
module = ast.parse((HERE.parent/'query-summary/check-ready.py').read_text(encoding='utf-8'))
|
|
probe = next(ast.literal_eval(n.value) for n in module.body if isinstance(n, ast.Assign)
|
|
and any(isinstance(t, ast.Name) and t.id=='probe' for t in n.targets))
|
|
try:
|
|
compose('up','-d','--no-build','--pull','never','backend','web','worker')
|
|
ready()
|
|
compose('stop','-t','30','worker','web','backend')
|
|
for source, target in [('state','shared/state'),('secrets','backend/secrets'),('calendar','web/calendar')]:
|
|
destination=root/target
|
|
destination.parent.mkdir(exist_ok=True)
|
|
(root/source).rename(destination)
|
|
base=base.replace('./state:', './shared/state:').replace('./state/data:', './shared/state/data:').replace('./secrets/', './backend/secrets/')
|
|
over=over.replace('./calendar:', './web/calendar:')
|
|
save()
|
|
compose('config','--quiet')
|
|
compose('up','-d','--no-build','--pull','never','backend','web','worker')
|
|
ready()
|
|
print('容器已标记就绪,立即执行实际网页探针:', flush=True)
|
|
result=subprocess.run([DOCKER,'--context','desktop-linux','exec','-i',PROJECT+'-web-1','python','-'],
|
|
input=probe.encode('utf-8'),capture_output=True)
|
|
print(result.stdout.decode('utf-8',errors='replace'), flush=True)
|
|
print(result.stderr.decode('utf-8',errors='replace'), flush=True)
|
|
if result.returncode:
|
|
print('首次探针失败,五秒后重复同一只读探针以区分启动时序。', flush=True)
|
|
time.sleep(5)
|
|
retry=subprocess.run([DOCKER,'--context','desktop-linux','exec','-i',PROJECT+'-web-1','python','-'],
|
|
input=probe.encode('utf-8'),capture_output=True)
|
|
print(retry.stdout.decode('utf-8',errors='replace'),flush=True)
|
|
print(retry.stderr.decode('utf-8',errors='replace'),flush=True)
|
|
if retry.returncode:
|
|
raise RuntimeError('本机网页探针持续失败')
|
|
print('LOCAL_REAL_REBUILD_AND_WEB_PROBE_OK',flush=True)
|
|
except subprocess.CalledProcessError as error:
|
|
# 此处仅含本机合成配置,无真实凭据。
|
|
print(error.output.decode('utf-8',errors='replace'),flush=True)
|
|
raise
|
|
finally:
|
|
compose('down')
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|