cancan-microstack 0.0.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (440) hide show
  1. cancan_microstack/__init__.py +14 -0
  2. cancan_microstack/__version__.py +10 -0
  3. cancan_microstack/assets/__init__.py +6 -0
  4. cancan_microstack/assets/builds/caddy/Caddyfile +187 -0
  5. cancan_microstack/assets/builds/caddy/DEPLOYMENT.md +303 -0
  6. cancan_microstack/assets/builds/caddy/Dockerfile +46 -0
  7. cancan_microstack/assets/builds/caddy/README.md +343 -0
  8. cancan_microstack/assets/builds/caddy/geoip/README.md +5 -0
  9. cancan_microstack/assets/builds/caddy/start.sh +78 -0
  10. cancan_microstack/assets/builds/caddy/waf/coraza.conf +179 -0
  11. cancan_microstack/assets/builds/service/Dockerfile +59 -0
  12. cancan_microstack/assets/builds/service/README.md +13 -0
  13. cancan_microstack/assets/ddl/create_db.sql +22 -0
  14. cancan_microstack/assets/ddl/infra/execution_log_tbl.sql +46 -0
  15. cancan_microstack/assets/ddl/infra/node_instance_tbl.sql +56 -0
  16. cancan_microstack/assets/ddl/infra/service_action_log_tbl.sql +36 -0
  17. cancan_microstack/assets/ddl/infra/service_config_tbl.sql +26 -0
  18. cancan_microstack/assets/ddl/infra/service_info_tbl.sql +45 -0
  19. cancan_microstack/assets/ddl/infra/service_instance_tbl.sql +54 -0
  20. cancan_microstack/assets/ddl/infra/service_operation_tbl.sql +47 -0
  21. cancan_microstack/assets/ddl/infra/workflow_definition_tbl.sql +60 -0
  22. cancan_microstack/assets/ddl/infra/workflow_definition_version_tbl.sql +35 -0
  23. cancan_microstack/assets/ddl/infra/workflow_engine_alert_tbl.sql +34 -0
  24. cancan_microstack/assets/ddl/infra/workflow_run_tbl.sql +52 -0
  25. cancan_microstack/assets/ddl/ops/admin_user_tbl.sql +34 -0
  26. cancan_microstack/assets/ddl/ops/caddy_access_log_tbl.sql +91 -0
  27. cancan_microstack/assets/ddl/ops/caddy_certificate_tbl.sql +59 -0
  28. cancan_microstack/assets/ddl/ops/caddy_rate_limit_tbl.sql +64 -0
  29. cancan_microstack/assets/ddl/ops/caddy_route_tbl.sql +63 -0
  30. cancan_microstack/assets/ddl/ops/caddy_stats_tbl.sql +77 -0
  31. cancan_microstack/assets/ddl/trigger.sql +21 -0
  32. cancan_microstack/assets/docker/docker-compose.infra.yml +401 -0
  33. cancan_microstack/assets/scripts/README.md +195 -0
  34. cancan_microstack/assets/scripts/docker/build_images.sh +44 -0
  35. cancan_microstack/assets/scripts/docker/force_rebuild_images.sh +38 -0
  36. cancan_microstack/assets/scripts/docker/rebuild_all.sh +34 -0
  37. cancan_microstack/assets/scripts/docker/rebuild_compose.sh +61 -0
  38. cancan_microstack/assets/scripts/docker/restart.sh +35 -0
  39. cancan_microstack/assets/scripts/docker/restart_compose.sh +35 -0
  40. cancan_microstack/assets/scripts/docker/start.sh +78 -0
  41. cancan_microstack/assets/scripts/docker/start_all.sh +46 -0
  42. cancan_microstack/assets/scripts/docker/start_compose.sh +66 -0
  43. cancan_microstack/assets/scripts/docker/stop.sh +67 -0
  44. cancan_microstack/assets/scripts/docker/stop_all.sh +38 -0
  45. cancan_microstack/assets/scripts/docker/stop_compose.sh +38 -0
  46. cancan_microstack/assets/scripts/podman/build_images_podman.sh +59 -0
  47. cancan_microstack/assets/scripts/podman/cleanup_podman.sh +25 -0
  48. cancan_microstack/assets/scripts/podman/force_rebuild_images_podman.sh +56 -0
  49. cancan_microstack/assets/scripts/podman/rebuild_all_podman.sh +37 -0
  50. cancan_microstack/assets/scripts/podman/rebuild_compose_podman.sh +60 -0
  51. cancan_microstack/assets/scripts/podman/restart_compose_podman.sh +73 -0
  52. cancan_microstack/assets/scripts/podman/start_all_podman.sh +66 -0
  53. cancan_microstack/assets/scripts/podman/start_compose_podman.sh +80 -0
  54. cancan_microstack/assets/scripts/podman/start_podman.sh +91 -0
  55. cancan_microstack/assets/scripts/podman/stop.sh +73 -0
  56. cancan_microstack/assets/scripts/podman/stop_all_podman.sh +34 -0
  57. cancan_microstack/assets/scripts/podman/stop_compose_podman.sh +58 -0
  58. cancan_microstack/assets/scripts/start_controllersrv.sh +9 -0
  59. cancan_microstack/assets/scripts/utils/check_all_db_tables.sh +104 -0
  60. cancan_microstack/assets/scripts/utils/check_env.sh +177 -0
  61. cancan_microstack/assets/scripts/utils/check_service_management_deployment.sh +225 -0
  62. cancan_microstack/assets/scripts/utils/deploy_service_management.sh +176 -0
  63. cancan_microstack/assets/scripts/utils/force_reload_infrasrv.sh +52 -0
  64. cancan_microstack/assets/scripts/utils/monitor_service_management.sh +187 -0
  65. cancan_microstack/assets/scripts/utils/reset_postgres_volume.sh +68 -0
  66. cancan_microstack/assets/scripts/utils/test_async_operations.sh +141 -0
  67. cancan_microstack/assets/scripts/utils/verify_real_operations.sh +76 -0
  68. cancan_microstack/assets/service/Dockerfile +65 -0
  69. cancan_microstack/assets/www/adminops/assets/AppEmpty.vue_vue_type_script_setup_true_lang-BOKUurnM.js +1 -0
  70. cancan_microstack/assets/www/adminops/assets/ConfigManage-DKV5YOUz.js +1 -0
  71. cancan_microstack/assets/www/adminops/assets/ConfigManage-Y5bhy7wG.css +1 -0
  72. cancan_microstack/assets/www/adminops/assets/ConsoleManage-8ljYvCW2.js +1 -0
  73. cancan_microstack/assets/www/adminops/assets/ConsoleManage-BWpyqbuQ.css +1 -0
  74. cancan_microstack/assets/www/adminops/assets/DashboardNew-B9Nf1OPl.js +1 -0
  75. cancan_microstack/assets/www/adminops/assets/DashboardNew-DYWZKQ1V.css +1 -0
  76. cancan_microstack/assets/www/adminops/assets/LogSearch-CA0Jhe78.js +1 -0
  77. cancan_microstack/assets/www/adminops/assets/LogSearch-CCZfTNPF.css +1 -0
  78. cancan_microstack/assets/www/adminops/assets/LoginView-BId3kP3M.css +1 -0
  79. cancan_microstack/assets/www/adminops/assets/LoginView-BQZTV_Qy.js +1 -0
  80. cancan_microstack/assets/www/adminops/assets/OperationProgressDialog-BdEYwqFq.js +1 -0
  81. cancan_microstack/assets/www/adminops/assets/OperationProgressDialog-D-pASR8G.css +1 -0
  82. cancan_microstack/assets/www/adminops/assets/PageContainer-Byss-yUC.js +1 -0
  83. cancan_microstack/assets/www/adminops/assets/PageContainer-C3nSZwM7.css +1 -0
  84. cancan_microstack/assets/www/adminops/assets/RateLimitManage-BDI8jLpC.css +1 -0
  85. cancan_microstack/assets/www/adminops/assets/RateLimitManage-DJY4NiF-.js +1 -0
  86. cancan_microstack/assets/www/adminops/assets/RouteManage-DaUQ4QLw.css +1 -0
  87. cancan_microstack/assets/www/adminops/assets/RouteManage-w9XCU0UA.js +1 -0
  88. cancan_microstack/assets/www/adminops/assets/ServiceCard-BFzHe6Tw.css +1 -0
  89. cancan_microstack/assets/www/adminops/assets/ServiceCard-BJUhWnA-.js +1 -0
  90. cancan_microstack/assets/www/adminops/assets/ServiceDetail-Cw24WuKp.js +1 -0
  91. cancan_microstack/assets/www/adminops/assets/ServiceDetail-Yum47zdB.css +1 -0
  92. cancan_microstack/assets/www/adminops/assets/ServiceList-C7ryvbhE.js +1 -0
  93. cancan_microstack/assets/www/adminops/assets/ServiceList-Cgd01fUx.css +1 -0
  94. cancan_microstack/assets/www/adminops/assets/ServiceLogs-COpG9H0h.js +1 -0
  95. cancan_microstack/assets/www/adminops/assets/ServiceLogs-H_Alq0cf.css +1 -0
  96. cancan_microstack/assets/www/adminops/assets/StatsOverview-D0TwMQkA.js +39 -0
  97. cancan_microstack/assets/www/adminops/assets/StatsOverview-lqAN6pqM.css +1 -0
  98. cancan_microstack/assets/www/adminops/assets/TotpBindView-CWlAmzFt.js +1 -0
  99. cancan_microstack/assets/www/adminops/assets/TotpBindView-HoQC1lhx.css +1 -0
  100. cancan_microstack/assets/www/adminops/assets/TotpVerifyView-BHN1VtX1.css +1 -0
  101. cancan_microstack/assets/www/adminops/assets/TotpVerifyView-D3w_lZk8.js +1 -0
  102. cancan_microstack/assets/www/adminops/assets/WorkflowCenter-DU_mpIA0.css +1 -0
  103. cancan_microstack/assets/www/adminops/assets/WorkflowCenter-i50rZyxN.js +1 -0
  104. cancan_microstack/assets/www/adminops/assets/WorkflowDesigner-CnHokPL9.js +1 -0
  105. cancan_microstack/assets/www/adminops/assets/WorkflowDesigner-DaZaZpLd.css +1 -0
  106. cancan_microstack/assets/www/adminops/assets/WorkflowRuns-B09hK48c.js +1 -0
  107. cancan_microstack/assets/www/adminops/assets/WorkflowRuns-wGutKIIU.css +1 -0
  108. cancan_microstack/assets/www/adminops/assets/caddy-nnCKf8fG.js +1 -0
  109. cancan_microstack/assets/www/adminops/assets/format-Cuzxgna9.js +1 -0
  110. cancan_microstack/assets/www/adminops/assets/index-CiFlm8oc.js +64 -0
  111. cancan_microstack/assets/www/adminops/assets/index-UW0T1Dkc.css +1 -0
  112. cancan_microstack/assets/www/adminops/assets/service-BYlgGPs_.js +1 -0
  113. cancan_microstack/assets/www/adminops/assets/service-operation-6GzLw2Z1.js +1 -0
  114. cancan_microstack/assets/www/adminops/assets/style-CcIXnQ5y.css +1 -0
  115. cancan_microstack/assets/www/adminops/assets/style-lRnStdGu.js +39 -0
  116. cancan_microstack/assets/www/adminops/assets/useDebounce-BRlqfXqf.js +1 -0
  117. cancan_microstack/assets/www/adminops/assets/workflow-CUXs39Ac.js +1 -0
  118. cancan_microstack/assets/www/adminops/index.html +16 -0
  119. cancan_microstack/assets/www/adminops/vite.svg +1 -0
  120. cancan_microstack/cli/__init__.py +14 -0
  121. cancan_microstack/cli/__main__.py +9 -0
  122. cancan_microstack/cli/main.py +552 -0
  123. cancan_microstack/cmd/__init__.py +54 -0
  124. cancan_microstack/cmd/cancan/__init__.py +12 -0
  125. cancan_microstack/cmd/cancan/run.py +395 -0
  126. cancan_microstack/cmd/controllersrv/__init__.py +0 -0
  127. cancan_microstack/cmd/controllersrv/run.py +131 -0
  128. cancan_microstack/cmd/infrasrv/__init__.py +5 -0
  129. cancan_microstack/cmd/infrasrv/run.py +100 -0
  130. cancan_microstack/cmd/opsbffsrv/__init__.py +5 -0
  131. cancan_microstack/cmd/opsbffsrv/run.py +96 -0
  132. cancan_microstack/core/__init__.py +5 -0
  133. cancan_microstack/core/assets.py +123 -0
  134. cancan_microstack/core/compose_builder.py +102 -0
  135. cancan_microstack/core/doctor.py +152 -0
  136. cancan_microstack/core/microstack.py +71 -0
  137. cancan_microstack/core/runner.py +56 -0
  138. cancan_microstack/core/stack_manager.py +186 -0
  139. cancan_microstack/public/__init__.py +7 -0
  140. cancan_microstack/public/api/__init__.py +1 -0
  141. cancan_microstack/public/api/controllersrv_client.py +277 -0
  142. cancan_microstack/public/api/infrasrv_client.py +404 -0
  143. cancan_microstack/public/const/__init__.py +1 -0
  144. cancan_microstack/public/const/action_consts.py +18 -0
  145. cancan_microstack/public/const/app_consts.py +42 -0
  146. cancan_microstack/public/const/caddy_consts.py +22 -0
  147. cancan_microstack/public/const/controllersrv_consts.py +163 -0
  148. cancan_microstack/public/const/docker_consts.py +15 -0
  149. cancan_microstack/public/const/error.py +56 -0
  150. cancan_microstack/public/const/health_consts.py +52 -0
  151. cancan_microstack/public/const/hook_enums.py +56 -0
  152. cancan_microstack/public/const/logging_enums.py +13 -0
  153. cancan_microstack/public/const/metrics_enums.py +36 -0
  154. cancan_microstack/public/const/monitor_enums.py +26 -0
  155. cancan_microstack/public/const/operation_consts.py +53 -0
  156. cancan_microstack/public/const/opsbffsrv_error.py +92 -0
  157. cancan_microstack/public/const/overrides_consts.py +13 -0
  158. cancan_microstack/public/const/redis.py +17 -0
  159. cancan_microstack/public/const/service_consts.py +15 -0
  160. cancan_microstack/public/const/workflow_consts.py +65 -0
  161. cancan_microstack/public/error.py +41 -0
  162. cancan_microstack/public/logging/__init__.py +0 -0
  163. cancan_microstack/public/logging/initializer.py +109 -0
  164. cancan_microstack/public/logging/mq_handler.py +279 -0
  165. cancan_microstack/public/schemas/__init__.py +1 -0
  166. cancan_microstack/public/schemas/caddy/__init__.py +381 -0
  167. cancan_microstack/public/schemas/caddy/analysis.py +90 -0
  168. cancan_microstack/public/schemas/caddy/route.py +18 -0
  169. cancan_microstack/public/schemas/common.py +79 -0
  170. cancan_microstack/public/schemas/controllersrv/__init__.py +3 -0
  171. cancan_microstack/public/schemas/controllersrv/async_requests.py +30 -0
  172. cancan_microstack/public/schemas/controllersrv/compose_models.py +47 -0
  173. cancan_microstack/public/schemas/controllersrv/const.py +24 -0
  174. cancan_microstack/public/schemas/controllersrv/docker_models.py +45 -0
  175. cancan_microstack/public/schemas/controllersrv/docker_responses.py +104 -0
  176. cancan_microstack/public/schemas/controllersrv/requests.py +54 -0
  177. cancan_microstack/public/schemas/controllersrv/responses.py +124 -0
  178. cancan_microstack/public/schemas/controllersrv/task_models.py +102 -0
  179. cancan_microstack/public/schemas/controllersrv/validation.py +23 -0
  180. cancan_microstack/public/schemas/hook_metrics.py +124 -0
  181. cancan_microstack/public/schemas/hooks.py +39 -0
  182. cancan_microstack/public/schemas/infra/__init__.py +0 -0
  183. cancan_microstack/public/schemas/infra/cleanup.py +25 -0
  184. cancan_microstack/public/schemas/infra/container.py +74 -0
  185. cancan_microstack/public/schemas/infra/enums.py +135 -0
  186. cancan_microstack/public/schemas/infra/health_check.py +42 -0
  187. cancan_microstack/public/schemas/infra/hook_log.py +42 -0
  188. cancan_microstack/public/schemas/infra/operation.py +90 -0
  189. cancan_microstack/public/schemas/infra/overview.py +25 -0
  190. cancan_microstack/public/schemas/infra/push.py +33 -0
  191. cancan_microstack/public/schemas/infra/service_action_log.py +47 -0
  192. cancan_microstack/public/schemas/infra/service_config.py +10 -0
  193. cancan_microstack/public/schemas/infra/service_info.py +69 -0
  194. cancan_microstack/public/schemas/infra/service_instance.py +93 -0
  195. cancan_microstack/public/schemas/infra/service_management.py +152 -0
  196. cancan_microstack/public/schemas/infra/service_operation.py +79 -0
  197. cancan_microstack/public/schemas/infra/service_registry.py +158 -0
  198. cancan_microstack/public/schemas/infra/status_types.py +19 -0
  199. cancan_microstack/public/schemas/infra/workflow.py +566 -0
  200. cancan_microstack/public/schemas/logging/__init__.py +1 -0
  201. cancan_microstack/public/schemas/logging/log_event.py +121 -0
  202. cancan_microstack/public/schemas/opsbffsrv/__init__.py +1 -0
  203. cancan_microstack/public/schemas/opsbffsrv/async_ops.py +17 -0
  204. cancan_microstack/public/schemas/opsbffsrv/db_admin.py +147 -0
  205. cancan_microstack/public/schemas/opsbffsrv/db_init.py +48 -0
  206. cancan_microstack/public/schemas/opsbffsrv/service_config.py +89 -0
  207. cancan_microstack/public/schemas/opsbffsrv/service_logs.py +54 -0
  208. cancan_microstack/public/schemas/service_operation.py +24 -0
  209. cancan_microstack/public/schemas/service_registry.py +40 -0
  210. cancan_microstack/public/types/__init__.py +7 -0
  211. cancan_microstack/public/web/__init__.py +0 -0
  212. cancan_microstack/public/web/config_value.py +105 -0
  213. cancan_microstack/public/web/server.py +385 -0
  214. cancan_microstack/py.typed +0 -0
  215. cancan_microstack/runtime/__init__.py +0 -0
  216. cancan_microstack/runtime/compose_cmd.py +228 -0
  217. cancan_microstack/runtime/host_daemon.py +318 -0
  218. cancan_microstack/runtime/overrides.py +103 -0
  219. cancan_microstack/runtime/resources.py +25 -0
  220. cancan_microstack/runtime/workspace.py +94 -0
  221. cancan_microstack/services/__init__.py +0 -0
  222. cancan_microstack/services/controllersrv/__init__.py +8 -0
  223. cancan_microstack/services/controllersrv/application/__init__.py +0 -0
  224. cancan_microstack/services/controllersrv/application/docker_compose_app.py +427 -0
  225. cancan_microstack/services/controllersrv/conf/__init__.py +0 -0
  226. cancan_microstack/services/controllersrv/conf/config.py +76 -0
  227. cancan_microstack/services/controllersrv/conf/settings.py +54 -0
  228. cancan_microstack/services/controllersrv/domain/__init__.py +0 -0
  229. cancan_microstack/services/controllersrv/domain/docker_compose/__init__.py +0 -0
  230. cancan_microstack/services/controllersrv/domain/docker_compose/docker_compose_domain.py +278 -0
  231. cancan_microstack/services/controllersrv/domain/service_validator.py +327 -0
  232. cancan_microstack/services/controllersrv/domain/task/__init__.py +17 -0
  233. cancan_microstack/services/controllersrv/domain/task/task_queue.py +286 -0
  234. cancan_microstack/services/controllersrv/domain/task/task_worker.py +495 -0
  235. cancan_microstack/services/controllersrv/infrastructure/__init__.py +0 -0
  236. cancan_microstack/services/controllersrv/interface/__init__.py +0 -0
  237. cancan_microstack/services/controllersrv/interface/api/__init__.py +0 -0
  238. cancan_microstack/services/controllersrv/interface/api/docker_control_api.py +470 -0
  239. cancan_microstack/services/controllersrv/router.py +132 -0
  240. cancan_microstack/services/infrasrv/__init__.py +4 -0
  241. cancan_microstack/services/infrasrv/application/__init__.py +0 -0
  242. cancan_microstack/services/infrasrv/application/health_check_app.py +24 -0
  243. cancan_microstack/services/infrasrv/application/logging/__init__.py +1 -0
  244. cancan_microstack/services/infrasrv/application/logging/log_ingestion_service.py +183 -0
  245. cancan_microstack/services/infrasrv/application/service_config.py +22 -0
  246. cancan_microstack/services/infrasrv/application/service_logs_app.py +53 -0
  247. cancan_microstack/services/infrasrv/application/service_management_app.py +689 -0
  248. cancan_microstack/services/infrasrv/application/service_operation_tracker.py +251 -0
  249. cancan_microstack/services/infrasrv/application/service_registry.py +53 -0
  250. cancan_microstack/services/infrasrv/application/workflow/__init__.py +0 -0
  251. cancan_microstack/services/infrasrv/application/workflow/workflow_app.py +991 -0
  252. cancan_microstack/services/infrasrv/application/workflow/workflow_queue.py +302 -0
  253. cancan_microstack/services/infrasrv/application/workflow/workflow_tasks.py +46 -0
  254. cancan_microstack/services/infrasrv/application/workflow/workflow_worker_runtime.py +122 -0
  255. cancan_microstack/services/infrasrv/conf/__init__.py +0 -0
  256. cancan_microstack/services/infrasrv/conf/config.py +98 -0
  257. cancan_microstack/services/infrasrv/domain/__init__.py +0 -0
  258. cancan_microstack/services/infrasrv/domain/health_check/__init__.py +3 -0
  259. cancan_microstack/services/infrasrv/domain/health_check/health_check_domain.py +576 -0
  260. cancan_microstack/services/infrasrv/domain/hooks/__init__.py +19 -0
  261. cancan_microstack/services/infrasrv/domain/hooks/builtin_hooks.py +308 -0
  262. cancan_microstack/services/infrasrv/domain/hooks/hook_registry.py +43 -0
  263. cancan_microstack/services/infrasrv/domain/hooks/hooks_log_utils.py +275 -0
  264. cancan_microstack/services/infrasrv/domain/hooks/init.py +17 -0
  265. cancan_microstack/services/infrasrv/domain/hooks/metrics.py +205 -0
  266. cancan_microstack/services/infrasrv/domain/hooks/pre_registration_hooks.py +490 -0
  267. cancan_microstack/services/infrasrv/domain/registry/__init__.py +0 -0
  268. cancan_microstack/services/infrasrv/domain/registry/service_registry.py +509 -0
  269. cancan_microstack/services/infrasrv/domain/service_config/__init__.py +0 -0
  270. cancan_microstack/services/infrasrv/domain/service_config/service_config.py +50 -0
  271. cancan_microstack/services/infrasrv/domain/service_logs/__init__.py +0 -0
  272. cancan_microstack/services/infrasrv/domain/service_logs/service_logs_domain.py +51 -0
  273. cancan_microstack/services/infrasrv/domain/workflow/__init__.py +4 -0
  274. cancan_microstack/services/infrasrv/domain/workflow/engine.py +159 -0
  275. cancan_microstack/services/infrasrv/domain/workflow/node_handlers.py +509 -0
  276. cancan_microstack/services/infrasrv/domain/workflow/workflow_domain.py +164 -0
  277. cancan_microstack/services/infrasrv/infrastructure/__init__.py +0 -0
  278. cancan_microstack/services/infrasrv/infrastructure/api/__init__.py +0 -0
  279. cancan_microstack/services/infrasrv/infrastructure/api/controllersrv_api.py +165 -0
  280. cancan_microstack/services/infrasrv/infrastructure/cache/__init__.py +0 -0
  281. cancan_microstack/services/infrasrv/infrastructure/cache/service_registry_cache.py +174 -0
  282. cancan_microstack/services/infrasrv/infrastructure/db/__init__.py +0 -0
  283. cancan_microstack/services/infrasrv/infrastructure/db/model/__init__.py +0 -0
  284. cancan_microstack/services/infrasrv/infrastructure/db/model/execution_log_tbl.py +53 -0
  285. cancan_microstack/services/infrasrv/infrastructure/db/model/node_instance_tbl.py +55 -0
  286. cancan_microstack/services/infrasrv/infrastructure/db/model/service_action_log_tbl.py +44 -0
  287. cancan_microstack/services/infrasrv/infrastructure/db/model/service_config_tbl.py +30 -0
  288. cancan_microstack/services/infrasrv/infrastructure/db/model/service_info_tbl.py +59 -0
  289. cancan_microstack/services/infrasrv/infrastructure/db/model/service_instance_tbl.py +88 -0
  290. cancan_microstack/services/infrasrv/infrastructure/db/model/service_operation_tbl.py +73 -0
  291. cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_definition_tbl.py +55 -0
  292. cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_definition_version_tbl.py +43 -0
  293. cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_engine_alert_tbl.py +57 -0
  294. cancan_microstack/services/infrasrv/infrastructure/db/model/workflow_run_tbl.py +56 -0
  295. cancan_microstack/services/infrasrv/infrastructure/db/operate/__init__.py +0 -0
  296. cancan_microstack/services/infrasrv/infrastructure/db/operate/service_action_log_op.py +239 -0
  297. cancan_microstack/services/infrasrv/infrastructure/db/operate/service_config.py +80 -0
  298. cancan_microstack/services/infrasrv/infrastructure/db/operate/service_config_manager.py +198 -0
  299. cancan_microstack/services/infrasrv/infrastructure/db/operate/service_info_op.py +297 -0
  300. cancan_microstack/services/infrasrv/infrastructure/db/operate/service_instance_op.py +688 -0
  301. cancan_microstack/services/infrasrv/infrastructure/db/operate/service_operation_op.py +387 -0
  302. cancan_microstack/services/infrasrv/infrastructure/db/operate/service_registry.py +124 -0
  303. cancan_microstack/services/infrasrv/infrastructure/db/operate/workflow_op.py +804 -0
  304. cancan_microstack/services/infrasrv/infrastructure/ddl_manager.py +31 -0
  305. cancan_microstack/services/infrasrv/infrastructure/mongo/__init__.py +1 -0
  306. cancan_microstack/services/infrasrv/infrastructure/mongo/log_repository.py +129 -0
  307. cancan_microstack/services/infrasrv/interface/__init__.py +0 -0
  308. cancan_microstack/services/infrasrv/interface/api/__init__.py +0 -0
  309. cancan_microstack/services/infrasrv/interface/api/health_check_api.py +29 -0
  310. cancan_microstack/services/infrasrv/interface/api/hooks.py +284 -0
  311. cancan_microstack/services/infrasrv/interface/api/internal.py +49 -0
  312. cancan_microstack/services/infrasrv/interface/api/internal_instance_api.py +265 -0
  313. cancan_microstack/services/infrasrv/interface/api/internal_operation_api.py +206 -0
  314. cancan_microstack/services/infrasrv/interface/api/service_config.py +50 -0
  315. cancan_microstack/services/infrasrv/interface/api/service_logs_api.py +49 -0
  316. cancan_microstack/services/infrasrv/interface/api/service_management_api.py +113 -0
  317. cancan_microstack/services/infrasrv/interface/api/service_registry.py +117 -0
  318. cancan_microstack/services/infrasrv/interface/api/workflow_api.py +303 -0
  319. cancan_microstack/services/infrasrv/interface/schedule/__init__.py +0 -0
  320. cancan_microstack/services/infrasrv/interface/schedule/cleanup.py +13 -0
  321. cancan_microstack/services/infrasrv/interface/schedule/health_check.py +27 -0
  322. cancan_microstack/services/infrasrv/interface/schedule/log_cleanup.py +26 -0
  323. cancan_microstack/services/infrasrv/interface/schedule/operation_tracker.py +25 -0
  324. cancan_microstack/services/infrasrv/interface/schedule/scheduler.py +39 -0
  325. cancan_microstack/services/infrasrv/interface/schedule/workflow_scheduler.py +115 -0
  326. cancan_microstack/services/infrasrv/router.py +341 -0
  327. cancan_microstack/services/opsbffsrv/__init__.py +4 -0
  328. cancan_microstack/services/opsbffsrv/application/__init__.py +0 -0
  329. cancan_microstack/services/opsbffsrv/application/async_operation_app.py +150 -0
  330. cancan_microstack/services/opsbffsrv/application/auth_app.py +285 -0
  331. cancan_microstack/services/opsbffsrv/application/caddy/__init__.py +0 -0
  332. cancan_microstack/services/opsbffsrv/application/caddy/access_log_analysis_app.py +344 -0
  333. cancan_microstack/services/opsbffsrv/application/caddy/access_log_ingestion_service.py +169 -0
  334. cancan_microstack/services/opsbffsrv/application/caddy/certificate_management_app.py +355 -0
  335. cancan_microstack/services/opsbffsrv/application/caddy/rate_limit_management_app.py +496 -0
  336. cancan_microstack/services/opsbffsrv/application/caddy/route_management_app.py +401 -0
  337. cancan_microstack/services/opsbffsrv/application/caddy/stats_aggregation_app.py +364 -0
  338. cancan_microstack/services/opsbffsrv/application/db_admin_app.py +103 -0
  339. cancan_microstack/services/opsbffsrv/application/db_init_app.py +283 -0
  340. cancan_microstack/services/opsbffsrv/application/logging/__init__.py +1 -0
  341. cancan_microstack/services/opsbffsrv/application/logging/log_query_app.py +28 -0
  342. cancan_microstack/services/opsbffsrv/application/service_config.py +158 -0
  343. cancan_microstack/services/opsbffsrv/application/service_logs_app.py +74 -0
  344. cancan_microstack/services/opsbffsrv/application/service_registry.py +36 -0
  345. cancan_microstack/services/opsbffsrv/application/workflow_ops_app.py +730 -0
  346. cancan_microstack/services/opsbffsrv/conf/__init__.py +0 -0
  347. cancan_microstack/services/opsbffsrv/conf/config.py +224 -0
  348. cancan_microstack/services/opsbffsrv/domain/__init__.py +0 -0
  349. cancan_microstack/services/opsbffsrv/domain/auth/__init__.py +0 -0
  350. cancan_microstack/services/opsbffsrv/domain/auth/admin_init.py +38 -0
  351. cancan_microstack/services/opsbffsrv/domain/auth/auth_domain.py +108 -0
  352. cancan_microstack/services/opsbffsrv/domain/caddy/__init__.py +0 -0
  353. cancan_microstack/services/opsbffsrv/domain/caddy/access_log_analysis.py +358 -0
  354. cancan_microstack/services/opsbffsrv/domain/caddy/certificate_management.py +325 -0
  355. cancan_microstack/services/opsbffsrv/domain/caddy/default_routes.py +53 -0
  356. cancan_microstack/services/opsbffsrv/domain/caddy/rate_limit_management.py +308 -0
  357. cancan_microstack/services/opsbffsrv/domain/caddy/route_management.py +279 -0
  358. cancan_microstack/services/opsbffsrv/domain/caddy/stats_aggregation.py +654 -0
  359. cancan_microstack/services/opsbffsrv/domain/db_admin/__init__.py +0 -0
  360. cancan_microstack/services/opsbffsrv/domain/db_admin/db_admin_domain.py +118 -0
  361. cancan_microstack/services/opsbffsrv/domain/db_init/__init__.py +3 -0
  362. cancan_microstack/services/opsbffsrv/domain/db_init/db_init_domain.py +358 -0
  363. cancan_microstack/services/opsbffsrv/domain/logging/__init__.py +1 -0
  364. cancan_microstack/services/opsbffsrv/domain/logging/log_query_domain.py +99 -0
  365. cancan_microstack/services/opsbffsrv/domain/service_config/__init__.py +0 -0
  366. cancan_microstack/services/opsbffsrv/domain/service_config/service_config.py +81 -0
  367. cancan_microstack/services/opsbffsrv/domain/service_registry/__init__.py +0 -0
  368. cancan_microstack/services/opsbffsrv/domain/service_registry/service_registry.py +292 -0
  369. cancan_microstack/services/opsbffsrv/infrastructure/__init__.py +0 -0
  370. cancan_microstack/services/opsbffsrv/infrastructure/api/__init__.py +0 -0
  371. cancan_microstack/services/opsbffsrv/infrastructure/api/infrasrv_api.py +242 -0
  372. cancan_microstack/services/opsbffsrv/infrastructure/auth/__init__.py +0 -0
  373. cancan_microstack/services/opsbffsrv/infrastructure/auth/captcha_service.py +67 -0
  374. cancan_microstack/services/opsbffsrv/infrastructure/auth/password_service.py +12 -0
  375. cancan_microstack/services/opsbffsrv/infrastructure/auth/redis_store.py +131 -0
  376. cancan_microstack/services/opsbffsrv/infrastructure/auth/totp_service.py +59 -0
  377. cancan_microstack/services/opsbffsrv/infrastructure/caddy/__init__.py +0 -0
  378. cancan_microstack/services/opsbffsrv/infrastructure/caddy/access_log_parser.py +307 -0
  379. cancan_microstack/services/opsbffsrv/infrastructure/caddy/admin_api_client.py +678 -0
  380. cancan_microstack/services/opsbffsrv/infrastructure/caddy/ip_geo_locator.py +176 -0
  381. cancan_microstack/services/opsbffsrv/infrastructure/db/__init__.py +0 -0
  382. cancan_microstack/services/opsbffsrv/infrastructure/db/model/__init__.py +0 -0
  383. cancan_microstack/services/opsbffsrv/infrastructure/db/model/admin_user_tbl.py +33 -0
  384. cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_access_log_tbl.py +90 -0
  385. cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_certificate_tbl.py +65 -0
  386. cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_rate_limit_tbl.py +69 -0
  387. cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_route_tbl.py +66 -0
  388. cancan_microstack/services/opsbffsrv/infrastructure/db/model/caddy_stats_tbl.py +78 -0
  389. cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_action_log_tbl.py +44 -0
  390. cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_config_tbl.py +30 -0
  391. cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_info_tbl.py +51 -0
  392. cancan_microstack/services/opsbffsrv/infrastructure/db/model/service_instance_tbl.py +68 -0
  393. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/__init__.py +0 -0
  394. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/admin_user_operate.py +59 -0
  395. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_access_log.py +531 -0
  396. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_certificate.py +451 -0
  397. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_rate_limit.py +360 -0
  398. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_route.py +271 -0
  399. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/caddy_stats.py +343 -0
  400. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_action_log_op.py +57 -0
  401. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_config.py +86 -0
  402. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_info_op.py +79 -0
  403. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_instance.py +58 -0
  404. cancan_microstack/services/opsbffsrv/infrastructure/db/operate/service_registry.py +138 -0
  405. cancan_microstack/services/opsbffsrv/infrastructure/ddl_manager.py +31 -0
  406. cancan_microstack/services/opsbffsrv/infrastructure/mongo/__init__.py +1 -0
  407. cancan_microstack/services/opsbffsrv/infrastructure/mongo/log_query_repository.py +87 -0
  408. cancan_microstack/services/opsbffsrv/interface/__init__.py +0 -0
  409. cancan_microstack/services/opsbffsrv/interface/api/__init__.py +0 -0
  410. cancan_microstack/services/opsbffsrv/interface/api/async_operation_api.py +137 -0
  411. cancan_microstack/services/opsbffsrv/interface/api/auth_api.py +113 -0
  412. cancan_microstack/services/opsbffsrv/interface/api/caddy/__init__.py +3 -0
  413. cancan_microstack/services/opsbffsrv/interface/api/caddy/access_log_api.py +174 -0
  414. cancan_microstack/services/opsbffsrv/interface/api/caddy/certificate_api.py +235 -0
  415. cancan_microstack/services/opsbffsrv/interface/api/caddy/rate_limit_api.py +302 -0
  416. cancan_microstack/services/opsbffsrv/interface/api/caddy/route_api.py +250 -0
  417. cancan_microstack/services/opsbffsrv/interface/api/caddy/stats_api.py +243 -0
  418. cancan_microstack/services/opsbffsrv/interface/api/db_admin_api.py +62 -0
  419. cancan_microstack/services/opsbffsrv/interface/api/db_init_api.py +109 -0
  420. cancan_microstack/services/opsbffsrv/interface/api/instance_management_api.py +165 -0
  421. cancan_microstack/services/opsbffsrv/interface/api/log_query_api.py +41 -0
  422. cancan_microstack/services/opsbffsrv/interface/api/mongo_express_proxy_api.py +181 -0
  423. cancan_microstack/services/opsbffsrv/interface/api/pgweb_proxy_api.py +154 -0
  424. cancan_microstack/services/opsbffsrv/interface/api/rabbitmq_mgmt_proxy_api.py +518 -0
  425. cancan_microstack/services/opsbffsrv/interface/api/redis_commander_proxy_api.py +133 -0
  426. cancan_microstack/services/opsbffsrv/interface/api/service_config.py +146 -0
  427. cancan_microstack/services/opsbffsrv/interface/api/service_logs_api.py +81 -0
  428. cancan_microstack/services/opsbffsrv/interface/api/service_registry.py +66 -0
  429. cancan_microstack/services/opsbffsrv/interface/api/workflow_ops_api.py +413 -0
  430. cancan_microstack/services/opsbffsrv/interface/middleware/__init__.py +0 -0
  431. cancan_microstack/services/opsbffsrv/interface/middleware/auth_middleware.py +52 -0
  432. cancan_microstack/services/opsbffsrv/router.py +901 -0
  433. cancan_microstack/utils/__init__.py +1 -0
  434. cancan_microstack/utils/container_env.py +218 -0
  435. cancan_microstack-0.0.1.dist-info/METADATA +155 -0
  436. cancan_microstack-0.0.1.dist-info/RECORD +440 -0
  437. cancan_microstack-0.0.1.dist-info/WHEEL +5 -0
  438. cancan_microstack-0.0.1.dist-info/entry_points.txt +2 -0
  439. cancan_microstack-0.0.1.dist-info/licenses/LICENSE +21 -0
  440. cancan_microstack-0.0.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,131 @@
