84 lines
6.7 KiB
JSON
84 lines
6.7 KiB
JSON
{
|
||
"path": "f/app_custom/system_heartbeat",
|
||
"summary": "Windmill Heartbeat - システム自己診断",
|
||
"description": "Windmillの動作確認用ワークフロー。UUID生成、時刻取得、計算チェック、HTTPヘルスチェック、年度判定を行い、全ステップの正常性を検証する。",
|
||
"value": {
|
||
"modules": [
|
||
{
|
||
"id": "a",
|
||
"value": {
|
||
"lock": "# py: 3.12\n",
|
||
"type": "rawscript",
|
||
"content": "import uuid\nfrom datetime import datetime, timezone\n\ndef main():\n \"\"\"診断データを生成する\"\"\"\n now = datetime.now(timezone.utc)\n run_id = str(uuid.uuid4())\n check_value = 2 + 2\n \n result = {\n \"timestamp\": now.isoformat(),\n \"run_id\": run_id,\n \"check\": check_value,\n \"python_version\": __import__('sys').version\n }\n print(f\"[Step1] 診断データ生成完了\")\n print(f\" run_id: {run_id}\")\n print(f\" timestamp: {now.isoformat()}\")\n print(f\" check: {check_value}\")\n return result\n",
|
||
"language": "python3",
|
||
"input_transforms": {}
|
||
},
|
||
"summary": "Step1: 診断データ生成"
|
||
},
|
||
{
|
||
"id": "b",
|
||
"value": {
|
||
"lock": "# py: 3.12\n",
|
||
"type": "rawscript",
|
||
"content": "from datetime import datetime, timezone\n\ndef main(step1_result: dict):\n \"\"\"Step1の結果を検証する\"\"\"\n errors = []\n \n # 計算チェック\n if step1_result.get(\"check\") != 4:\n errors.append(f\"計算エラー: expected 4, got {step1_result.get('check')}\")\n \n # run_idの存在チェック\n if not step1_result.get(\"run_id\"):\n errors.append(\"run_idが存在しない\")\n \n # timestampの存在チェック\n if not step1_result.get(\"timestamp\"):\n errors.append(\"timestampが存在しない\")\n \n if errors:\n error_msg = \"; \".join(errors)\n print(f\"[Step2] 検証失敗: {error_msg}\")\n raise Exception(f\"検証失敗: {error_msg}\")\n \n print(f\"[Step2] データ検証OK\")\n print(f\" 計算チェック: 2+2={step1_result['check']} ✓\")\n print(f\" run_id: {step1_result['run_id']} ✓\")\n print(f\" timestamp: {step1_result['timestamp']} ✓\")\n \n return {\n \"verification\": \"PASS\",\n \"step1_data\": step1_result\n }\n",
|
||
"language": "python3",
|
||
"input_transforms": {
|
||
"step1_result": {
|
||
"expr": "results.a",
|
||
"type": "javascript"
|
||
}
|
||
}
|
||
},
|
||
"summary": "Step2: データ検証"
|
||
},
|
||
{
|
||
"id": "c",
|
||
"value": {
|
||
"lock": "# py: 3.12\n",
|
||
"type": "rawscript",
|
||
"content": "import urllib.request\nimport ssl\n\ndef main(verification_result: dict):\n \"\"\"Windmillサーバー自身へのHTTPチェック\"\"\"\n url = \"https://windmill.keinafarm.net/api/version\"\n \n # SSL検証をスキップ(自己署名証明書対応)\n ctx = ssl.create_default_context()\n ctx.check_hostname = False\n ctx.verify_mode = ssl.CERT_NONE\n \n try:\n req = urllib.request.Request(url)\n with urllib.request.urlopen(req, context=ctx, timeout=10) as response:\n status_code = response.status\n body = response.read().decode('utf-8')\n except Exception as e:\n print(f\"[Step3] HTTPチェック失敗: {e}\")\n raise Exception(f\"HTTPヘルスチェック失敗: {e}\")\n \n print(f\"[Step3] HTTPヘルスチェックOK\")\n print(f\" URL: {url}\")\n print(f\" Status: {status_code}\")\n print(f\" Version: {body}\")\n \n return {\n \"http_check\": \"PASS\",\n \"status_code\": status_code,\n \"server_version\": body\n }\n",
|
||
"language": "python3",
|
||
"input_transforms": {
|
||
"verification_result": {
|
||
"expr": "results.b",
|
||
"type": "javascript"
|
||
}
|
||
}
|
||
},
|
||
"summary": "Step3: HTTPヘルスチェック"
|
||
},
|
||
{
|
||
"id": "d",
|
||
"value": {
|
||
"lock": "# py: 3.12\n",
|
||
"type": "rawscript",
|
||
"content": "from datetime import datetime, timezone\n\ndef main(step1_data: dict, verification: dict, http_check: dict):\n \"\"\"年度判定と最終診断レポートを生成\"\"\"\n now = datetime.now(timezone.utc)\n \n # 日本の年度判定(4月始まり)\n fiscal_year = now.year if now.month >= 4 else now.year - 1\n \n report = {\n \"status\": \"ALL OK\",\n \"fiscal_year\": fiscal_year,\n \"diagnostics\": {\n \"data_generation\": \"PASS\",\n \"data_verification\": verification.get(\"verification\", \"UNKNOWN\"),\n \"http_health\": http_check.get(\"http_check\", \"UNKNOWN\"),\n \"server_version\": http_check.get(\"server_version\", \"UNKNOWN\")\n },\n \"run_id\": step1_data.get(\"run_id\"),\n \"started_at\": step1_data.get(\"timestamp\"),\n \"completed_at\": now.isoformat()\n }\n \n print(\"\")\n print(\"========================================\")\n print(\" Windmill Heartbeat - 診断レポート\")\n print(\"========================================\")\n print(f\" Status: {report['status']}\")\n print(f\" 年度: {fiscal_year}年度\")\n print(f\" Run ID: {report['run_id']}\")\n print(f\" Server: {report['diagnostics']['server_version']}\")\n print(f\" 開始: {report['started_at']}\")\n print(f\" 完了: {report['completed_at']}\")\n print(\" ────────────────────────────────────\")\n print(f\" データ生成: PASS ✓\")\n print(f\" データ検証: {report['diagnostics']['data_verification']} ✓\")\n print(f\" HTTP確認: {report['diagnostics']['http_health']} ✓\")\n print(\"========================================\")\n print(\"\")\n \n return report\n",
|
||
"language": "python3",
|
||
"input_transforms": {
|
||
"http_check": {
|
||
"expr": "results.c",
|
||
"type": "javascript"
|
||
},
|
||
"step1_data": {
|
||
"expr": "results.a",
|
||
"type": "javascript"
|
||
},
|
||
"verification": {
|
||
"expr": "results.b",
|
||
"type": "javascript"
|
||
}
|
||
}
|
||
},
|
||
"summary": "Step4: 年度判定 & 最終レポート"
|
||
}
|
||
]
|
||
},
|
||
"schema": {
|
||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||
"type": "object",
|
||
"order": [],
|
||
"properties": {},
|
||
"required": []
|
||
}
|
||
}
|