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,56 @@
1
+ """Service runner utilities for controllersrv.
2
+
3
+ 在启动服务前自动完成 workspace & overrides bootstrap,再按入口点动态加载。
4
+ Run bundled services after bootstrapping workspace/overrides and resolving entrypoints.
5
+ """
6
+ import asyncio
7
+ import inspect
8
+ from importlib import import_module
9
+ from pathlib import Path
10
+ from typing import Dict
11
+
12
+ from cancan_microstack.runtime.overrides import bootstrap_from_workspace
13
+
14
+
15
+ class ServiceRunner:
16
+ """加载并执行内置服务入口点 / Load and execute bundled service entrypoints."""
17
+
18
+ _ENTRYPOINTS: Dict[str, str] = {
19
+ "controllersrv": "cancan_microstack.cmd.controllersrv.run:main",
20
+ "infrasrv": "cancan_microstack.cmd.infrasrv.run:main",
21
+ "opsbffsrv": "cancan_microstack.cmd.opsbffsrv.run:main",
22
+ }
23
+
24
+ def run(
25
+ self,
26
+ service_name: str,
27
+ *,
28
+ host: str = "0.0.0.0",
29
+ port: int = 8080,
30
+ workspace: str | Path | None = None,
31
+ ) -> None:
32
+ asyncio.run(self.run_async(service_name, host=host, port=port, workspace=workspace))
33
+
34
+ async def run_async(
35
+ self,
36
+ service_name: str,
37
+ *,
38
+ host: str = "0.0.0.0",
39
+ port: int = 8080,
40
+ workspace: str | Path | None = None,
41
+ ) -> None:
42
+ workspace_path = Path(workspace).expanduser().resolve() if workspace else None
43
+ bootstrap_from_workspace(workspace_path)
44
+ entry = self._ENTRYPOINTS.get(service_name)
45
+ if not entry:
46
+ raise ValueError(f"Unknown service '{service_name}'")
47
+ module_name, func_name = entry.split(":")
48
+ module = import_module(module_name)
49
+ func = getattr(module, func_name)
50
+ result = func(host=host, port=port)
51
+ if inspect.isawaitable(result):
52
+ await result
53
+ elif callable(result): # pragma: no cover - defensive
54
+ maybe = result()
55
+ if inspect.isawaitable(maybe):
56
+ await maybe
@@ -0,0 +1,186 @@
1
+ """Stack lifecycle manager.
2
+
3
+ 提供“整栈 up/down/status”的统一入口:
4
+ - controllersrv 在宿主机后台运行(daemon + pidfile)
5
+ - 其他服务通过 docker/podman compose 运行
6
+
7
+ Provide a unified stack lifecycle entry:
8
+ - controllersrv runs on host as a background daemon (pidfile-managed)
9
+ - other services run via docker/podman compose
10
+ """
11
+ import time
12
+ import urllib.request
13
+ import sys
14
+ from dataclasses import dataclass
15
+ from pathlib import Path
16
+ from typing import Sequence
17
+
18
+ from ..runtime.compose_cmd import run_compose_streaming
19
+ from ..runtime.host_daemon import default_daemon_paths
20
+ from ..runtime.host_daemon import start_daemon
21
+ from ..runtime.host_daemon import stop_daemon
22
+ from .microstack import CancanMicrostack
23
+
24
+
25
+ @dataclass(frozen=True)
26
+ class StackOptions:
27
+ """整栈运行参数 / Stack runtime options."""
28
+
29
+ workspace: Path
30
+ service_file: Path | None
31
+ overrides: Sequence[Path]
32
+ output: Path | None
33
+ bootstrap: bool
34
+ engine: str | None
35
+
36
+ controllersrv_host: str
37
+ controllersrv_port: int
38
+ with_controllersrv: bool
39
+
40
+
41
+ class StackManager:
42
+ """整栈生命周期管理 / Stack lifecycle manager."""
43
+
44
+ def get_controllersrv_daemon_paths(self, workspace: Path):
45
+ """Get default daemon paths for controllersrv.
46
+
47
+ 获取 controllersrv 的默认 daemon 路径。
48
+ """
49
+
50
+ return default_daemon_paths(workspace, name="controllersrv")
51
+
52
+ def __init__(self, stack: CancanMicrostack | None = None) -> None:
53
+ self._stack = stack or CancanMicrostack()
54
+
55
+ def build(self, options: StackOptions) -> Path:
56
+ """生成 compose 文件 / Build compose file."""
57
+
58
+ if options.bootstrap:
59
+ # CLI 的 bootstrap 逻辑目前在 cli/main.py 中。
60
+ # Here we only build compose; bootstrap happens in CLI layer.
61
+ pass
62
+
63
+ return self._stack.build_compose(
64
+ workspace=options.workspace,
65
+ service_file=options.service_file,
66
+ overrides=options.overrides,
67
+ output=options.output,
68
+ )
69
+
70
+ def start_controllersrv(self, options: StackOptions) -> int:
71
+ """后台启动 controllersrv / Start controllersrv as host daemon."""
72
+
73
+ paths = default_daemon_paths(options.workspace, name="controllersrv")
74
+
75
+ argv = [
76
+ sys.executable,
77
+ "-m",
78
+ "cancan_microstack.cli",
79
+ "services",
80
+ "run",
81
+ "controllersrv",
82
+ "--host",
83
+ options.controllersrv_host,
84
+ "--port",
85
+ str(options.controllersrv_port),
86
+ "--workspace",
87
+ str(options.workspace),
88
+ ]
89
+
90
+ env = {}
91
+ if options.engine:
92
+ # Propagate engine preference into controllersrv (Dragonfly auto-detect is Docker-first).
93
+ # 将引擎偏好传给 controllersrv(Dragonfly 的 auto-detect 是 Docker-first)。
94
+ env["CANCAN_CONTAINER_ENGINE"] = options.engine
95
+
96
+ return start_daemon(argv=argv, workspace=options.workspace, paths=paths, env=env)
97
+
98
+ def wait_controllersrv_ready(
99
+ self,
100
+ *,
101
+ host: str,
102
+ port: int,
103
+ timeout_seconds: float = 8.0,
104
+ ) -> bool:
105
+ """Wait until controllersrv internal health is reachable.
106
+
107
+ 等待 controllersrv 的 /internal/health 可访问。
108
+ """
109
+
110
+ url = f"http://{host}:{port}/internal/health"
111
+ deadline = time.time() + timeout_seconds
112
+ last_error: Exception | None = None
113
+ while time.time() < deadline:
114
+ try:
115
+ with urllib.request.urlopen(url, timeout=1.0) as resp:
116
+ if 200 <= resp.status < 300:
117
+ return True
118
+ except Exception as exc:
119
+ last_error = exc
120
+ time.sleep(0.2)
121
+
122
+ _ = last_error
123
+ return False
124
+
125
+ def stop_controllersrv(self, workspace: Path) -> bool:
126
+ """停止 controllersrv daemon / Stop controllersrv daemon."""
127
+
128
+ paths = default_daemon_paths(workspace, name="controllersrv")
129
+ return stop_daemon(paths=paths)
130
+
131
+ def compose_up(
132
+ self,
133
+ *,
134
+ workspace: Path,
135
+ compose_file: Path,
136
+ engine: str | None = None,
137
+ build: bool = False,
138
+ ) -> None:
139
+ """启动容器栈 / Bring up container stack."""
140
+
141
+ log_file = workspace / "server_log_data" / "stack" / "compose.up.log"
142
+ args = ["up", "-d"]
143
+ if build:
144
+ args.append("--build")
145
+ run_compose_streaming(
146
+ compose_file=compose_file,
147
+ args=args,
148
+ workspace=workspace,
149
+ engine=engine,
150
+ log_file=log_file,
151
+ )
152
+
153
+ def compose_down(
154
+ self,
155
+ *,
156
+ workspace: Path,
157
+ compose_file: Path,
158
+ engine: str | None = None,
159
+ remove_volumes: bool = False,
160
+ ) -> None:
161
+ """关闭容器栈 / Bring down container stack."""
162
+
163
+ args = ["down"]
164
+ if remove_volumes:
165
+ args.append("--volumes")
166
+
167
+ log_file = workspace / "server_log_data" / "stack" / "compose.down.log"
168
+ run_compose_streaming(
169
+ compose_file=compose_file,
170
+ args=args,
171
+ workspace=workspace,
172
+ engine=engine,
173
+ log_file=log_file,
174
+ )
175
+
176
+ def compose_ps(self, *, workspace: Path, compose_file: Path, engine: str | None = None) -> None:
177
+ """查看 compose 状态 / Show compose status."""
178
+
179
+ log_file = workspace / "server_log_data" / "stack" / "compose.ps.log"
180
+ run_compose_streaming(
181
+ compose_file=compose_file,
182
+ args=["ps"],
183
+ workspace=workspace,
184
+ engine=engine,
185
+ log_file=log_file,
186
+ )
@@ -0,0 +1,7 @@
1
+ """Cancan Microstack public helpers.
2
+
3
+ 该包封装了 const/logging/web/schema 等公共能力,供 controllersrv / infrasrv /
4
+ opsbffsrv 以及业务服务共享使用。
5
+ This package bundles shared public modules (const, logging, web, schemas) for
6
+ controllersrv / infrasrv / opsbffsrv and any business service consuming Cancan.
7
+ """
@@ -0,0 +1 @@
1
+ """Core API clients for Cancan Microstack services."""
@@ -0,0 +1,277 @@
1
+ """
2
+ controllersrv API 客户端 / controllersrv API client
3
+ """
4
+ import http
5
+ from typing import (
6
+ Any,
7
+ Dict,
8
+ List,
9
+ Optional,
10
+ Sequence,
11
+ Tuple,
12
+ Type,
13
+ Union,
14
+ cast,
15
+ )
16
+
17
+ from pydantic import (
18
+ BaseModel,
19
+ ValidationError,
20
+ )
21
+
22
+ from linglong_web.utils import logger
23
+ from linglong_web import (
24
+ http_client,
25
+ HTTPClientConfig,
26
+ )
27
+ from cancan_microstack.public.schemas.common import (
28
+ APIError,
29
+ APIResponse,
30
+ )
31
+ from cancan_microstack.public.schemas.controllersrv.responses import (
32
+ EnqueueSuccessResponse,
33
+ EnqueueErrorResponse,
34
+ TaskListResponse,
35
+ TaskStatusResponse,
36
+ )
37
+ from cancan_microstack.public.schemas.controllersrv.validation import ValidationResult
38
+
39
+ ServiceOperationResponse = Union[
40
+ EnqueueSuccessResponse,
41
+ EnqueueErrorResponse,
42
+ ValidationResult,
43
+ ]
44
+
45
+
46
+ class ControllerSrvApiClient:
47
+ """
48
+ 用于与 controllersrv 通信的基础客户端 / TableBase client for communicating with controllersrv
49
+
50
+ 提供通用的 HTTP 调用与响应解析逻辑,具体业务端可在子类中扩展
51
+ Provides generic HTTP invocation and response parsing logic for subclasses to extend
52
+ """
53
+
54
+ SERVICE_OPERATION_MODELS: Tuple[Type[BaseModel], ...] = (
55
+ EnqueueSuccessResponse,
56
+ EnqueueErrorResponse,
57
+ ValidationResult,
58
+ )
59
+ TASK_STATUS_MODELS: Tuple[Type[BaseModel], ...] = (TaskStatusResponse,)
60
+ TASK_LIST_MODELS: Tuple[Type[BaseModel], ...] = (TaskListResponse,)
61
+
62
+ def __init__(self, base_url: str):
63
+ """
64
+ 初始化 API 客户端 / Initialise API client
65
+
66
+ Args:
67
+ base_url: controllersrv 的基础 URL / TableBase URL of controllersrv
68
+ """
69
+
70
+ self.base_url = base_url
71
+ logger.info(f"ControllerSrvApiClient initialized with base_url: {self.base_url}")
72
+
73
+ async def _make_request(
74
+ self,
75
+ method: http.HTTPMethod,
76
+ endpoint: str,
77
+ json_data: Optional[Dict[str, Any]] = None,
78
+ params: Optional[Dict[str, Any]] = None,
79
+ response_models: Sequence[Type[BaseModel]] = (),
80
+ ) -> APIResponse[Optional[BaseModel]]:
81
+ """
82
+ 通用请求方法 / Generic request executor
83
+
84
+ Args:
85
+ method: HTTP 方法枚举 / HTTP method enum
86
+ endpoint: API 路径 / API path
87
+ json_data: 请求体(POST 使用)/ Request payload for POST
88
+ params: 查询参数(GET 使用)/ Query parameters for GET
89
+ response_models: 可用于解析 data 字段的模型列表
90
+ Models used to deserialize the data payload
91
+ """
92
+
93
+ url = f"{self.base_url}{endpoint}"
94
+ try:
95
+ http_callable = getattr(http_client, method.value.lower())
96
+ response = await http_callable(
97
+ url=url,
98
+ params=params,
99
+ json=json_data,
100
+ timeout=HTTPClientConfig.INTERNAL_SERVICE_TIMEOUT,
101
+ )
102
+ except Exception as exc:
103
+ logger.error(f"Error calling controllersrv API [{endpoint}]: {exc}", exc_info=True)
104
+ return APIResponse(success=False, error=APIError(code="HTTP_EXCEPTION", msg=str(exc)))
105
+
106
+ if response is None:
107
+ logger.error(f"Failed to call controllersrv API [{endpoint}]: no response object")
108
+ return APIResponse(success=False, error=APIError(code="HTTP_NO_RESPONSE", msg="No response received"))
109
+
110
+ if response.status != 200:
111
+ error_message = f"HTTP error: {response.status}"
112
+ logger.error(f"controllersrv API [{endpoint}] returned non-200 status: {response.status}")
113
+ return APIResponse(success=False, error=APIError(code=str(response.status), msg=error_message))
114
+
115
+ try:
116
+ payload = await response.json()
117
+ except Exception as exc:
118
+ logger.error(f"Failed to parse controllersrv response JSON for [{endpoint}]: {exc}", exc_info=True)
119
+ return APIResponse(success=False, error=APIError(code="JSON_DECODE_ERROR", msg=str(exc)))
120
+
121
+ if not isinstance(payload, dict):
122
+ logger.error(f"Unexpected controllersrv response format for [{endpoint}]: {payload}")
123
+ return APIResponse(success=False, error=APIError(code="INVALID_PAYLOAD", msg="Response is not a dict"))
124
+
125
+ success = bool(payload.get("success"))
126
+ error_content = payload.get("error") or {}
127
+ api_error = self._create_api_error(error_content)
128
+ raw_data = payload.get("data")
129
+ parsed_data = self._parse_response_data(raw_data, response_models, endpoint)
130
+
131
+ if parsed_data is None and raw_data is not None and response_models:
132
+ logger.error(
133
+ "Failed to parse controllersrv response data for [%s]: %s",
134
+ endpoint,
135
+ raw_data,
136
+ )
137
+
138
+ logger.debug(
139
+ "controllersrv API [%s] completed: success=%s, code=%s",
140
+ endpoint,
141
+ success,
142
+ api_error.code,
143
+ )
144
+
145
+ return APIResponse(success=success, error=api_error, data=parsed_data)
146
+
147
+ @staticmethod
148
+ def _create_api_error(error_content: Any) -> APIError:
149
+ """构造 APIError 对象 / Build APIError object"""
150
+
151
+ if isinstance(error_content, dict):
152
+ code = str(error_content.get("code", "50000"))
153
+ msg = str(error_content.get("msg", ""))
154
+ else:
155
+ code = "50000"
156
+ msg = str(error_content) if error_content is not None else ""
157
+ return APIError(code=code, msg=msg)
158
+
159
+ def _parse_response_data(
160
+ self,
161
+ data: Any,
162
+ response_models: Sequence[Type[BaseModel]],
163
+ endpoint: str,
164
+ ) -> Optional[BaseModel]:
165
+ """
166
+ 将 data 字段反序列化为 Pydantic 模型 / Deserialize data payload into Pydantic model
167
+ """
168
+
169
+ if data is None or not response_models:
170
+ return None
171
+
172
+ if not isinstance(data, (dict, list)):
173
+ logger.error(f"controllersrv API [{endpoint}] returned non-serialisable data: {data}")
174
+ return None
175
+
176
+ for model in response_models:
177
+ try:
178
+ if isinstance(data, model):
179
+ return data
180
+ return model.model_validate(data)
181
+ except ValidationError:
182
+ continue
183
+
184
+ return None
185
+
186
+ async def restart_services(
187
+ self,
188
+ service_names: List[str],
189
+ serial_number: str,
190
+ ) -> APIResponse[Optional[ServiceOperationResponse]]:
191
+ """
192
+ 调用 controllersrv 重启服务 / Call controllersrv to restart services
193
+ """
194
+
195
+ payload = {"service_names": service_names, "serial_number": serial_number}
196
+ response = await self._make_request(
197
+ http.HTTPMethod.POST,
198
+ "/service/restart",
199
+ json_data=payload,
200
+ response_models=self.SERVICE_OPERATION_MODELS,
201
+ )
202
+ return cast(APIResponse[Optional[ServiceOperationResponse]], response)
203
+
204
+ async def start_services(
205
+ self,
206
+ service_names: List[str],
207
+ serial_number: str,
208
+ ) -> APIResponse[Optional[ServiceOperationResponse]]:
209
+ """
210
+ 调用 controllersrv 启动服务 / Call controllersrv to start services
211
+ """
212
+
213
+ payload = {"service_names": service_names, "serial_number": serial_number}
214
+ response = await self._make_request(
215
+ http.HTTPMethod.POST,
216
+ "/service/start",
217
+ json_data=payload,
218
+ response_models=self.SERVICE_OPERATION_MODELS,
219
+ )
220
+ return cast(APIResponse[Optional[ServiceOperationResponse]], response)
221
+
222
+ async def stop_services(
223
+ self,
224
+ service_names: List[str],
225
+ serial_number: str,
226
+ ) -> APIResponse[Optional[ServiceOperationResponse]]:
227
+ """
228
+ 调用 controllersrv 停止服务 / Call controllersrv to stop services
229
+ """
230
+ logger.info(f"Stopping services: {service_names} with serial number: {serial_number}")
231
+ payload = {"service_names": service_names, "serial_number": serial_number}
232
+ response = await self._make_request(
233
+ http.HTTPMethod.POST,
234
+ "/service/stop",
235
+ json_data=payload,
236
+ response_models=self.SERVICE_OPERATION_MODELS,
237
+ )
238
+ return cast(APIResponse[Optional[ServiceOperationResponse]], response)
239
+
240
+ async def get_operation_status(
241
+ self,
242
+ serial_number: str,
243
+ ) -> APIResponse[Optional[TaskStatusResponse]]:
244
+ """
245
+ 查询异步操作状态 / Query asynchronous operation status
246
+ """
247
+
248
+ response = await self._make_request(
249
+ http.HTTPMethod.GET,
250
+ "/task/status",
251
+ params={"serial_number": serial_number},
252
+ response_models=self.TASK_STATUS_MODELS,
253
+ )
254
+ return cast(APIResponse[Optional[TaskStatusResponse]], response)
255
+
256
+ async def list_operations(
257
+ self,
258
+ status: Optional[str] = None,
259
+ limit: int = 100,
260
+ ) -> APIResponse[Optional[TaskListResponse]]:
261
+ """
262
+ 列出异步操作 / List asynchronous operations
263
+ """
264
+
265
+ params: Dict[str, Any] = {}
266
+ if status:
267
+ params["status"] = status
268
+ if limit:
269
+ params["limit"] = limit
270
+
271
+ response = await self._make_request(
272
+ http.HTTPMethod.GET,
273
+ "/task/list",
274
+ params=params,
275
+ response_models=self.TASK_LIST_MODELS,
276
+ )
277
+ return cast(APIResponse[Optional[TaskListResponse]], response)