1
+ """Redis session / 限频 / 验证码存储 / Redis store for auth data."""
2
+ from typing import Optional
3
+
4
+ import redis.asyncio as aioredis
5
+
6
+ from linglong_web import LinglongConfig
7
+
8
+ _redis: Optional[aioredis.Redis] = None
9
+
10
+ _KEY_PREFIX = "ops"
11
+
12
+
13
+ async def _get_redis() -> aioredis.Redis:
14
+ """懒初始化 Redis 连接 / Lazy-initialize async Redis connection."""
15
+ global _redis
16
+ if _redis is None:
17
+ host = LinglongConfig.get("AUTH_REDIS_URL", "redis://redis.service:6379/0")
18
+ _redis = aioredis.from_url(host, decode_responses=True)
19
+ return _redis
20
+
21
+
22
+ # ── Captcha ──────────────────────────────────────────────────────────────────
23
+
24
+ async def save_captcha(captcha_id: str, answer: str, ttl: int = 60) -> None:
25
+ """存储验证码答案 / Save captcha answer to Redis."""
26
+ r = await _get_redis()
27
+ await r.setex(f"{_KEY_PREFIX}:captcha:{captcha_id}", ttl, answer.upper())
28
+
29
+
30
+ async def get_and_delete_captcha(captcha_id: str) -> Optional[str]:
31
+ """获取并删除验证码(一次性消费)/ Get and delete captcha answer atomically."""
32
+ r = await _get_redis()
33
+ key = f"{_KEY_PREFIX}:captcha:{captcha_id}"
34
+ answer = await r.get(key)
35
+ if answer is not None:
36
+ await r.delete(key)
37
+ return answer
38
+
39
+
40
+ # ── Session ──────────────────────────────────────────────────────────────────
41
+
42
+ async def save_session(token: str, user_id: int, ttl: int = 86400) -> None:
43
+ """存储 session token / Save session token to Redis."""
44
+ r = await _get_redis()
45
+ await r.setex(f"{_KEY_PREFIX}:session:{token}", ttl, str(user_id))
46
+
47
+
48
+ async def get_session(token: str) -> Optional[int]:
49
+ """获取 session 对应的 user_id / Get user_id from session token."""
50
+ r = await _get_redis()
51
+ val = await r.get(f"{_KEY_PREFIX}:session:{token}")
52
+ return int(val) if val is not None else None
53
+
54
+
55
+ async def delete_session(token: str) -> None:
56
+ """删除 session token / Delete (revoke) a session token."""
57
+ r = await _get_redis()
58
+ await r.delete(f"{_KEY_PREFIX}:session:{token}")
59
+
60
+
61
+ # ── Temp Token ───────────────────────────────────────────────────────────────
62
+
63
+ async def save_temp_token(token: str, user_id: int, ttl: int = 300) -> None:
64
+ """存储临时 token / Save temp token for TOTP flow."""
65
+ r = await _get_redis()
66
+ await r.setex(f"{_KEY_PREFIX}:temp_token:{token}", ttl, str(user_id))
67
+
68
+
69
+ async def get_temp_token(token: str) -> Optional[int]:
70
+ """获取临时 token 对应的 user_id / Get user_id from temp token."""
71
+ r = await _get_redis()
72
+ val = await r.get(f"{_KEY_PREFIX}:temp_token:{token}")
73
+ return int(val) if val is not None else None
74
+
75
+
76
+ async def delete_temp_token(token: str) -> None:
77
+ """删除临时 token / Delete temp token."""
78
+ r = await _get_redis()
79
+ await r.delete(f"{_KEY_PREFIX}:temp_token:{token}")
80
+
81
+
82
+ # ── IP Rate Limit ────────────────────────────────────────────────────────────
83
+
84
+ async def get_ip_fail_count(ip: str) -> int:
85
+ """获取 IP 失败次数 / Get login failure count for an IP."""
86
+ r = await _get_redis()
87
+ val = await r.get(f"{_KEY_PREFIX}:rate_limit:ip:{ip}")
88
+ return int(val) if val is not None else 0
89
+
90
+
91
+ async def increment_ip_fail(ip: str, ttl: int = 1800) -> int:
92
+ """递增 IP 失败计数 / Increment IP failure count with TTL."""
93
+ r = await _get_redis()
94
+ key = f"{_KEY_PREFIX}:rate_limit:ip:{ip}"
95
+ count = await r.incr(key)
96
+ await r.expire(key, ttl)
97
+ return count
98
+
99
+
100
+ async def reset_ip_fail(ip: str) -> None:
101
+ """重置 IP 失败计数 / Reset IP failure count."""
102
+ r = await _get_redis()
103
+ await r.delete(f"{_KEY_PREFIX}:rate_limit:ip:{ip}")
104
+
105
+
106
+ # ── TOTP Failure Count (per temp_token) ───────────────────────────────────────
107
+
108
+ async def get_totp_fail_count(temp_token: str) -> int:
109
+ """获取 temp_token 的 TOTP 失败次数 / Get TOTP failure count for a temp token."""
110
+ r = await _get_redis()
111
+ val = await r.get(f"{_KEY_PREFIX}:totp_fail:{temp_token}")
112
+ return int(val) if val is not None else 0
113
+
114
+
115
+ async def increment_totp_fail(temp_token: str, ttl: int = 300) -> int:
116
+ """递增 TOTP 失败计数 / Increment TOTP failure count with TTL.
117
+
118
+ TTL 跟随 temp_token 生命周期,避免计数长期残留。
119
+ TTL follows the temp_token lifetime so the counter does not linger.
120
+ """
121
+ r = await _get_redis()
122
+ key = f"{_KEY_PREFIX}:totp_fail:{temp_token}"
123
+ count = await r.incr(key)
124
+ await r.expire(key, ttl)
125
+ return count
126
+
127
+
128
+ async def reset_totp_fail(temp_token: str) -> None:
129
+ """重置 TOTP 失败计数 / Reset TOTP failure count for a temp token."""
130
+ r = await _get_redis()
131
+ await r.delete(f"{_KEY_PREFIX}:totp_fail:{temp_token}")
@@ -0,0 +1,59 @@
1
+ """TOTP 封装 / TOTP service wrapping pyotp + Fernet encryption."""
2
+ import base64
3
+ import io
4
+
5
+ import pyotp
6
+ import qrcode
7
+ from cryptography.fernet import Fernet
8
+
9
+ from linglong_web import LinglongConfig
10
+
11
+
12
+ def _get_fernet() -> Fernet:
13
+ """获取 Fernet 实例 / Get Fernet instance from config."""
14
+ key = LinglongConfig.get("AUTH_TOTP_FERNET_KEY")
15
+ if not key:
16
+ raise RuntimeError("AUTH_TOTP_FERNET_KEY is not configured")
17
+ return Fernet(key.encode("utf-8") if isinstance(key, str) else key)
18
+
19
+
20
+ def generate_secret() -> str:
21
+ """生成 TOTP base32 secret / Generate a random TOTP base32 secret."""
22
+ return pyotp.random_base32()
23
+
24
+
25
+ def encrypt_secret(secret: str) -> str:
26
+ """Fernet 加密 TOTP secret / Encrypt TOTP secret with Fernet."""
27
+ f = _get_fernet()
28
+ return f.encrypt(secret.encode("utf-8")).decode("utf-8")
29
+
30
+
31
+ def decrypt_secret(encrypted: str) -> str:
32
+ """Fernet 解密 TOTP secret / Decrypt TOTP secret with Fernet."""
33
+ f = _get_fernet()
34
+ return f.decrypt(encrypted.encode("utf-8")).decode("utf-8")
35
+
36
+
37
+ def verify_totp(secret: str, code: str) -> bool:
38
+ """验证 TOTP 码 / Verify a TOTP code against secret (±30s window)."""
39
+ totp = pyotp.TOTP(secret)
40
+ return totp.verify(code, valid_window=1)
41
+
42
+
43
+ def get_provisioning_uri(secret: str, username: str) -> str:
44
+ """生成 otpauth URI / Generate provisioning URI for authenticator apps."""
45
+ issuer = LinglongConfig.get("AUTH_TOTP_ISSUER", "OPS Admin")
46
+ totp = pyotp.TOTP(secret)
47
+ return totp.provisioning_uri(name=username, issuer_name=issuer)
48
+
49
+
50
+ def generate_qr_base64(uri: str) -> str:
51
+ """生成 QR 二维码 base64 / Generate QR code as data URI base64 PNG."""
52
+ qr = qrcode.QRCode(version=1, box_size=6, border=2)
53
+ qr.add_data(uri)
54
+ qr.make(fit=True)
55
+ img = qr.make_image(fill_color="black", back_color="white")
56
+ buf = io.BytesIO()
57
+ img.save(buf, format="PNG")
58
+ b64 = base64.b64encode(buf.getvalue()).decode("utf-8")
59
+ return f"data:image/png;base64,{b64}"
@@ -0,0 +1,307 @@
1
+ """
2
+ Caddy 访问日志解析器
3
+ 解析 Caddy JSON 格式的访问日志并提取关键信息
4
+ """
5
+ from typing import (
6
+ Any,
7
+ Dict,
8
+ Optional,
9
+ )
10
+ import json
11
+ from datetime import datetime, timezone
12
+ from nanoid import generate
13
+ from linglong_web.utils import logger
14
+ from cancan_microstack.public.schemas.caddy import CaddyAccessLog
15
+ from cancan_microstack.services.opsbffsrv.infrastructure.caddy.ip_geo_locator import ip_geo_locator
16
+
17
+
18
+ class AccessLogParser:
19
+ """访问日志解析器"""
20
+
21
+ @staticmethod
22
+ def parse_json_log(log_line: str) -> Optional[CaddyAccessLog]:
23
+ """
24
+ 解析 JSON 格式的访问日志行
25
+
26
+ Args:
27
+ log_line: JSON 格式的日志行
28
+
29
+ Returns:
30
+ 访问日志对象或 None
31
+ """
32
+ try:
33
+ log_data = json.loads(log_line)
34
+ return AccessLogParser._build_access_log(log_data)
35
+ except json.JSONDecodeError as e:
36
+ logger.error(f"Failed to parse JSON log: {e}", exc_info=True)
37
+ return None
38
+ except Exception as e:
39
+ logger.error(f"Error parsing access log: {e}", exc_info=True)
40
+ return None
41
+
42
+ @staticmethod
43
+ def parse_dict_log(log_data: Dict[str, Any]) -> Optional[CaddyAccessLog]:
44
+ """
45
+ 解析字典格式的访问日志
46
+
47
+ Args:
48
+ log_data: 日志数据字典
49
+
50
+ Returns:
51
+ 访问日志对象或 None
52
+ """
53
+ try:
54
+ return AccessLogParser._build_access_log(log_data)
55
+ except Exception as e:
56
+ logger.error(f"Error parsing access log dict: {e}", exc_info=True)
57
+ return None
58
+
59
+ @staticmethod
60
+ def _build_access_log(log_data: Dict[str, Any]) -> CaddyAccessLog:
61
+ """
62
+ 从日志数据构建 CaddyAccessLog 对象
63
+
64
+ Args:
65
+ log_data: 日志数据字典
66
+
67
+ Returns:
68
+ 访问日志对象
69
+ """
70
+ # 提取基础信息
71
+ request = log_data.get("request", {})
72
+ response = log_data.get("resp_headers", {})
73
+
74
+ # 提取客户端 IP(处理代理情况)
75
+ client_ip = AccessLogParser._extract_client_ip(log_data)
76
+
77
+ # 提取请求 ID(优先使用 X-Linglong-Reqid,其次 X-Request-Id)
78
+ # Extract request ID preferring X-Linglong-Reqid, then X-Request-Id
79
+ request_id = (
80
+ log_data.get("request_id")
81
+ or response.get("X-Linglong-Reqid", [None])[0]
82
+ or response.get("X-Request-Id", [None])[0]
83
+ or generate()
84
+ )
85
+
86
+ # 提取时间戳
87
+ timestamp_str = log_data.get("ts") or log_data.get("timestamp")
88
+ timestamp = AccessLogParser._parse_timestamp(timestamp_str)
89
+
90
+ # 提取路径和查询字符串
91
+ uri = request.get("uri", "")
92
+ path, query_string = AccessLogParser._split_uri(uri)
93
+
94
+ # 获取 IP 地理位置信息
95
+ geo_info = ip_geo_locator.lookup(client_ip) if client_ip else {}
96
+
97
+ # 提取 WAF 信息
98
+ waf_action = log_data.get("waf_action")
99
+ waf_rule_id = log_data.get("waf_rule_id")
100
+ waf_score = log_data.get("waf_score")
101
+
102
+ # 提取限流信息
103
+ rate_limited = log_data.get("rate_limited", False)
104
+ rate_limit_rule = log_data.get("rate_limit_rule")
105
+
106
+ # 提取上游信息
107
+ upstream_info = log_data.get("upstream", {})
108
+
109
+ # 提取 TLS 信息
110
+ tls_info = request.get("tls", {})
111
+
112
+ # 构建访问日志对象
113
+ return CaddyAccessLog(
114
+ request_id=request_id,
115
+ timestamp=timestamp,
116
+ client_ip=client_ip,
117
+ client_port=AccessLogParser._extract_client_port(log_data),
118
+ user_agent=request.get("headers", {}).get("User-Agent", [None])[0],
119
+ referer=request.get("headers", {}).get("Referer", [None])[0],
120
+ country=geo_info.get("country"),
121
+ country_code=geo_info.get("country_code"),
122
+ region=geo_info.get("region"),
123
+ city=geo_info.get("city"),
124
+ latitude=geo_info.get("latitude"),
125
+ longitude=geo_info.get("longitude"),
126
+ timezone=geo_info.get("timezone"),
127
+ isp=geo_info.get("isp"),
128
+ method=request.get("method", "GET"),
129
+ protocol=request.get("proto", "HTTP/1.1"),
130
+ host=request.get("host"),
131
+ path=path,
132
+ query_string=query_string,
133
+ matched_route=log_data.get("matched_route"),
134
+ upstream_service=upstream_info.get("service"),
135
+ upstream_host=upstream_info.get("host"),
136
+ upstream_port=upstream_info.get("port"),
137
+ status_code=log_data.get("status", 0),
138
+ response_size=log_data.get("size"),
139
+ response_time=AccessLogParser._parse_duration(log_data.get("duration")),
140
+ waf_action=waf_action,
141
+ waf_rule_id=waf_rule_id,
142
+ waf_score=waf_score,
143
+ rate_limited=rate_limited,
144
+ rate_limit_rule=rate_limit_rule,
145
+ tls_version=tls_info.get("version"),
146
+ tls_cipher=tls_info.get("cipher_suite"),
147
+ log_metadata=AccessLogParser._extract_log_metadata(log_data),
148
+ )
149
+
150
+ @staticmethod
151
+ def _extract_client_ip(log_data: Dict[str, Any]) -> str:
152
+ """
153
+ 提取客户端真实 IP
154
+
155
+ 优先级:X-Forwarded-For > X-Real-IP > remote_ip
156
+
157
+ Args:
158
+ log_data: 日志数据字典
159
+
160
+ Returns:
161
+ 客户端 IP
162
+ """
163
+ request = log_data.get("request", {})
164
+ headers = request.get("headers", {})
165
+
166
+ # 检查 X-Forwarded-For
167
+ x_forwarded_for = headers.get("X-Forwarded-For", [None])[0]
168
+ if x_forwarded_for:
169
+ # 取第一个 IP(客户端真实 IP)
170
+ return x_forwarded_for.split(',')[0].strip()
171
+
172
+ # 检查 X-Real-IP
173
+ x_real_ip = headers.get("X-Real-IP", [None])[0]
174
+ if x_real_ip:
175
+ return x_real_ip
176
+
177
+ # 使用 remote_ip
178
+ return request.get("remote_ip", "unknown")
179
+
180
+ @staticmethod
181
+ def _extract_client_port(log_data: Dict[str, Any]) -> Optional[int]:
182
+ """
183
+ 提取客户端端口
184
+
185
+ Args:
186
+ log_data: 日志数据字典
187
+
188
+ Returns:
189
+ 客户端端口或 None
190
+ """
191
+ try:
192
+ remote_port = log_data.get("request", {}).get("remote_port")
193
+ if remote_port is not None:
194
+ return int(remote_port)
195
+
196
+ remote_addr = log_data.get("request", {}).get("remote_addr", "")
197
+ if ':' in remote_addr:
198
+ return int(remote_addr.split(':')[-1])
199
+ except Exception:
200
+ pass
201
+ return None
202
+
203
+ @staticmethod
204
+ def _parse_timestamp(timestamp_str: Optional[str]) -> datetime:
205
+ """
206
+ 解析时间戳字符串
207
+
208
+ Args:
209
+ timestamp_str: 时间戳字符串
210
+
211
+ Returns:
212
+ datetime 对象
213
+ """
214
+ if not timestamp_str:
215
+ return datetime.now(timezone.utc)
216
+
217
+ try:
218
+ # Caddy 使用 Unix 时间戳(秒)
219
+ if isinstance(timestamp_str, (int, float)):
220
+ return datetime.fromtimestamp(timestamp_str, tz=timezone.utc)
221
+
222
+ # 尝试解析 ISO 格式
223
+ parsed = datetime.fromisoformat(str(timestamp_str).replace('Z', '+00:00'))
224
+ if parsed.tzinfo is None:
225
+ return parsed.replace(tzinfo=timezone.utc)
226
+ return parsed
227
+ except Exception as e:
228
+ logger.warning(f"Failed to parse timestamp '{timestamp_str}': {e}")
229
+ return datetime.now(timezone.utc)
230
+
231
+ @staticmethod
232
+ def _parse_duration(duration_str: Optional[Any]) -> Optional[int]:
233
+ """
234
+ 解析持续时间字符串(转换为毫秒)
235
+
236
+ Args:
237
+ duration_str: 持续时间字符串(如 "0.123s" 或 123000000 纳秒)
238
+
239
+ Returns:
240
+ 毫秒数或 None
241
+ """
242
+ if not duration_str:
243
+ return None
244
+
245
+ try:
246
+ # Caddy 常见格式:float 秒(如 0.0123)
247
+ if isinstance(duration_str, float):
248
+ return int(duration_str * 1000)
249
+
250
+ # 整数格式:兼容纳秒与毫秒
251
+ if isinstance(duration_str, int):
252
+ if duration_str > 1_000_000:
253
+ return duration_str // 1_000_000 # 纳秒转毫秒
254
+ return duration_str
255
+
256
+ # 如果是字符串(如 "0.123s")
257
+ if isinstance(duration_str, str):
258
+ if duration_str.endswith('s'):
259
+ seconds = float(duration_str[:-1])
260
+ return int(seconds * 1000)
261
+ elif duration_str.endswith('ms'):
262
+ return int(float(duration_str[:-2]))
263
+ except Exception as e:
264
+ logger.warning(f"Failed to parse duration '{duration_str}': {e}")
265
+
266
+ return None
267
+
268
+ @staticmethod
269
+ def _split_uri(uri: str) -> tuple:
270
+ """
271
+ 分割 URI 为路径和查询字符串
272
+
273
+ Args:
274
+ uri: 完整 URI
275
+
276
+ Returns:
277
+ (path, query_string) 元组
278
+ """
279
+ if '?' in uri:
280
+ parts = uri.split('?', 1)
281
+ return parts[0], parts[1]
282
+ return uri, None
283
+
284
+ @staticmethod
285
+ def _extract_log_metadata(log_data: Dict[str, Any]) -> Optional[Dict[str, Any]]:
286
+ """
287
+ 提取额外的元数据
288
+
289
+ Args:
290
+ log_data: 日志数据字典
291
+
292
+ Returns:
293
+ 元数据字典或 None
294
+ """
295
+ log_metadata = {}
296
+
297
+ # 提取自定义字段
298
+ custom_fields = ["user_id", "session_id", "trace_id", "span_id"]
299
+ for field in custom_fields:
300
+ if field in log_data:
301
+ log_metadata[field] = log_data[field]
302
+
303
+ return log_metadata if log_metadata else None
304
+
305
+
306
+ # 全局实例
307
+ access_log_parser = AccessLogParser()