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,118 @@
1
+ """Domain logic for delegating schema management to the dbadmin CLI."""
2
+ import json
3
+ import subprocess
4
+ from typing import (
5
+ Any,
6
+ Dict,
7
+ List,
8
+ Optional,
9
+ Sequence,
10
+ )
11
+
12
+ from linglong_web.utils import logger
13
+
14
+
15
+ class DatabaseAdminDomain:
16
+ """Execute dbadmin CLI commands inside the target service container.
17
+
18
+ 诚实声明 / Honesty note:
19
+ 本类不自带 schema 管理实现,而是通过 `docker-compose exec ... python src/tools/dbadmin/manage.py`
20
+ 外壳调用一个**未随本包分发**的外部 dbadmin 工具。该脚本不在本仓库/本包内,只有目标容器镜像里存在
21
+ 时才可用。若目标容器没有该脚本,调用会失败——这是设计性的外部依赖,并非本包内已实现的能力。
22
+ This class shells out to an external dbadmin tool (src/tools/dbadmin/manage.py) that is NOT shipped
23
+ with this package; it only works when that script exists inside the target container image.
24
+ """
25
+
26
+ def __init__(
27
+ self,
28
+ *,
29
+ compose_file: str,
30
+ project_name: str,
31
+ target_service: str,
32
+ script_path: str,
33
+ python_executable: str = "python",
34
+ python_path: str = "/app/src:/app:/app/cmd:/app/tools",
35
+ ) -> None:
36
+ self.compose_file = compose_file
37
+ self.project_name = project_name
38
+ self.target_service = target_service
39
+ self.script_path = script_path
40
+ self.python_executable = python_executable
41
+ self.python_path = python_path
42
+ self.base_compose_cmd = [
43
+ "docker-compose",
44
+ "-f",
45
+ compose_file,
46
+ "-p",
47
+ project_name,
48
+ ]
49
+
50
+ def ensure_schema(self, *, databases: Optional[Sequence[str]], tables: Optional[Sequence[str]], dry_run: bool) -> \
51
+ Dict[str, Any]:
52
+ args = ["apply"]
53
+ if databases:
54
+ args.append("--databases")
55
+ args.extend(databases)
56
+ if tables:
57
+ args.append("--tables")
58
+ args.extend(tables)
59
+ if dry_run:
60
+ args.append("--dry-run")
61
+ return self._run_dbadmin(args)
62
+
63
+ def diff_schema(self, *, databases: Optional[Sequence[str]], tables: Optional[Sequence[str]]) -> Dict[str, Any]:
64
+ args = ["diff"]
65
+ if databases:
66
+ args.append("--databases")
67
+ args.extend(databases)
68
+ if tables:
69
+ args.append("--tables")
70
+ args.extend(tables)
71
+ return self._run_dbadmin(args)
72
+
73
+ def rebuild_database(self, database: str) -> Dict[str, Any]:
74
+ return self._run_dbadmin(["rebuild-db", database])
75
+
76
+ def rebuild_tables(self, database: str, tables: Sequence[str], cascade: bool) -> Dict[str, Any]:
77
+ args = ["rebuild-table", database]
78
+ args.extend(tables)
79
+ if not cascade:
80
+ args.append("--no-cascade")
81
+ return self._run_dbadmin(args)
82
+
83
+ def _run_dbadmin(self, additional_args: List[str]) -> Dict[str, Any]:
84
+ cmd = self.base_compose_cmd + [
85
+ "exec",
86
+ "-T",
87
+ self.target_service,
88
+ "env",
89
+ f"PYTHONPATH={self.python_path}",
90
+ self.python_executable,
91
+ self.script_path,
92
+ "--output",
93
+ "json",
94
+ ]
95
+ cmd.extend(additional_args)
96
+
97
+ logger.info("Executing dbadmin command: %s", " ".join(cmd))
98
+ result = subprocess.run(cmd, capture_output=True, text=True)
99
+
100
+ if result.returncode != 0:
101
+ stderr = result.stderr.strip()
102
+ stdout = result.stdout.strip()
103
+ message = stderr or stdout or "dbadmin command failed"
104
+ logger.error("dbadmin command failed: %s", message)
105
+ raise RuntimeError(message)
106
+
107
+ payload_text = result.stdout.strip() or result.stderr.strip()
108
+ if not payload_text:
109
+ logger.error("dbadmin command returned empty output")
110
+ raise RuntimeError("dbadmin command returned empty output")
111
+
112
+ try:
113
+ payload = json.loads(payload_text)
114
+ except json.JSONDecodeError as exc:
115
+ logger.error("Unable to parse dbadmin output: %s", payload_text)
116
+ raise RuntimeError("dbadmin command produced invalid JSON") from exc
117
+
118
+ return payload
@@ -0,0 +1,3 @@
1
+ """
2
+ db_init 领域模块
3
+ """
@@ -0,0 +1,358 @@
1
+ """
2
+ 数据库初始化领域层
3
+ 负责数据库和表的创建、检查等核心业务逻辑
4
+ """
5
+ from pathlib import Path
6
+ from typing import (
7
+ List,
8
+ Optional,
9
+ Set,
10
+ Tuple,
11
+ )
12
+
13
+ from sqlalchemy import text
14
+ from sqlalchemy.ext.asyncio import AsyncConnection
15
+ from sqlalchemy.ext.asyncio import create_async_engine
16
+ from sqlalchemy.pool import NullPool
17
+
18
+ from linglong_web.utils import logger
19
+ from linglong_web import Rmanager
20
+ from linglong_web import LinglongConfig
21
+
22
+ from cancan_microstack.runtime.resources import resolve_workspace_or_asset
23
+
24
+
25
+ class DatabaseInitDomain:
26
+ """数据库初始化领域服务"""
27
+
28
+ # 数据库和对应的 DDL 目录映射
29
+ DB_DDL_MAPPING = {
30
+ "infra": "infra",
31
+ "ops": "ops",
32
+ "biz": "biz",
33
+ }
34
+
35
+ def __init__(self, ddl_root_path: str = None):
36
+ """
37
+ 初始化
38
+
39
+ Args:
40
+ ddl_root_path: DDL 文件根目录,默认为项目根目录/ddl
41
+ """
42
+ if ddl_root_path is None:
43
+ ddl_root = resolve_workspace_or_asset("ddl", "ddl")
44
+ else:
45
+ ddl_root = Path(ddl_root_path)
46
+
47
+ self.ddl_root = ddl_root
48
+ logger.info(f"DatabaseInitDomain initialized with DDL path: {self.ddl_root}")
49
+
50
+ async def check_database_exists(self, database_name: str, conn: AsyncConnection) -> bool:
51
+ """
52
+ 检查数据库是否存在
53
+
54
+ Args:
55
+ database_name: 数据库名称
56
+ conn: 数据库连接
57
+
58
+ Returns:
59
+ 数据库是否存在
60
+ """
61
+ query = text("SELECT 1 FROM pg_database WHERE datname = :dbname")
62
+ result = await conn.execute(query, {"dbname": database_name})
63
+ return result.scalar() is not None
64
+
65
+ async def create_database(self, database_name: str, conn: AsyncConnection) -> bool:
66
+ """
67
+ 创建数据库
68
+
69
+ Args:
70
+ database_name: 数据库名称
71
+ conn: 数据库连接(必须是 postgres 或其他存在的数据库)
72
+
73
+ Returns:
74
+ 是否成功创建
75
+ """
76
+ try:
77
+ # 必须在自动提交模式下创建数据库
78
+ await conn.execute(text("COMMIT"))
79
+ await conn.execute(text(f"CREATE DATABASE {database_name}"))
80
+ logger.info(f"Database '{database_name}' created successfully")
81
+ return True
82
+ except Exception as e:
83
+ logger.error(f"Failed to create database '{database_name}': {e}")
84
+ return False
85
+
86
+ async def get_existing_tables(self, database_name: str) -> Set[str]:
87
+ """
88
+ 获取数据库中已存在的表
89
+
90
+ Args:
91
+ database_name: 数据库名称
92
+
93
+ Returns:
94
+ 表名集合
95
+ """
96
+ try:
97
+ # 尝试使用指定数据库的引擎,如果没有则创建临时连接
98
+ engine = Rmanager.get_pgsql_engine(database_name)
99
+ if engine is None:
100
+ # 没有预注册的引擎,需要临时连接
101
+ # 临时引擎必须避免连接池残留,否则高频调用会推高 Postgres 连接数。
102
+ # Temporary engine must avoid pooled connections; otherwise frequent calls can exhaust Postgres.
103
+ temp_engine = create_async_engine(
104
+ f"postgresql+asyncpg://{LinglongConfig.PGSQL_USER}:{LinglongConfig.PGSQL_PASSWORD}@{LinglongConfig.PGSQL_HOST}:{LinglongConfig.PGSQL_PORT}/{database_name}",
105
+ poolclass=NullPool,
106
+ pool_pre_ping=True,
107
+ )
108
+
109
+ try:
110
+ async with temp_engine.begin() as conn:
111
+ query = text("""
112
+ SELECT tablename
113
+ FROM pg_tables
114
+ WHERE schemaname = 'public'
115
+ """)
116
+ result = await conn.execute(query)
117
+ tables = {row[0] for row in result}
118
+ finally:
119
+ await temp_engine.dispose()
120
+
121
+ return tables
122
+
123
+ async with engine.begin() as conn:
124
+ query = text("""
125
+ SELECT tablename
126
+ FROM pg_tables
127
+ WHERE schemaname = 'public'
128
+ """)
129
+ result = await conn.execute(query)
130
+ return {row[0] for row in result}
131
+ except Exception as e:
132
+ logger.error(f"Failed to get tables for database '{database_name}': {e}")
133
+ return set()
134
+
135
+ def get_sql_files_for_database(self, database_name: str) -> List[Tuple[str, str]]:
136
+ """
137
+ 获取数据库对应的 SQL 文件列表
138
+
139
+ Args:
140
+ database_name: 数据库名称
141
+
142
+ Returns:
143
+ (表名, SQL文件路径) 的列表
144
+ """
145
+ ddl_dir = self.DB_DDL_MAPPING.get(database_name)
146
+ if not ddl_dir:
147
+ logger.warning(f"No DDL directory mapping for database '{database_name}'")
148
+ return []
149
+
150
+ sql_dir = self.ddl_root / ddl_dir
151
+ if not sql_dir.exists():
152
+ logger.warning(f"DDL directory not found: {sql_dir}")
153
+ return []
154
+
155
+ sql_files = []
156
+ for sql_file in sorted(sql_dir.glob("*.sql")):
157
+ # 表名就是文件名(去掉 .sql 后缀)
158
+ table_name = sql_file.stem
159
+ sql_files.append((table_name, str(sql_file)))
160
+
161
+ return sql_files
162
+
163
+ async def execute_sql_file(self, sql_file_path: str, database_name: str) -> bool:
164
+ """
165
+ 执行 SQL 文件(支持多条语句)
166
+
167
+ Args:
168
+ sql_file_path: SQL 文件路径
169
+ database_name: 目标数据库名称
170
+
171
+ Returns:
172
+ 是否成功执行
173
+ """
174
+ try:
175
+ # 读取 SQL 文件
176
+ with open(sql_file_path, 'r', encoding='utf-8') as f:
177
+ sql_content = f.read()
178
+
179
+ # 拆分 SQL 语句(按分号分隔,忽略注释中的分号)
180
+ statements = self._split_sql_statements(sql_content)
181
+
182
+ # 尝试使用指定数据库的引擎,如果没有则创建临时连接
183
+ engine = Rmanager.get_pgsql_engine(database_name)
184
+ if engine is None:
185
+ # 没有预注册的引擎,需要临时连接
186
+ # 临时引擎必须避免连接池残留,否则高频调用会推高 Postgres 连接数。
187
+ # Temporary engine must avoid pooled connections; otherwise frequent calls can exhaust Postgres.
188
+ temp_engine = create_async_engine(
189
+ f"postgresql+asyncpg://{LinglongConfig.PGSQL_USER}:{LinglongConfig.PGSQL_PASSWORD}@{LinglongConfig.PGSQL_HOST}:{LinglongConfig.PGSQL_PORT}/{database_name}",
190
+ poolclass=NullPool,
191
+ pool_pre_ping=True,
192
+ )
193
+
194
+ try:
195
+ async with temp_engine.begin() as conn:
196
+ # 逐条执行 SQL 语句
197
+ for stmt in statements:
198
+ if stmt.strip(): # 跳过空语句
199
+ await conn.execute(text(stmt))
200
+ finally:
201
+ await temp_engine.dispose()
202
+ else:
203
+ async with engine.begin() as conn:
204
+ # 逐条执行 SQL 语句
205
+ for stmt in statements:
206
+ if stmt.strip(): # 跳过空语句
207
+ await conn.execute(text(stmt))
208
+
209
+ logger.info(f"Executed SQL file: {sql_file_path} ({len(statements)} statements)")
210
+ return True
211
+
212
+ except Exception as e:
213
+ logger.error(f"Failed to execute SQL file '{sql_file_path}': {e}", exc_info=True)
214
+ return False
215
+
216
+ def _split_sql_statements(self, sql_content: str) -> List[str]:
217
+ """
218
+ 拆分 SQL 内容为多条语句
219
+
220
+ 处理规则:
221
+ 1. 按分号分隔
222
+ 2. 忽略 -- 注释
223
+ 3. 处理 $$ dollar-quoted 字符串(不拆分其中的分号)
224
+ 4. 处理 'string' 单引号字符串
225
+
226
+ Args:
227
+ sql_content: SQL 文件内容
228
+
229
+ Returns:
230
+ SQL 语句列表
231
+ """
232
+ statements = []
233
+ current_statement = []
234
+ in_dollar_quote = False
235
+ in_single_quote = False
236
+
237
+ for line in sql_content.split('\n'):
238
+ # 跳过纯注释行
239
+ stripped_line = line.strip()
240
+ if stripped_line.startswith('--'):
241
+ continue
242
+
243
+ # 检查 dollar-quoted 字符串状态
244
+ # 简单处理:如果行中包含 $$,切换状态
245
+ dollar_count = line.count('$$')
246
+ if dollar_count % 2 == 1: # 奇数个 $$ 表示状态切换
247
+ in_dollar_quote = not in_dollar_quote
248
+
249
+ # 在 dollar-quoted 字符串内部,不检查分号
250
+ if in_dollar_quote:
251
+ current_statement.append(line)
252
+ continue
253
+
254
+ # 移除行尾注释(不在字符串内的注释)
255
+ # 简化处理:如果不在引号内,可以移除注释
256
+ line_without_comment = line.split('--')[0] if '--' in line else line
257
+
258
+ # 检查是否包含分号(语句结束符)
259
+ if ';' in line_without_comment:
260
+ # 分号前的内容加入当前语句
261
+ parts = line_without_comment.split(';')
262
+ current_statement.append(parts[0])
263
+
264
+ # 完成当前语句
265
+ stmt = '\n'.join(current_statement).strip()
266
+ if stmt and stmt not in ('BEGIN', 'COMMIT'): # 跳过 BEGIN/COMMIT
267
+ statements.append(stmt)
268
+
269
+ # 重置当前语句
270
+ current_statement = []
271
+
272
+ # 如果分号后还有内容,作为新语句的开始
273
+ if parts[-1].strip():
274
+ current_statement.append(parts[-1])
275
+ else:
276
+ # 没有分号,继续累积
277
+ current_statement.append(line)
278
+
279
+ # 处理最后可能未结束的语句
280
+ if current_statement:
281
+ stmt = '\n'.join(current_statement).strip()
282
+ if stmt and stmt not in ('BEGIN', 'COMMIT'):
283
+ statements.append(stmt)
284
+
285
+ return statements
286
+
287
+ async def ensure_triggers_exist(self, database_name: str) -> bool:
288
+ """
289
+ 确保数据库中存在必要的触发器函数
290
+
291
+ Args:
292
+ database_name: 数据库名称
293
+
294
+ Returns:
295
+ 是否成功
296
+ """
297
+ trigger_file = self.ddl_root / "trigger.sql"
298
+ if not trigger_file.exists():
299
+ logger.warning(f"Trigger file not found: {trigger_file}")
300
+ return True # 文件不存在也不算失败,可能不需要触发器
301
+
302
+ logger.info(f"Ensuring triggers exist in '{database_name}'...")
303
+ return await self.execute_sql_file(str(trigger_file), database_name)
304
+
305
+ async def create_tables_incremental(
306
+ self,
307
+ database_name: str,
308
+ target_tables: Optional[List[str]] = None
309
+ ) -> Tuple[List[str], List[str]]:
310
+ """
311
+ 增量创建表(只创建不存在的表)
312
+
313
+ Args:
314
+ database_name: 数据库名称
315
+ target_tables: 目标表列表,None 表示全部
316
+
317
+ Returns:
318
+ (成功创建的表列表, 失败的表列表)
319
+ """
320
+ # 首先确保触发器函数存在
321
+ await self.ensure_triggers_exist(database_name)
322
+
323
+ # 获取已存在的表
324
+ existing_tables = await self.get_existing_tables(database_name)
325
+
326
+ # 获取 SQL 文件列表
327
+ sql_files = self.get_sql_files_for_database(database_name)
328
+
329
+ created_tables = []
330
+ failed_tables = []
331
+
332
+ for table_name, sql_file in sql_files:
333
+ # 如果指定了目标表,只处理目标表
334
+ if target_tables and table_name not in target_tables:
335
+ continue
336
+
337
+ # 如果表已存在,跳过
338
+ if table_name in existing_tables:
339
+ logger.info(f"Table '{table_name}' already exists in '{database_name}', skipping")
340
+ continue
341
+
342
+ # 创建表
343
+ logger.info(f"Creating table '{table_name}' in '{database_name}'...")
344
+ if await self.execute_sql_file(sql_file, database_name):
345
+ created_tables.append(table_name)
346
+ else:
347
+ failed_tables.append(table_name)
348
+
349
+ return created_tables, failed_tables
350
+
351
+ def get_all_databases(self) -> List[str]:
352
+ """
353
+ 获取所有配置的数据库列表
354
+
355
+ Returns:
356
+ 数据库名称列表
357
+ """
358
+ return list(self.DB_DDL_MAPPING.keys())
@@ -0,0 +1 @@
1
+ """opsbffsrv logging domain package."""
@@ -0,0 +1,99 @@
1
+ """日志查询领域服务 / Log query domain service."""
2
+ import re
3
+ from datetime import timedelta
4
+ from typing import (
5
+ Any,
6
+ Dict,
7
+ List,
8
+ )
9
+
10
+ from cancan_microstack.public.schemas.logging.log_event import (
11
+ LogQueryRequest,
12
+ LogQueryResponse,
13
+ )
14
+ from linglong_web.utils import logger
15
+
16
+ from cancan_microstack.services.opsbffsrv.infrastructure.mongo.log_query_repository import LogQueryRepository
17
+
18
+
19
+ class LogQueryDomain:
20
+ """实现日志查询业务规则 / Implements log query business rules."""
21
+
22
+ def __init__(self, repository: LogQueryRepository) -> None:
23
+ self._repository = repository
24
+
25
+ async def search_logs(self, request: LogQueryRequest, max_range_days: int) -> LogQueryResponse:
26
+ self._validate_range(request, max_range_days)
27
+ filters = self._build_filters(request)
28
+ skip = (request.page - 1) * request.page_size
29
+ events, total = await self._repository.query_logs(filters, skip, request.page_size)
30
+ has_next = (skip + len(events)) < total
31
+ logger.debug(
32
+ "Log query completed: filters=%s total=%s page=%s page_size=%s", filters, total, request.page,
33
+ request.page_size
34
+ )
35
+ return LogQueryResponse(
36
+ items=events,
37
+ total=total,
38
+ page=request.page,
39
+ page_size=request.page_size,
40
+ has_next=has_next,
41
+ )
42
+
43
+ def _validate_range(self, request: LogQueryRequest, max_range_days: int) -> None:
44
+ max_delta = timedelta(days=max_range_days)
45
+ actual_range = request.end_time - request.start_time
46
+ if actual_range > max_delta:
47
+ raise ValueError(f"Time range exceeds {max_range_days} days")
48
+
49
+ @staticmethod
50
+ def _clean_values(values: List[str] | None) -> List[str]:
51
+ """清理输入字符串列表,移除空值并去重
52
+ Clean string list inputs by trimming, dropping empty items, and de-duplicating
53
+ """
54
+ if not values:
55
+ return []
56
+
57
+ result: List[str] = []
58
+ for value in values:
59
+ normalized = str(value or "").strip()
60
+ if not normalized:
61
+ continue
62
+ if normalized not in result:
63
+ result.append(normalized)
64
+ return result
65
+
66
+ def _build_filters(self, request: LogQueryRequest) -> Dict[str, Any]:
67
+ cleaned_service_names = self._clean_values(request.service_names)
68
+ cleaned_levels = [level.value for level in request.levels] if request.levels else []
69
+ cleaned_method_names = self._clean_values(request.method_names)
70
+ cleaned_ip_addresses = self._clean_values(request.ip_addresses)
71
+ cleaned_instance_ids = self._clean_values(request.instance_ids)
72
+ cleaned_keywords = self._clean_values(request.keywords)
73
+
74
+ filters: Dict[str, Any] = {
75
+ "service_name": {"$in": cleaned_service_names},
76
+ "timestamp": {"$gte": request.start_time, "$lte": request.end_time},
77
+ }
78
+ if cleaned_levels:
79
+ filters["level"] = {"$in": cleaned_levels}
80
+ if cleaned_method_names:
81
+ filters["func_name"] = {"$in": cleaned_method_names}
82
+ if cleaned_ip_addresses:
83
+ filters["ip"] = {"$in": cleaned_ip_addresses}
84
+ if cleaned_instance_ids:
85
+ filters["instance_id"] = {"$in": cleaned_instance_ids}
86
+ if cleaned_keywords:
87
+ # 同时搜索 message/trace/event 以及 metadata 中常见 reqid 字段
88
+ # Search message/trace/event and common reqid fields in metadata
89
+ keyword_pattern = "|".join(re.escape(keyword) for keyword in cleaned_keywords)
90
+ filters["$or"] = [
91
+ {"message": {"$regex": keyword_pattern, "$options": "i"}},
92
+ {"trace_id": {"$regex": keyword_pattern, "$options": "i"}},
93
+ {"event_id": {"$regex": keyword_pattern, "$options": "i"}},
94
+ {"metadata_flattened": {"$regex": keyword_pattern, "$options": "i"}},
95
+ {"metadata.oid": {"$regex": keyword_pattern, "$options": "i"}},
96
+ {"metadata.reqid": {"$regex": keyword_pattern, "$options": "i"}},
97
+ {"metadata.trace_id": {"$regex": keyword_pattern, "$options": "i"}},
98
+ ]
99
+ return filters
@@ -0,0 +1,81 @@
1
+ """
2
+ 服务配置管理领域层
3
+ 负责处理ops前端对配置的管理操作
4
+ """
5
+ from typing import Dict
6
+
7
+ from linglong_web.utils import logger
8
+ from cancan_microstack.public.schemas.infra.service_config import ServiceConfig
9
+ from cancan_microstack.services.opsbffsrv.infrastructure.db.operate.service_config import (
10
+ insert_service_config,
11
+ get_service_config,
12
+ update_service_config,
13
+ get_all_service_configs,
14
+ delete_service_config,
15
+ )
16
+
17
+
18
+ class ServiceConfigDomain:
19
+ """服务配置管理域"""
20
+
21
+ async def get_service_config(self, service_name: str) -> Dict[str, str]:
22
+ """获取服务配置"""
23
+ configs = await get_service_config(service_name)
24
+ if not configs:
25
+ return {}
26
+
27
+ config_dict = {c.conf_key: c.conf_value for c in configs}
28
+ logger.info(f"Retrieved config for service {service_name}: {len(config_dict)} items")
29
+ return config_dict
30
+
31
+ async def insert_service_config(self, service_name: str, conf_dict: Dict[str, str]) -> None:
32
+ """插入服务配置"""
33
+ logger.info(f"Inserting config for service {service_name}: {list(conf_dict.keys())}")
34
+
35
+ configs = [
36
+ ServiceConfig(
37
+ service_name=service_name,
38
+ conf_key=key,
39
+ conf_value=value
40
+ )
41
+ for key, value in conf_dict.items()
42
+ ]
43
+
44
+ await insert_service_config(configs)
45
+ logger.info(f"Successfully inserted {len(configs)} config items for service {service_name}")
46
+
47
+ async def update_service_config(self, service_name: str, conf_dict: Dict[str, str]) -> None:
48
+ """更新服务配置"""
49
+ logger.info(f"Updating config for service {service_name}: {list(conf_dict.keys())}")
50
+
51
+ configs = [
52
+ ServiceConfig(
53
+ service_name=service_name,
54
+ conf_key=key,
55
+ conf_value=value
56
+ )
57
+ for key, value in conf_dict.items()
58
+ ]
59
+
60
+ await update_service_config(configs)
61
+ logger.info(f"Successfully updated {len(configs)} config items for service {service_name}")
62
+
63
+ async def get_all_service_configs(self) -> Dict[str, Dict[str, str]]:
64
+ """获取所有服务的配置"""
65
+ configs = await get_all_service_configs()
66
+
67
+ # 按服务名分组
68
+ service_configs: Dict[str, Dict[str, str]] = {}
69
+ for config in configs:
70
+ if config.service_name not in service_configs:
71
+ service_configs[config.service_name] = {}
72
+ service_configs[config.service_name][config.conf_key] = config.conf_value
73
+
74
+ logger.info(f"Retrieved configs for {len(service_configs)} services")
75
+ return service_configs
76
+
77
+ async def delete_service_config(self, service_name: str, conf_key: str) -> None:
78
+ """删除服务配置项"""
79
+ logger.info(f"Deleting config for service {service_name}, key: {conf_key}")
80
+ await delete_service_config(service_name, conf_key)
81
+ logger.info(f"Successfully deleted config item {conf_key} for service {service_name}")